diff options
Diffstat (limited to 'themes')
30 files changed, 887 insertions, 834 deletions
diff --git a/themes/dist/output.js b/themes/dist/output.js index 079be8d..e814b4e 100644 --- a/themes/dist/output.js +++ b/themes/dist/output.js @@ -1,5 +1,4 @@ - - +// include: shell.js // The Module object: Our interface to the outside world. We import // and export values on it. There are various ways Module can be used: // 1. Not defined. We create it here @@ -15,13 +14,9 @@ // can continue to use Module afterwards as well. var Module = typeof Module != 'undefined' ? Module : {}; -// See https://caniuse.com/mdn-javascript_builtins_object_assign - -// See https://caniuse.com/mdn-javascript_builtins_bigint64array - // --pre-jses are emitted after the Module integration code, so that they can // refer to Module (if they choose; they can also define Module) -// {{PRE_JSES}} + // Sometimes an existing Module object exists with properties // meant to overwrite the default module functionality. Here @@ -84,32 +79,26 @@ function logExceptionOnExit(e) { if (ENVIRONMENT_IS_NODE) { if (typeof process == 'undefined' || !process.release || process.release.name !== 'node') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + // `require()` is no-op in an ESM module, use `createRequire()` to construct + // the require()` function. This is only necessary for multi-environment + // builds, `-sENVIRONMENT=node` emits a static import declaration instead. + // TODO: Swap all `require()`'s with `import()`'s? + // These modules will usually be used on Node.js. Load them eagerly to avoid + // the complexity of lazy-loading. + var fs = require('fs'); + var nodePath = require('path'); + if (ENVIRONMENT_IS_WORKER) { - scriptDirectory = require('path').dirname(scriptDirectory) + '/'; + scriptDirectory = nodePath.dirname(scriptDirectory) + '/'; } else { scriptDirectory = __dirname + '/'; } // include: node_shell_read.js - - -// These modules will usually be used on Node.js. Load them eagerly to avoid -// the complexity of lazy-loading. However, for now we must guard on require() -// actually existing: if the JS is put in a .mjs file (ES6 module) and run on -// node, then we'll detect node as the environment and get here, but require() -// does not exist (since ES6 modules should use |import|). If the code actually -// uses the node filesystem then it will crash, of course, but in the case of -// code that never uses it we don't want to crash here, so the guarding if lets -// such code work properly. See discussion in -// https://github.com/emscripten-core/emscripten/pull/17851 -var fs, nodePath; -if (typeof require === 'function') { - fs = require('fs'); - nodePath = require('path'); -} - read_ = (filename, binary) => { - filename = nodePath['normalize'](filename); + // We need to re-wrap `file://` strings to URLs. Normalizing isn't + // necessary in that case, the path should already be absolute. + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); return fs.readFileSync(filename, binary ? undefined : 'utf8'); }; @@ -123,7 +112,8 @@ readBinary = (filename) => { }; readAsync = (filename, onload, onerror) => { - filename = nodePath['normalize'](filename); + // See the comment in the `read_` function. + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); fs.readFile(filename, function(err, data) { if (err) onerror(err); else onload(data.buffer); @@ -153,7 +143,10 @@ readAsync = (filename, onload, onerror) => { // not be needed with node v15 and about because it is now the default // behaviour: // See https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode - process['on']('unhandledRejection', function(reason) { throw reason; }); + var nodeMajor = process.version.match(/^v(\d+)\./)[1]; + if (nodeMajor < 15) { + process['on']('unhandledRejection', function(reason) { throw reason; }); + } quit_ = (status, toThrow) => { if (keepRuntimeAlive()) { @@ -191,6 +184,10 @@ if (ENVIRONMENT_IS_SHELL) { setTimeout(() => onload(readBinary(f)), 0); }; + if (typeof clearTimeout == 'undefined') { + globalThis.clearTimeout = (id) => {}; + } + if (typeof scriptArgs != 'undefined') { arguments_ = scriptArgs; } else if (typeof arguments != 'undefined') { @@ -240,9 +237,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { // be done differently. { // include: web_or_worker_shell_read.js - - - read_ = (url) => { +read_ = (url) => { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.send(null); @@ -327,110 +322,8 @@ var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js'; assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at build time. Add 'shell' to `-sENVIRONMENT` to enable."); - - -var STACK_ALIGN = 16; -var POINTER_SIZE = 4; - -function getNativeTypeSize(type) { - switch (type) { - case 'i1': case 'i8': case 'u8': return 1; - case 'i16': case 'u16': return 2; - case 'i32': case 'u32': return 4; - case 'i64': case 'u64': return 8; - case 'float': return 4; - case 'double': return 8; - default: { - if (type[type.length - 1] === '*') { - return POINTER_SIZE; - } - if (type[0] === 'i') { - const bits = Number(type.substr(1)); - assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type); - return bits / 8; - } - return 0; - } - } -} - -// include: runtime_debug.js - - -function legacyModuleProp(prop, newName) { - if (!Object.getOwnPropertyDescriptor(Module, prop)) { - Object.defineProperty(Module, prop, { - configurable: true, - get: function() { - abort('Module.' + prop + ' has been replaced with plain ' + newName + ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)'); - } - }); - } -} - -function ignoredModuleProp(prop) { - if (Object.getOwnPropertyDescriptor(Module, prop)) { - abort('`Module.' + prop + '` was supplied but `' + prop + '` not included in INCOMING_MODULE_JS_API'); - } -} - -// forcing the filesystem exports a few things by default -function isExportedByForceFilesystem(name) { - return name === 'FS_createPath' || - name === 'FS_createDataFile' || - name === 'FS_createPreloadedFile' || - name === 'FS_unlink' || - name === 'addRunDependency' || - // The old FS has some functionality that WasmFS lacks. - name === 'FS_createLazyFile' || - name === 'FS_createDevice' || - name === 'removeRunDependency'; -} - -function missingLibrarySymbol(sym) { - if (typeof globalThis !== 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { - Object.defineProperty(globalThis, sym, { - configurable: true, - get: function() { - // Can't `abort()` here because it would break code that does runtime - // checks. e.g. `if (typeof SDL === 'undefined')`. - var msg = '`' + sym + '` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line'; - // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in - // library.js, which means $name for a JS name with no prefix, or name - // for a JS name like _name. - var librarySymbol = sym; - if (!librarySymbol.startsWith('_')) { - librarySymbol = '$' + sym; - } - msg += " (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=" + librarySymbol + ")"; - if (isExportedByForceFilesystem(sym)) { - msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; - } - warnOnce(msg); - return undefined; - } - }); - } -} - -function unexportedRuntimeSymbol(sym) { - if (!Object.getOwnPropertyDescriptor(Module, sym)) { - Object.defineProperty(Module, sym, { - configurable: true, - get: function() { - var msg = "'" + sym + "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)"; - if (isExportedByForceFilesystem(sym)) { - msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; - } - abort(msg); - } - }); - } -} - -// end include: runtime_debug.js - - +// end include: shell.js +// include: preamble.js // === Preamble library stuff === // Documentation for the public APIs defined in this file must be updated in: @@ -477,8 +370,6 @@ function assert(condition, text) { // builds with assertions. // include: runtime_strings.js - - // runtime_strings.js: String related runtime functions that are part of both // MINIMAL_RUNTIME and regular runtime. @@ -522,7 +413,7 @@ function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) { if ((u0 & 0xF0) == 0xE0) { u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; } else { - if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!'); + if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!'); u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); } @@ -612,7 +503,7 @@ function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) { heap[outIdx++] = 0x80 | (u & 63); } else { if (outIdx + 3 >= endIdx) break; - if (u > 0x10FFFF) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).'); + if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).'); heap[outIdx++] = 0xF0 | (u >> 18); heap[outIdx++] = 0x80 | ((u >> 12) & 63); heap[outIdx++] = 0x80 | ((u >> 6) & 63); @@ -670,8 +561,6 @@ function lengthBytesUTF8(str) { // Memory management var HEAP, -/** @type {!ArrayBuffer} */ - buffer, /** @type {!Int8Array} */ HEAP8, /** @type {!Uint8Array} */ @@ -689,32 +578,26 @@ var HEAP, /** @type {!Float64Array} */ HEAPF64; -function updateGlobalBufferAndViews(buf) { - buffer = buf; - Module['HEAP8'] = HEAP8 = new Int8Array(buf); - Module['HEAP16'] = HEAP16 = new Int16Array(buf); - Module['HEAP32'] = HEAP32 = new Int32Array(buf); - Module['HEAPU8'] = HEAPU8 = new Uint8Array(buf); - Module['HEAPU16'] = HEAPU16 = new Uint16Array(buf); - Module['HEAPU32'] = HEAPU32 = new Uint32Array(buf); - Module['HEAPF32'] = HEAPF32 = new Float32Array(buf); - Module['HEAPF64'] = HEAPF64 = new Float64Array(buf); +function updateMemoryViews() { + var b = wasmMemory.buffer; + Module['HEAP8'] = HEAP8 = new Int8Array(b); + Module['HEAP16'] = HEAP16 = new Int16Array(b); + Module['HEAP32'] = HEAP32 = new Int32Array(b); + Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); + Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); + Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); + Module['HEAPF32'] = HEAPF32 = new Float32Array(b); + Module['HEAPF64'] = HEAPF64 = new Float64Array(b); } -var STACK_SIZE = 5242880; -if (Module['STACK_SIZE']) assert(STACK_SIZE === Module['STACK_SIZE'], 'the stack size can no longer be determined at runtime') - -var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;legacyModuleProp('INITIAL_MEMORY', 'INITIAL_MEMORY'); +assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time') -assert(INITIAL_MEMORY >= STACK_SIZE, 'INITIAL_MEMORY should be larger than STACK_SIZE, was ' + INITIAL_MEMORY + '! (STACK_SIZE=' + STACK_SIZE + ')'); - -// check for full engine support (use string 'subarray' to avoid closure compiler confusion) assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined, 'JS engine does not provide full typed array support'); -// If memory is defined in wasm, the user can't provide it. +// If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally'); -assert(INITIAL_MEMORY == 16777216, 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically'); +assert(!Module['INITIAL_MEMORY'], 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically'); // include: runtime_init_table.js // In regular non-RELOCATABLE mode the table is exported @@ -724,12 +607,16 @@ var wasmTable; // end include: runtime_init_table.js // include: runtime_stack_check.js - - // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. function writeStackCookie() { var max = _emscripten_stack_get_end(); assert((max & 3) == 0); + // If the stack ends at address zero we write our cookies 4 bytes into the + // stack. This prevents interference with the (separate) address-zero check + // below. + if (max == 0) { + max += 4; + } // The stack grow downwards towards _emscripten_stack_get_end. // We write cookies to the final two words in the stack and detect if they are // ever overwritten. @@ -742,19 +629,23 @@ function writeStackCookie() { function checkStackCookie() { if (ABORT) return; var max = _emscripten_stack_get_end(); + // See writeStackCookie(). + if (max == 0) { + max += 4; + } var cookie1 = HEAPU32[((max)>>2)]; var cookie2 = HEAPU32[(((max)+(4))>>2)]; if (cookie1 != 0x2135467 || cookie2 != 0x89BACDFE) { - abort('Stack overflow! Stack cookie has been overwritten at 0x' + max.toString(16) + ', expected hex dwords 0x89BACDFE and 0x2135467, but received 0x' + cookie2.toString(16) + ' 0x' + cookie1.toString(16)); + abort('Stack overflow! Stack cookie has been overwritten at ' + ptrToString(max) + ', expected hex dwords 0x89BACDFE and 0x2135467, but received ' + ptrToString(cookie2) + ' ' + ptrToString(cookie1)); } // Also test the global address 0 for integrity. - if (HEAPU32[0] !== 0x63736d65 /* 'emsc' */) abort('Runtime error: The application has corrupted its heap memory area (address zero)!'); + if (HEAPU32[0] !== 0x63736d65 /* 'emsc' */) { + abort('Runtime error: The application has corrupted its heap memory area (address zero)!'); + } } // end include: runtime_stack_check.js // include: runtime_assertions.js - - // Endianness check (function() { var h16 = new Int16Array(1); @@ -777,14 +668,12 @@ function keepRuntimeAlive() { } function preRun() { - if (Module['preRun']) { if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; while (Module['preRun'].length) { addOnPreRun(Module['preRun'].shift()); } } - callRuntimeCallbacks(__ATPRERUN__); } @@ -837,8 +726,6 @@ function addOnPostRun(cb) { } // include: runtime_math.js - - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround @@ -971,11 +858,7 @@ function abort(what) { throw e; } -// {{MEM_INITIALIZER}} - // include: memoryprofiler.js - - // end include: memoryprofiler.js // show errors on likely calls to FS when it was not included var FS = { @@ -998,8 +881,6 @@ Module['FS_createDataFile'] = FS.createDataFile; Module['FS_createPreloadedFile'] = FS.createPreloadedFile; // include: URIUtils.js - - // Prefix of data URIs emitted by SINGLE_FILE and related options. var dataURIPrefix = 'data:application/octet-stream;base64,'; @@ -1090,8 +971,8 @@ function getBinaryPromise() { function createWasm() { // prepare imports var info = { - 'env': asmLibraryArg, - 'wasi_snapshot_preview1': asmLibraryArg, + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, }; // Load the wasm module and create an instance of using native support in the JS engine. // handle a generated wasm instance, receiving its exports and @@ -1108,7 +989,7 @@ function createWasm() { // mode. // TODO(sbc): Read INITIAL_MEMORY out of the wasm file in post-link mode. //assert(wasmMemory.buffer.byteLength === 16777216); - updateGlobalBufferAndViews(wasmMemory.buffer); + updateMemoryViews(); wasmTable = Module['asm']['__indirect_function_table']; assert(wasmTable, "table not found in wasm exports"); @@ -1118,7 +999,7 @@ function createWasm() { removeRunDependency('wasm-instantiate'); } - // we can't run yet (except in a pthread, where we have a custom sync instantiator) + // wait for the pthread pool (if any) addRunDependency('wasm-instantiate'); // Prefer streaming instantiation if available. @@ -1211,16 +1092,100 @@ function createWasm() { var tempDouble; var tempI64; -// === Body === +// include: runtime_debug.js +function legacyModuleProp(prop, newName) { + if (!Object.getOwnPropertyDescriptor(Module, prop)) { + Object.defineProperty(Module, prop, { + configurable: true, + get: function() { + abort('Module.' + prop + ' has been replaced with plain ' + newName + ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)'); + } + }); + } +} -var ASM_CONSTS = { - -}; +function ignoredModuleProp(prop) { + if (Object.getOwnPropertyDescriptor(Module, prop)) { + abort('`Module.' + prop + '` was supplied but `' + prop + '` not included in INCOMING_MODULE_JS_API'); + } +} + +// forcing the filesystem exports a few things by default +function isExportedByForceFilesystem(name) { + return name === 'FS_createPath' || + name === 'FS_createDataFile' || + name === 'FS_createPreloadedFile' || + name === 'FS_unlink' || + name === 'addRunDependency' || + // The old FS has some functionality that WasmFS lacks. + name === 'FS_createLazyFile' || + name === 'FS_createDevice' || + name === 'removeRunDependency'; +} +function missingGlobal(sym, msg) { + if (typeof globalThis !== 'undefined') { + Object.defineProperty(globalThis, sym, { + configurable: true, + get: function() { + warnOnce('`' + sym + '` is not longer defined by emscripten. ' + msg); + return undefined; + } + }); + } +} + +missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer'); + +function missingLibrarySymbol(sym) { + if (typeof globalThis !== 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { + Object.defineProperty(globalThis, sym, { + configurable: true, + get: function() { + // Can't `abort()` here because it would break code that does runtime + // checks. e.g. `if (typeof SDL === 'undefined')`. + var msg = '`' + sym + '` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line'; + // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in + // library.js, which means $name for a JS name with no prefix, or name + // for a JS name like _name. + var librarySymbol = sym; + if (!librarySymbol.startsWith('_')) { + librarySymbol = '$' + sym; + } + msg += " (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=" + librarySymbol + ")"; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + warnOnce(msg); + return undefined; + } + }); + } + // Any symbol that is not included from the JS libary is also (by definttion) + // not exported on the Module object. + unexportedRuntimeSymbol(sym); +} +function unexportedRuntimeSymbol(sym) { + if (!Object.getOwnPropertyDescriptor(Module, sym)) { + Object.defineProperty(Module, sym, { + configurable: true, + get: function() { + var msg = "'" + sym + "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)"; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + abort(msg); + } + }); + } +} +// end include: runtime_debug.js +// === Body === +// end include: preamble.js /** @constructor */ function ExitStatus(status) { @@ -1257,6 +1222,11 @@ var ASM_CONSTS = { return null; } + function ptrToString(ptr) { + assert(typeof ptr === 'number'); + return '0x' + ptr.toString(16).padStart(8, '0'); + } + /** * @param {number} ptr @@ -1541,6 +1511,7 @@ var ASM_CONSTS = { } var wasmTableMirror = []; + function getWasmTableEntry(funcPtr) { var func = wasmTableMirror[funcPtr]; if (!func) { @@ -1568,13 +1539,14 @@ var ASM_CONSTS = { } function emscripten_realloc_buffer(size) { + var b = wasmMemory.buffer; try { // round size grow request up to wasm page size (fixed 64KB per spec) - wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16); // .grow() takes a delta compared to the previous size - updateGlobalBufferAndViews(wasmMemory.buffer); + wasmMemory.grow((size - b.byteLength + 65535) >>> 16); // .grow() takes a delta compared to the previous size + updateMemoryViews(); return 1 /*success*/; } catch(e) { - err('emscripten_realloc_buffer: Attempted to grow heap from ' + buffer.byteLength + ' bytes to ' + size + ' bytes, but got error: ' + e); + err('emscripten_realloc_buffer: Attempted to grow heap from ' + b.byteLength + ' bytes to ' + size + ' bytes, but got error: ' + e); } // implicit 0 return to save code size (caller will cast "undefined" into 0 // anyhow) @@ -1633,6 +1605,7 @@ var ASM_CONSTS = { return false; } + function findCanvasEventTarget(target) { return findEventTarget(target); } function _emscripten_set_canvas_element_size(target, width, height) { var canvas = findCanvasEventTarget(target); @@ -1642,6 +1615,9 @@ var ASM_CONSTS = { return 0; } + + + function fillMouseEventData(eventStruct, e, target) { assert(eventStruct % 4 == 0); HEAPF64[((eventStruct)>>3)] = e.timeStamp; @@ -1668,13 +1644,13 @@ var ASM_CONSTS = { HEAP32[idx + 14] = e.clientY - rect.top; } + + function registerMouseEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.mouseEvent) JSEvents.mouseEvent = _malloc( 72 ); target = findEventTarget(target); - var mouseEventHandlerFunc = function(ev) { - var e = ev || event; - + var mouseEventHandlerFunc = function(e = event) { // TODO: Make this access thread safe, or this could update live while app is reading it. fillMouseEventData(JSEvents.mouseEvent, e, target); @@ -1696,13 +1672,14 @@ var ASM_CONSTS = { return 0; } + + function registerUiEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.uiEvent) JSEvents.uiEvent = _malloc( 36 ); target = findEventTarget(target); - var uiEventHandlerFunc = function(ev) { - var e = ev || event; + var uiEventHandlerFunc = function(e = event) { if (e.target != target) { // Never take ui events such as scroll via a 'bubbled' route, but always from the direct element that // was targeted. Otherwise e.g. if app logs a message in response to a page scroll, the Emscripten log @@ -1760,25 +1737,18 @@ var ASM_CONSTS = { openRequest.onsuccess = (event) => onsuccess(event.target.result); openRequest.onerror = (error) => onerror(error); },staticInit:function() { - var isMainThread = true; - var onsuccess = (db) => { Fetch.dbInstance = db; - - if (isMainThread) { - removeRunDependency('library_fetch_init'); - } + removeRunDependency('library_fetch_init'); }; + var onerror = () => { Fetch.dbInstance = false; - - if (isMainThread) { - removeRunDependency('library_fetch_init'); - } + removeRunDependency('library_fetch_init'); }; - Fetch.openDatabase('emscripten_filesystem', 1, onsuccess, onerror); - if (typeof ENVIRONMENT_IS_FETCH_WORKER == 'undefined' || !ENVIRONMENT_IS_FETCH_WORKER) addRunDependency('library_fetch_init'); + addRunDependency('library_fetch_init'); + Fetch.openDatabase('emscripten_filesystem', 1, onsuccess, onerror); }}; function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) { @@ -1957,6 +1927,12 @@ var ASM_CONSTS = { if (e instanceof ExitStatus || e == 'unwind') { return EXITSTATUS; } + checkStackCookie(); + if (e instanceof WebAssembly.RuntimeError) { + if (_emscripten_stack_get_current() <= 0) { + err('Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to ' + 65536 + ')'); + } + } quit_(1, e); } function callUserCallback(func) { @@ -2092,6 +2068,7 @@ var ASM_CONSTS = { onerror(fetch, 0, e); } } + function _emscripten_start_fetch(fetch, successcb, errorcb, progresscb, readystatechangecb) { // Avoid shutting down the runtime since we want to wait for the async // response. @@ -2238,6 +2215,7 @@ var ASM_CONSTS = { // Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted. return !!(ctx.multiDrawWebgl = ctx.getExtension('WEBGL_multi_draw')); } + var GL = {counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode) { if (!GL.lastError) { GL.lastError = errorCode; @@ -2392,7 +2370,7 @@ var ASM_CONSTS = { canvas.getContext = fixedGetContext; } - var ctx = + var ctx = (webGLContextAttributes.majorVersion > 1) ? canvas.getContext("webgl2", webGLContextAttributes) @@ -2492,7 +2470,10 @@ var ASM_CONSTS = { }); }}; + var __emscripten_webgl_power_preferences = ['default', 'low-power', 'high-performance']; + + function _emscripten_webgl_do_create_context(target, attributes) { assert(attributes); var a = attributes >> 2; @@ -2569,6 +2550,10 @@ var ASM_CONSTS = { assert(hi === (hi|0)); // hi should be a i32 return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN; } + + + + function _fd_seek(fd, offset_low, offset_high, whence, newOffset) { return 70; } @@ -2584,12 +2569,15 @@ var ASM_CONSTS = { buffer.push(curr); } } + function flush_NO_FILESYSTEM() { // flush anything remaining in the buffers during shutdown _fflush(0); if (printCharBuffers[1].length) printChar(1, 10); if (printCharBuffers[2].length) printChar(2, 10); } + + function _fd_write(fd, iov, iovcnt, pnum) { // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0 var num = 0; @@ -2809,11 +2797,13 @@ var ASM_CONSTS = { HEAP32[(((buffers)+(i*4))>>2)] = id; } } + function _glGenBuffers(n, buffers) { __glGenObject(n, buffers, 'createBuffer', GL.buffers ); } + function _glGenVertexArrays(n, arrays) { __glGenObject(n, arrays, 'createVertexArray', GL.vaos ); @@ -2918,6 +2908,7 @@ var ASM_CONSTS = { function webglGetLeftBracePos(name) { return name.slice(-1) == ']' && name.lastIndexOf('['); } + function webglPrepareUniformLocationsBeforeFirstUse(program) { var uniformLocsById = program.uniformLocsById, // Maps GLuint -> WebGLUniformLocation uniformSizeAndIdsByName = program.uniformSizeAndIdsByName, // Maps name -> [uniform array length, GLuint] @@ -2957,6 +2948,8 @@ var ASM_CONSTS = { } } } + + function _glGetUniformLocation(program, name) { name = UTF8ToString(name); @@ -3035,6 +3028,7 @@ var ASM_CONSTS = { } var miniTempWebGLFloatBuffers = []; + function _glUniformMatrix4fv(location, count, transpose, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. @@ -3104,6 +3098,7 @@ var ASM_CONSTS = { GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr); } + function _proc_exit(code) { EXITSTATUS = code; if (!keepRuntimeAlive()) { @@ -3134,12 +3129,10 @@ var miniTempWebGLFloatBuffersStorage = new Float32Array(288); miniTempWebGLFloatBuffers[i] = miniTempWebGLFloatBuffersStorage.subarray(0, i+1); } ; -var ASSERTIONS = true; - function checkIncomingModuleAPI() { ignoredModuleProp('fetchSettings'); } -var asmLibraryArg = { +var wasmImports = { "_emscripten_fetch_free": __emscripten_fetch_free, "_localtime_js": __localtime_js, "_tzset_js": __tzset_js, @@ -3199,112 +3192,58 @@ var asmLibraryArg = { }; var asm = createWasm(); /** @type {function(...*):?} */ -var ___wasm_call_ctors = Module["___wasm_call_ctors"] = createExportWrapper("__wasm_call_ctors"); - +var ___wasm_call_ctors = createExportWrapper("__wasm_call_ctors"); /** @type {function(...*):?} */ var _main = Module["_main"] = createExportWrapper("main"); - /** @type {function(...*):?} */ -var _malloc = Module["_malloc"] = createExportWrapper("malloc"); - +var _free = createExportWrapper("free"); /** @type {function(...*):?} */ -var _free = Module["_free"] = createExportWrapper("free"); - +var _malloc = createExportWrapper("malloc"); /** @type {function(...*):?} */ -var ___errno_location = Module["___errno_location"] = createExportWrapper("__errno_location"); - +var ___errno_location = createExportWrapper("__errno_location"); /** @type {function(...*):?} */ var _fflush = Module["_fflush"] = createExportWrapper("fflush"); - /** @type {function(...*):?} */ -var _emscripten_stack_init = Module["_emscripten_stack_init"] = function() { - return (_emscripten_stack_init = Module["_emscripten_stack_init"] = Module["asm"]["emscripten_stack_init"]).apply(null, arguments); +var _emscripten_stack_init = function() { + return (_emscripten_stack_init = Module["asm"]["emscripten_stack_init"]).apply(null, arguments); }; /** @type {function(...*):?} */ -var _emscripten_stack_get_free = Module["_emscripten_stack_get_free"] = function() { - return (_emscripten_stack_get_free = Module["_emscripten_stack_get_free"] = Module["asm"]["emscripten_stack_get_free"]).apply(null, arguments); +var _emscripten_stack_get_free = function() { + return (_emscripten_stack_get_free = Module["asm"]["emscripten_stack_get_free"]).apply(null, arguments); }; /** @type {function(...*):?} */ -var _emscripten_stack_get_base = Module["_emscripten_stack_get_base"] = function() { - return (_emscripten_stack_get_base = Module["_emscripten_stack_get_base"] = Module["asm"]["emscripten_stack_get_base"]).apply(null, arguments); +var _emscripten_stack_get_base = function() { + return (_emscripten_stack_get_base = Module["asm"]["emscripten_stack_get_base"]).apply(null, arguments); }; /** @type {function(...*):?} */ -var _emscripten_stack_get_end = Module["_emscripten_stack_get_end"] = function() { - return (_emscripten_stack_get_end = Module["_emscripten_stack_get_end"] = Module["asm"]["emscripten_stack_get_end"]).apply(null, arguments); +var _emscripten_stack_get_end = function() { + return (_emscripten_stack_get_end = Module["asm"]["emscripten_stack_get_end"]).apply(null, arguments); }; /** @type {function(...*):?} */ -var stackSave = Module["stackSave"] = createExportWrapper("stackSave"); - +var stackSave = createExportWrapper("stackSave"); /** @type {function(...*):?} */ -var stackRestore = Module["stackRestore"] = createExportWrapper("stackRestore"); - +var stackRestore = createExportWrapper("stackRestore"); +/** @type {function(...*):?} */ +var stackAlloc = createExportWrapper("stackAlloc"); /** @type {function(...*):?} */ -var stackAlloc = Module["stackAlloc"] = createExportWrapper("stackAlloc"); +var _emscripten_stack_get_current = function() { + return (_emscripten_stack_get_current = Module["asm"]["emscripten_stack_get_current"]).apply(null, arguments); +}; /** @type {function(...*):?} */ var dynCall_jiji = Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji"); - - - +// include: postamble.js // === Auto-generated postamble setup entry stuff === - -var unexportedRuntimeSymbols = [ - 'run', - 'UTF8ArrayToString', - 'UTF8ToString', - 'stringToUTF8Array', - 'stringToUTF8', - 'lengthBytesUTF8', - 'addOnPreRun', - 'addOnInit', - 'addOnPreMain', - 'addOnExit', - 'addOnPostRun', - 'addRunDependency', - 'removeRunDependency', - 'FS_createFolder', - 'FS_createPath', - 'FS_createDataFile', - 'FS_createPreloadedFile', - 'FS_createLazyFile', - 'FS_createLink', - 'FS_createDevice', - 'FS_unlink', - 'getLEB', - 'getFunctionTables', - 'alignFunctionTables', - 'registerFunctions', - 'prettyPrint', - 'getCompilerSetting', - 'out', - 'err', - 'callMain', - 'abort', - 'keepRuntimeAlive', - 'wasmMemory', - 'stackAlloc', - 'stackSave', - 'stackRestore', - 'getTempRet0', - 'setTempRet0', - 'writeStackCookie', - 'checkStackCookie', - 'ptrToString', +var missingLibrarySymbols = [ 'zeroMemory', 'stringToNewUTF8', - 'exitJS', - 'getHeapMax', - 'emscripten_realloc_buffer', - 'ENV', - 'ERRNO_CODES', - 'ERRNO_MESSAGES', 'setErrNo', 'inetPton4', 'inetNtop4', @@ -3312,19 +3251,11 @@ var unexportedRuntimeSymbols = [ 'inetNtop6', 'readSockaddr', 'writeSockaddr', - 'DNS', 'getHostByName', - 'Protocols', - 'Sockets', 'getRandomDevice', - 'warnOnce', 'traverseStack', - 'UNWIND_CACHE', 'convertPCtoSourceLocation', - 'readAsmConstArgsArray', - 'readAsmConstArgs', - 'mainThreadEM_ASM', - 'jstoi_q', + 'readEmAsmArgs', 'jstoi_s', 'getExecutableName', 'listenOnce', @@ -3332,25 +3263,27 @@ var unexportedRuntimeSymbols = [ 'dynCallLegacy', 'getDynCaller', 'dynCall', - 'handleException', 'runtimeKeepalivePush', 'runtimeKeepalivePop', - 'callUserCallback', 'maybeExit', 'safeSetTimeout', 'asmjsMangle', 'asyncLoad', 'alignMemory', 'mmapAlloc', + 'handleAllocator', + 'getNativeTypeSize', + 'STACK_SIZE', + 'STACK_ALIGN', + 'POINTER_SIZE', + 'ASSERTIONS', 'writeI53ToI64', 'writeI53ToI64Clamped', 'writeI53ToI64Signaling', 'writeI53ToU64Clamped', 'writeI53ToU64Signaling', - 'readI53FromI64', 'readI53FromU64', 'convertI32PairToI53', - 'convertI32PairToI53Checked', 'convertU32PairToI53', 'getCFunc', 'ccall', @@ -3359,10 +3292,9 @@ var unexportedRuntimeSymbols = [ 'sigToWasmTypes', 'generateFuncType', 'convertJsFunctionToWasm', - 'freeTableIndexes', - 'functionsInTableMap', 'getEmptyTableSlot', 'updateTableMap', + 'getFunctionAddress', 'addFunction', 'removeFunction', 'reallyNegative', @@ -3370,40 +3302,24 @@ var unexportedRuntimeSymbols = [ 'strLen', 'reSign', 'formatString', - 'setValue', - 'getValue', - 'PATH', - 'PATH_FS', 'intArrayFromString', 'intArrayToString', 'AsciiToString', 'stringToAscii', - 'UTF16Decoder', 'UTF16ToString', 'stringToUTF16', 'lengthBytesUTF16', 'UTF32ToString', 'stringToUTF32', 'lengthBytesUTF32', - 'allocateUTF8', 'allocateUTF8OnStack', 'writeStringToMemory', 'writeArrayToMemory', 'writeAsciiToMemory', - 'SYSCALLS', 'getSocketFromFD', 'getSocketAddress', - 'JSEvents', 'registerKeyEventCallback', - 'specialHTMLTargets', - 'maybeCStringToJsString', - 'findEventTarget', - 'findCanvasEventTarget', - 'getBoundingClientRect', - 'fillMouseEventData', - 'registerMouseEventCallback', 'registerWheelEventCallback', - 'registerUiEventCallback', 'registerFocusEventCallback', 'fillDeviceOrientationEventData', 'registerDeviceOrientationEventCallback', @@ -3420,8 +3336,6 @@ var unexportedRuntimeSymbols = [ 'hideEverythingExceptGivenElement', 'restoreHiddenElements', 'setLetterbox', - 'currentFullscreenStrategy', - 'restoreOldWindowedStyle', 'softFullscreenResizeWebGLRenderTarget', 'doRequestFullscreen', 'fillPointerlockChangeEventData', @@ -3443,213 +3357,151 @@ var unexportedRuntimeSymbols = [ 'demangleAll', 'jsStackTrace', 'stackTrace', - 'ExitStatus', 'getEnvStrings', 'checkWasiClock', - 'flush_NO_FILESYSTEM', - 'dlopenMissingError', 'createDyncallWrapper', 'setImmediateWrapped', 'clearImmediateWrapped', 'polyfillSetImmediate', - 'uncaughtExceptionCount', - 'exceptionLast', - 'exceptionCaught', + 'newNativePromise', + 'getPromise', 'ExceptionInfo', 'exception_addRef', 'exception_decRef', - 'Browser', 'setMainLoop', - 'wget', - 'FS', - 'MEMFS', - 'TTY', - 'PIPEFS', - 'SOCKFS', '_setNetworkCallback', - 'tempFixedLengthArray', - 'miniTempWebGLFloatBuffers', 'heapObjectForWebGLType', 'heapAccessShiftForWebGLHeap', - 'GL', 'emscriptenWebGLGet', 'computeUnpackAlignedImageSize', 'emscriptenWebGLGetTexPixelData', 'emscriptenWebGLGetUniform', - 'webglGetUniformLocation', - 'webglPrepareUniformLocationsBeforeFirstUse', - 'webglGetLeftBracePos', 'emscriptenWebGLGetVertexAttrib', 'emscriptenWebGLGetBufferBinding', 'emscriptenWebGLValidateMapBufferTarget', 'writeGLArray', - 'AL', 'SDL_unicode', 'SDL_ttfContext', 'SDL_audio', + 'GLFW_Window', + 'runAndAbortIfError', + 'emscriptenWebGLGetIndexed', + 'ALLOC_NORMAL', + 'ALLOC_STACK', + 'allocate', +]; +missingLibrarySymbols.forEach(missingLibrarySymbol) + +var unexportedSymbols = [ + 'run', + 'UTF8ArrayToString', + 'UTF8ToString', + 'stringToUTF8Array', + 'stringToUTF8', + 'lengthBytesUTF8', + 'addOnPreRun', + 'addOnInit', + 'addOnPreMain', + 'addOnExit', + 'addOnPostRun', + 'addRunDependency', + 'removeRunDependency', + 'FS_createFolder', + 'FS_createPath', + 'FS_createDataFile', + 'FS_createPreloadedFile', + 'FS_createLazyFile', + 'FS_createLink', + 'FS_createDevice', + 'FS_unlink', + 'out', + 'err', + 'callMain', + 'abort', + 'keepRuntimeAlive', + 'wasmMemory', + 'stackAlloc', + 'stackSave', + 'stackRestore', + 'getTempRet0', + 'setTempRet0', + 'writeStackCookie', + 'checkStackCookie', + 'ptrToString', + 'exitJS', + 'getHeapMax', + 'emscripten_realloc_buffer', + 'ENV', + 'ERRNO_CODES', + 'ERRNO_MESSAGES', + 'DNS', + 'Protocols', + 'Sockets', + 'timers', + 'warnOnce', + 'UNWIND_CACHE', + 'readEmAsmArgsArray', + 'jstoi_q', + 'handleException', + 'callUserCallback', + 'readI53FromI64', + 'convertI32PairToI53Checked', + 'freeTableIndexes', + 'functionsInTableMap', + 'setValue', + 'getValue', + 'PATH', + 'PATH_FS', + 'UTF16Decoder', + 'allocateUTF8', + 'SYSCALLS', + 'JSEvents', + 'specialHTMLTargets', + 'maybeCStringToJsString', + 'findEventTarget', + 'findCanvasEventTarget', + 'getBoundingClientRect', + 'fillMouseEventData', + 'registerMouseEventCallback', + 'registerUiEventCallback', + 'currentFullscreenStrategy', + 'restoreOldWindowedStyle', + 'ExitStatus', + 'flush_NO_FILESYSTEM', + 'dlopenMissingError', + 'promiseMap', + 'uncaughtExceptionCount', + 'exceptionLast', + 'exceptionCaught', + 'Browser', + 'wget', + 'FS', + 'MEMFS', + 'TTY', + 'PIPEFS', + 'SOCKFS', + 'tempFixedLengthArray', + 'miniTempWebGLFloatBuffers', + 'GL', + 'webglGetUniformLocation', + 'webglPrepareUniformLocationsBeforeFirstUse', + 'webglGetLeftBracePos', + 'AL', 'SDL', 'SDL_gfx', 'GLUT', 'EGL', - 'GLFW_Window', 'GLFW', 'GLEW', 'IDBStore', - 'runAndAbortIfError', - 'emscriptenWebGLGetIndexed', - 'ALLOC_NORMAL', - 'ALLOC_STACK', - 'allocate', 'Fetch', 'fetchDeleteCachedData', 'fetchLoadCachedData', 'fetchCacheData', 'fetchXHR', ]; -unexportedRuntimeSymbols.forEach(unexportedRuntimeSymbol); -var missingLibrarySymbols = [ - 'ptrToString', - 'zeroMemory', - 'stringToNewUTF8', - 'setErrNo', - 'inetPton4', - 'inetNtop4', - 'inetPton6', - 'inetNtop6', - 'readSockaddr', - 'writeSockaddr', - 'getHostByName', - 'getRandomDevice', - 'traverseStack', - 'convertPCtoSourceLocation', - 'readAsmConstArgs', - 'mainThreadEM_ASM', - 'jstoi_s', - 'getExecutableName', - 'listenOnce', - 'autoResumeAudioContext', - 'dynCallLegacy', - 'getDynCaller', - 'dynCall', - 'runtimeKeepalivePush', - 'runtimeKeepalivePop', - 'maybeExit', - 'safeSetTimeout', - 'asmjsMangle', - 'asyncLoad', - 'alignMemory', - 'mmapAlloc', - 'writeI53ToI64', - 'writeI53ToI64Clamped', - 'writeI53ToI64Signaling', - 'writeI53ToU64Clamped', - 'writeI53ToU64Signaling', - 'readI53FromU64', - 'convertI32PairToI53', - 'convertU32PairToI53', - 'getCFunc', - 'ccall', - 'cwrap', - 'uleb128Encode', - 'sigToWasmTypes', - 'generateFuncType', - 'convertJsFunctionToWasm', - 'getEmptyTableSlot', - 'updateTableMap', - 'addFunction', - 'removeFunction', - 'reallyNegative', - 'unSign', - 'strLen', - 'reSign', - 'formatString', - 'intArrayFromString', - 'intArrayToString', - 'AsciiToString', - 'stringToAscii', - 'UTF16ToString', - 'stringToUTF16', - 'lengthBytesUTF16', - 'UTF32ToString', - 'stringToUTF32', - 'lengthBytesUTF32', - 'allocateUTF8OnStack', - 'writeStringToMemory', - 'writeArrayToMemory', - 'writeAsciiToMemory', - 'getSocketFromFD', - 'getSocketAddress', - 'registerKeyEventCallback', - 'registerWheelEventCallback', - 'registerFocusEventCallback', - 'fillDeviceOrientationEventData', - 'registerDeviceOrientationEventCallback', - 'fillDeviceMotionEventData', - 'registerDeviceMotionEventCallback', - 'screenOrientation', - 'fillOrientationChangeEventData', - 'registerOrientationChangeEventCallback', - 'fillFullscreenChangeEventData', - 'registerFullscreenChangeEventCallback', - 'JSEvents_requestFullscreen', - 'JSEvents_resizeCanvasForFullscreen', - 'registerRestoreOldStyle', - 'hideEverythingExceptGivenElement', - 'restoreHiddenElements', - 'setLetterbox', - 'softFullscreenResizeWebGLRenderTarget', - 'doRequestFullscreen', - 'fillPointerlockChangeEventData', - 'registerPointerlockChangeEventCallback', - 'registerPointerlockErrorEventCallback', - 'requestPointerLock', - 'fillVisibilityChangeEventData', - 'registerVisibilityChangeEventCallback', - 'registerTouchEventCallback', - 'fillGamepadEventData', - 'registerGamepadEventCallback', - 'registerBeforeUnloadEventCallback', - 'fillBatteryEventData', - 'battery', - 'registerBatteryEventCallback', - 'setCanvasElementSize', - 'getCanvasElementSize', - 'demangle', - 'demangleAll', - 'jsStackTrace', - 'stackTrace', - 'getEnvStrings', - 'checkWasiClock', - 'createDyncallWrapper', - 'setImmediateWrapped', - 'clearImmediateWrapped', - 'polyfillSetImmediate', - 'ExceptionInfo', - 'exception_addRef', - 'exception_decRef', - 'setMainLoop', - '_setNetworkCallback', - 'heapObjectForWebGLType', - 'heapAccessShiftForWebGLHeap', - 'emscriptenWebGLGet', - 'computeUnpackAlignedImageSize', - 'emscriptenWebGLGetTexPixelData', - 'emscriptenWebGLGetUniform', - 'emscriptenWebGLGetVertexAttrib', - 'emscriptenWebGLGetBufferBinding', - 'emscriptenWebGLValidateMapBufferTarget', - 'writeGLArray', - 'SDL_unicode', - 'SDL_ttfContext', - 'SDL_audio', - 'GLFW_Window', - 'runAndAbortIfError', - 'emscriptenWebGLGetIndexed', - 'ALLOC_NORMAL', - 'ALLOC_STACK', - 'allocate', -]; -missingLibrarySymbols.forEach(missingLibrarySymbol) +unexportedSymbols.forEach(unexportedRuntimeSymbol); + var calledRun; @@ -3660,11 +3512,11 @@ dependenciesFulfilled = function runCaller() { if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled }; -function callMain(args) { +function callMain() { assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])'); assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called'); - var entryFunction = Module['_main']; + var entryFunction = _main; var argc = 0; var argv = 0; @@ -3694,8 +3546,7 @@ function stackCheckInit() { } /** @type {function(Array=)} */ -function run(args) { - args = args || arguments_; +function run() { if (runDependencies > 0) { return; @@ -3725,7 +3576,7 @@ function run(args) { if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); - if (shouldRunNow) callMain(args); + if (shouldRunNow) callMain(); postRun(); } @@ -3789,6 +3640,4 @@ if (Module['noInitialRun']) shouldRunNow = false; run(); - - - +// end include: postamble.js diff --git a/themes/dist/output.wasm b/themes/dist/output.wasm Binary files differindex ab6ef25..1b24bbd 100755 --- a/themes/dist/output.wasm +++ b/themes/dist/output.wasm diff --git a/themes/resources/grass-blade.png b/themes/resources/grass-blade.png Binary files differnew file mode 100644 index 0000000..286cc23 --- /dev/null +++ b/themes/resources/grass-blade.png diff --git a/themes/src/Renderer3d.cpp b/themes/src/Renderer3d.cpp index 5f9ce88..00315de 100644 --- a/themes/src/Renderer3d.cpp +++ b/themes/src/Renderer3d.cpp @@ -8,32 +8,8 @@ // Note: In the 'transform' attribute, the transform.x is the scale, // transform.y is the rotation, and transform.zw is the translatiob. -const char* vertexShader = - "attribute vec4 position; \n" - "attribute vec4 color; \n" - "attribute vec4 normal; \n" - "uniform mat4 projection; \n" - "uniform mat4 view; \n" - "uniform mat4 model; \n" - "varying lowp vec4 VertexColor; \n" - "varying lowp vec4 VertexNormal; \n" - "void main() { \n" - " vec4 fragmentPosition = projection * view * model * position; \n" - " gl_Position = fragmentPosition; \n" - " VertexColor = color; \n" - " VertexNormal = normal; \n" - "}"; - -const char* fragmentShader = - "varying lowp vec4 VertexColor; \n" - "varying lowp vec4 VertexNormal; \n" - "void main() { \n" - " const lowp vec3 lightDirection = vec3(0.0, 1.0, 0.0);\n" - " gl_FragColor = vec4(VertexColor.xyz * dot(VertexNormal.xyz, lightDirection), 1); \n" - "}"; - EM_BOOL onScreenSizeChanged_3D(int eventType, const EmscriptenUiEvent *uiEvent, void *userData) { - Renderer3D* renderer = (Renderer3D*)userData; + Renderer3d* renderer = (Renderer3d*)userData; EMSCRIPTEN_RESULT result = emscripten_set_canvas_element_size( renderer->context->query, uiEvent->documentBodyClientWidth, uiEvent->documentBodyClientHeight); if (result != EMSCRIPTEN_RESULT_SUCCESS) { @@ -44,9 +20,9 @@ EM_BOOL onScreenSizeChanged_3D(int eventType, const EmscriptenUiEvent *uiEvent, return true; } -void Renderer3D::load(WebglContext* inContext) { +void Renderer3d::load(WebglContext* inContext, const char* vertexShader, const char* fragmentShader) { context = inContext; - printf("Compiling Renderer2d shader...\n"); + printf("Compiling Renderer3d shader...\n"); shader = loadShader(vertexShader, fragmentShader); useShader(shader); @@ -59,12 +35,12 @@ void Renderer3D::load(WebglContext* inContext) { projection = Mat4x4().getPerspectiveProjection(0.1, 1000.f, 0.872f, static_cast<f32>(context->width) / static_cast<f32>(context->height)); view = Mat4x4().getLookAt({ 0, 25, 75 }, { 0, 15, 0 }, { 0, 1, 0 }); - logger_info("Renderer2d shader compiled.\n"); + logger_info("Renderer3d shader compiled.\n"); emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, this, false, onScreenSizeChanged_3D); } -void Renderer3D::render() { +void Renderer3d::render() { glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glDepthMask(GL_TRUE); @@ -78,7 +54,7 @@ void Renderer3D::render() { setShaderMat4(uniforms.view, view); } -void Renderer3D::unload() { +void Renderer3d::unload() { glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT); glDeleteProgram(shader); @@ -126,7 +102,7 @@ inline i32 readToken(i32 i, const char* content, char* output) { return i; } -Mesh3d Mesh3d_fromObj(Renderer3D* renderer, const char* content, const i32 len) { +Mesh3d Mesh3d_fromObj(Renderer3d* renderer, const char* content, const i32 len) { Mesh3d result; result.vertices.allocate(2048); result.indices.allocate(2048); @@ -218,7 +194,7 @@ Mesh3d Mesh3d_fromObj(Renderer3D* renderer, const char* content, const i32 len) return result; } -void Mesh3d::load(Renderer3D* renderer) { +void Mesh3d::load(Renderer3d* renderer) { glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); glGenBuffers(1, &ebo); @@ -254,7 +230,7 @@ void Mesh3d::unload() { indices.deallocate(); } -void Mesh3d::render(Renderer3D* renderer) { +void Mesh3d::render(Renderer3d* renderer) { setShaderMat4(renderer->uniforms.model, model); glBindVertexArray(vao); diff --git a/themes/src/Renderer3d.h b/themes/src/Renderer3d.h index 7e89c93..5b2c8c8 100644 --- a/themes/src/Renderer3d.h +++ b/themes/src/Renderer3d.h @@ -5,7 +5,7 @@ #include "types.h" #include <string> -struct Renderer3D; +struct Renderer3d; struct Vertex3d { Vector4 position; @@ -21,13 +21,13 @@ struct Mesh3d { matte::List<u32> indices; Mat4x4 model; - void load(Renderer3D* renderer); - void render(Renderer3D* renderer); + void load(Renderer3d* renderer); + void render(Renderer3d* renderer); void unload(); }; struct WebglContext; -struct Renderer3D { +struct Renderer3d { WebglContext* context = NULL; Mat4x4 projection; Mat4x4 view; @@ -46,11 +46,11 @@ struct Renderer3D { i32 model; } uniforms; - void load(WebglContext* context); + void load(WebglContext* context, const char* vertexShader, const char* fragmentShader); void render(); void unload(); }; -Mesh3d Mesh3d_fromObj(Renderer3D* renderer, const char* content, const i32 len); +Mesh3d Mesh3d_fromObj(Renderer3d* renderer, const char* content, const i32 len); #endif diff --git a/themes/src/autumn/AutumnTheme.cpp b/themes/src/autumn/AutumnTheme.cpp new file mode 100644 index 0000000..6e6fe2b --- /dev/null +++ b/themes/src/autumn/AutumnTheme.cpp @@ -0,0 +1,23 @@ +#include "AutumnTheme.hpp" +#include "../Renderer2d.h" + +void AutumnTheme::load(Renderer2d* renderer) { + renderer->clearColor = Vector4(252, 210, 153, 255).toNormalizedColor(); + auto lr = tree.load(renderer); + leafParticles.load(renderer, &lr); +} + +void AutumnTheme::update(f32 dtSeconds) { + tree.update(dtSeconds); + leafParticles.update(dtSeconds); +} + +void AutumnTheme::render(Renderer2d* renderer) { + tree.render(renderer); + leafParticles.render(renderer); +} + +void AutumnTheme::unload() { + tree.unload(); + leafParticles.unload(); +}
\ No newline at end of file diff --git a/themes/src/autumn/AutumnTheme.hpp b/themes/src/autumn/AutumnTheme.hpp new file mode 100644 index 0000000..18da959 --- /dev/null +++ b/themes/src/autumn/AutumnTheme.hpp @@ -0,0 +1,20 @@ +#ifndef AUTUMN_THEME_HPP +#define AUTUMN_THEME_HPP + +#include "TreeShape.h" +#include "LeafParticleRender.h" +#include "../types.h" + +struct Renderer2d; + +struct AutumnTheme { + TreeShape tree; + LeafParticleRender leafParticles; + + void load(Renderer2d* renderer); + void update(f32 dtSeconds); + void render(Renderer2d* renderer); + void unload(); +}; + +#endif
\ No newline at end of file diff --git a/themes/src/LeafParticleRender.cpp b/themes/src/autumn/LeafParticleRender.cpp index 0c6fbca..fee3df2 100644 --- a/themes/src/LeafParticleRender.cpp +++ b/themes/src/autumn/LeafParticleRender.cpp @@ -1,8 +1,8 @@ #include "LeafParticleRender.h" -#include "Renderer2d.h" -#include "mathlib.h" +#include "../Renderer2d.h" +#include "../mathlib.h" #include "TreeShape.h" -#include "types.h" +#include "../types.h" #include <math.h> const i32 verticesPerLeaf = 6; diff --git a/themes/src/LeafParticleRender.h b/themes/src/autumn/LeafParticleRender.h index 713d9f6..f6efe1f 100644 --- a/themes/src/LeafParticleRender.h +++ b/themes/src/autumn/LeafParticleRender.h @@ -1,6 +1,6 @@ -#include "Renderer2d.h" -#include "mathlib.h" -#include "types.h" +#include "../Renderer2d.h" +#include "../mathlib.h" +#include "../types.h" struct TreeShapeLoadResult; diff --git a/themes/src/TreeShape.cpp b/themes/src/autumn/TreeShape.cpp index a3ae8f7..9738fd5 100644 --- a/themes/src/TreeShape.cpp +++ b/themes/src/autumn/TreeShape.cpp @@ -1,5 +1,5 @@ #include "TreeShape.h" -#include "mathlib.h" +#include "../mathlib.h" #include <cstdio> #include <cstdlib> #include <cfloat> diff --git a/themes/src/TreeShape.h b/themes/src/autumn/TreeShape.h index 32b00d3..fc0d11e 100644 --- a/themes/src/TreeShape.h +++ b/themes/src/autumn/TreeShape.h @@ -1,6 +1,6 @@ -#include "Renderer2d.h" -#include "types.h" -#include "mathlib.h" +#include "../Renderer2d.h" +#include "../types.h" +#include "../mathlib.h" struct TreeLoadData { f32 trunkHeight = 96.f; // Height of the trunk start diff --git a/themes/src/main.cpp b/themes/src/main.cpp index f8771d4..4e1a646 100644 --- a/themes/src/main.cpp +++ b/themes/src/main.cpp @@ -1,13 +1,12 @@ #include "WebglContext.h" #include "MainLoop.h" #include "Renderer2d.h" -#include "Renderer3d.h" #include "mathlib.h" #include "types.h" -#include "TreeShape.h" -#include "SummerTheme.h" -#include "LeafParticleRender.h" -#include "Snowflake.h" +#include "summer/SummerTheme.h" +#include "autumn/AutumnTheme.hpp" +#include "spring/SpringTheme.hpp" +#include "winter/WinterTheme.hpp" #include <cstdio> #include <emscripten/fetch.h> @@ -20,55 +19,6 @@ enum Theme { Summer }; -struct AutumnTheme { - TreeShape tree; - LeafParticleRender leafParticles; - - void load(Renderer2d* renderer); - void update(f32 dtSeconds); - void render(Renderer2d* renderer); - void unload(); -}; - -struct WinterTheme { - SnowflakeParticleRenderer spr; - - void load(Renderer2d* renderer); - void update(f32 dtSeconds); - void render(Renderer2d* renderer); - void unload(); -}; - -enum class BunnyAnimationState { - Loading = 0, - Loaded, - PreHop, - Hopping, - Idle -}; - -struct SpringTheme { - BunnyAnimationState state; - f32 bunnySpeed = 5.f; - Vector3 bunnyPosition = Vector3(0, 0, 0); - Vector3 bunnyTarget = Vector3(0, 0, 0); - Vector3 hopIncrement = Vector3(0, 0, 0); - - f32 numHops = 0; - f32 hopCount = 0; - f32 bunnyHopAnimationTimer = 0.f; - f32 stateTimer = 0.f; - f32 bunnyRotation = 0.f; - f32 targetRotation = 0.f; - - Mesh3d bunnyMesh; - - void load(Renderer3D* renderer); - void update(f32 dtSeconds); - void render(Renderer3D* renderer); - void unload(); -}; - void load(Theme theme); void unload(); void update(f32 dtSeconds, void* userData); @@ -80,7 +30,6 @@ EM_BOOL selectSummer(int eventType, const EmscriptenMouseEvent* mouseEvent, void WebglContext context; Renderer2d renderer2d; -Renderer3D renderer3d; MainLoop mainLoop; Theme activeTheme = Theme::Default; AutumnTheme autumnTheme; @@ -120,10 +69,10 @@ void load(Theme theme) { renderer2d.load(&context); winterTheme.load(&renderer2d); break; - case Theme::Spring: - renderer3d.load(&context); - springTheme.load(&renderer3d); + case Theme::Spring: { + springTheme.load(&context); break; + } case Theme::Summer: renderer2d.load(&context); summerTheme.load(&renderer2d); @@ -163,8 +112,7 @@ void update(f32 dtSeconds, void* userData) { winterTheme.render(&renderer2d); break; case Theme::Spring: - renderer3d.render(); - springTheme.render(&renderer3d); + springTheme.render(); break; case Theme::Summer: renderer2d.render(); @@ -197,7 +145,6 @@ void unload() { if (mainLoop.isRunning) { mainLoop.stop(); renderer2d.unload(); - renderer3d.unload(); } } @@ -230,216 +177,4 @@ EM_BOOL selectSummer(int eventType, const EmscriptenMouseEvent* mouseEvent, void printf("Summer theme selected\n"); load(Theme::Summer); return true; -} - -// -- Autumn theme -void AutumnTheme::load(Renderer2d* renderer) { - renderer->clearColor = Vector4(252, 210, 153, 255).toNormalizedColor(); - auto lr = tree.load(renderer); - leafParticles.load(renderer, &lr); -} - -void AutumnTheme::update(f32 dtSeconds) { - tree.update(dtSeconds); - leafParticles.update(dtSeconds); -} - -void AutumnTheme::render(Renderer2d* renderer) { - tree.render(renderer); - leafParticles.render(renderer); -} - -void AutumnTheme::unload() { - tree.unload(); - leafParticles.unload(); -} - -// -- Winter theme -void WinterTheme::load(Renderer2d* renderer) { - renderer->clearColor = Vector4(200, 229, 239, 255).toNormalizedColor(); - SnowflakeLoadParameters lp; - spr.load(lp, renderer); -} - -void WinterTheme::update(f32 dtSeconds) { - spr.update(dtSeconds); -} - -void WinterTheme::render(Renderer2d* renderer) { - spr.render(renderer); -} - -void WinterTheme::unload() { - spr.unload(); -} - -// -- Spring theme -void onBunnySuccess(emscripten_fetch_t *fetch) { - springTheme.state = BunnyAnimationState::Loaded; - printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url); - const i32 len = fetch->numBytes; - springTheme.bunnyMesh = Mesh3d_fromObj(&renderer3d, fetch->data, len); - // The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1]; - emscripten_fetch_close(fetch); // Free data associated with the fetch. -} - -void onBunnyFail(emscripten_fetch_t *fetch) { - printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status); - emscripten_fetch_close(fetch); // Also free data on failure. -} - -void SpringTheme::load(Renderer3D* renderer) { - springTheme.state = BunnyAnimationState::Loading; - renderer->clearColor = Vector4(160, 231, 160, 255.f).toNormalizedColor(); - - emscripten_fetch_attr_t attr; - emscripten_fetch_attr_init(&attr); - strcpy(attr.requestMethod, "GET"); - attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; - attr.onsuccess = onBunnySuccess; - attr.onerror = onBunnyFail; - emscripten_fetch(&attr, "themes/resources/bunny.obj"); -} - -inline Vector3 bunnyLerp(Vector3& start, Vector3& target, f32 t) { - t = 3 * t *t - 2 * t * t * t; - return start + ((target - start) * t); -} - -inline f32 verticalHopLerp(f32 start, f32 target, f32 t) { - f32 ogt = t; - t = 3 * t *t - 2 * t * t * t; - if (ogt >= 0.5f) t = 1.f - t; - return start + ((target - start) * t); -} - -inline f32 rotationLerp(f32 start, f32 target, f32 t) { - return start + ((target - start) * t); -} - -void SpringTheme::update(f32 dtSeconds) { - switch (state) { - case BunnyAnimationState::Loading: return; - case BunnyAnimationState::Loaded: - state = BunnyAnimationState::Idle; - stateTimer = 0.f; - bunnyHopAnimationTimer = 0.f; - break; - case BunnyAnimationState::Idle: { - bunnyHopAnimationTimer += dtSeconds; - const f32 HOP_FREQUENCY = 6.f; - - if (bunnyHopAnimationTimer > stateTimer) { - state = BunnyAnimationState::PreHop; - f32 xDir = 1; - f32 yDir = 1; - if (bunnyTarget.x > 0) xDir = -1; - if (bunnyTarget.z > 0) yDir = -1; - bunnyTarget = bunnyPosition + Vector3(randomFloatBetween(0, xDir * 25), 0, randomFloatBetween(0, yDir * 25)); - auto direction = (bunnyTarget - bunnyPosition); - auto distance = direction.length(); - direction = direction.normalize(); - numHops = ceil(distance / HOP_FREQUENCY); - hopCount = 0; - - targetRotation = PI - atan2(direction.y, direction.x); - stateTimer = ((bunnyTarget - bunnyPosition).length() / bunnySpeed) / numHops; - bunnyHopAnimationTimer = 0.f; - hopIncrement = (bunnyTarget - bunnyPosition) / numHops; - } - break; - } - case BunnyAnimationState::PreHop: { - const f32 ROTATION_TIME = 0.5f; - bunnyHopAnimationTimer += dtSeconds; - f32 current = bunnyRotation + (targetRotation - bunnyRotation) * (bunnyHopAnimationTimer / ROTATION_TIME); - bunnyMesh.model = Mat4x4().rotate(0, current, 0).translate(bunnyPosition); - - if (bunnyHopAnimationTimer > ROTATION_TIME) { - bunnyRotation = targetRotation; - bunnyHopAnimationTimer = 0; - state = BunnyAnimationState::Hopping; - } - break; - } - case BunnyAnimationState::Hopping: { - bunnyHopAnimationTimer += dtSeconds; - f32 t = bunnyHopAnimationTimer / stateTimer; - - Vector3 nextPosition = bunnyPosition + hopIncrement; - auto renderPos = bunnyLerp(bunnyPosition, nextPosition, t); - if ((renderPos - nextPosition).length() < 0.01f) { - hopCount += 1; - bunnyHopAnimationTimer = 0.f; - bunnyPosition = nextPosition; - } - - renderPos.y = verticalHopLerp(0.f, 4.f, t); - - const f32 RMAX = PI / 16.f; - f32 zRotation = 0; - f32 start = 0.f; - f32 end = PI / 8.f; - f32 startTime = 0.f; - f32 endTime = 0.f; - bool disableRot = false; - - if (t >= 0.9f) { - disableRot = true; - } - else if (t >= 0.7f) { - start = -RMAX; - end = 0.f; - startTime = 0.7f; - endTime = 0.9f; - } - else if (t >= 0.50f) { - start = 0.f; - end = -RMAX; - startTime = 0.50f; - endTime = 0.70f; - } - else if (t >= 0.40f) { - disableRot = true; - } - else if (t >= 0.20f) { - start = RMAX; - end = 0.f; - startTime = 0.20f; - endTime = 0.40f; - } - else { - start = 0.f; - end = RMAX; - startTime = 0.f; - endTime = 0.20f; - } - - - if (!disableRot) { - f32 totalTime = endTime - startTime; - zRotation = rotationLerp(start, end, (totalTime - (endTime - t)) / totalTime); - } - - bunnyMesh.model = Mat4x4().getZRotationMatrix(zRotation).rotate(0, bunnyRotation, 0).translate(renderPos); - if (hopCount == numHops) { - bunnyPosition = bunnyTarget; - bunnyHopAnimationTimer = 0.f; - state = BunnyAnimationState::Idle; - stateTimer = randomFloatBetween(0.5f, 1.f); - } - break; - } - } -} - -void SpringTheme::render(Renderer3D* renderer) { - renderer->render(); - if (state != BunnyAnimationState::Loading) { - bunnyMesh.render(renderer); - } -} - -void SpringTheme::unload() { - bunnyMesh.unload(); -} +}
\ No newline at end of file diff --git a/themes/src/shader_fetcher.cpp b/themes/src/shader_fetcher.cpp new file mode 100644 index 0000000..19ef983 --- /dev/null +++ b/themes/src/shader_fetcher.cpp @@ -0,0 +1,69 @@ +#include "shader_fetcher.hpp" +#include "types.h" +#include <cstdio> +#include <emscripten/fetch.h> + +struct FetchtimeData { + ShaderFetchResult result; + ShaderFetchPaths paths_data; + void (*cb)(ShaderFetchResult*); +}; + +void on_failure(emscripten_fetch_t *fetch) { + FetchtimeData* ftd = (FetchtimeData*)fetch->userData; + printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status); + emscripten_fetch_close(fetch); // Also free data on failure. + ftd->cb(nullptr); +} + +void on_fragment_shader(emscripten_fetch_t *fetch) { + FetchtimeData* ftd = (FetchtimeData*)fetch->userData; + printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url); + const i32 len = fetch->numBytes; + char* data = (char*)fetch->data; + data[len - 1] = '\0'; + ftd->result.fragment = data; + emscripten_fetch_close(fetch); // Free data associated with the fetch. + + ftd->cb(&ftd->result); + delete ftd; +} + +void on_vertex_shader(emscripten_fetch_t *fetch) { + + FetchtimeData* ftd = (FetchtimeData*)fetch->userData; + printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url); + const i32 len = fetch->numBytes; + char* data = (char*)fetch->data; + data[len - 1] = '\0'; + + ftd->result.vertex = data; + emscripten_fetch_close(fetch); // Free data associated with the fetch. + + // Fetch fragment shader next + emscripten_fetch_attr_t attr; + emscripten_fetch_attr_init(&attr); + strcpy(attr.requestMethod, "GET"); + attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; + attr.onsuccess = on_fragment_shader; + attr.onerror = on_failure; + auto* request = emscripten_fetch(&attr, ftd->paths_data.fragment); + request->userData = ftd; +} + +void fetch_shader(ShaderFetchPaths paths, void (*cb)(ShaderFetchResult*), void* user_data) { + FetchtimeData* ftd = new FetchtimeData(); + ftd->cb = cb; + ftd->paths_data = paths; + ftd->result.user_data = user_data; + + // Fetch vertex shader + emscripten_fetch_attr_t attr; + emscripten_fetch_attr_init(&attr); + strcpy(attr.requestMethod, "GET"); + attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; + attr.onsuccess = on_vertex_shader; + attr.onerror = on_failure; + auto* request = emscripten_fetch(&attr, paths.vertex); + request->userData = ftd; +}
\ No newline at end of file diff --git a/themes/src/shader_fetcher.hpp b/themes/src/shader_fetcher.hpp new file mode 100644 index 0000000..aef25b4 --- /dev/null +++ b/themes/src/shader_fetcher.hpp @@ -0,0 +1,19 @@ +#ifndef SHADER_FETCHER_HPP +#define SHADER_FETCHER_HPP + +#include <string> + +struct ShaderFetchPaths { + const char* vertex; + const char* fragment; +}; + +struct ShaderFetchResult { + std::string vertex; + std::string fragment; + void* user_data; +}; + +void fetch_shader(ShaderFetchPaths, void (*cb)(ShaderFetchResult*), void* user_data = nullptr); + +#endif
\ No newline at end of file diff --git a/themes/src/shaders/renderer2d.frag b/themes/src/shaders/renderer2d.frag new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/themes/src/shaders/renderer2d.frag diff --git a/themes/src/shaders/renderer2d.vert b/themes/src/shaders/renderer2d.vert new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/themes/src/shaders/renderer2d.vert diff --git a/themes/src/shaders/renderer3d.frag b/themes/src/shaders/renderer3d.frag new file mode 100644 index 0000000..2f50347 --- /dev/null +++ b/themes/src/shaders/renderer3d.frag @@ -0,0 +1,7 @@ +varying lowp vec4 VertexColor; +varying lowp vec4 VertexNormal; + +void main() { + const lowp vec3 lightDirection = vec3(0.0, 1.0, 0.0); + gl_FragColor = vec4(VertexColor.xyz * dot(VertexNormal.xyz, lightDirection), 1); +} diff --git a/themes/src/shaders/renderer3d.vert b/themes/src/shaders/renderer3d.vert new file mode 100644 index 0000000..026285f --- /dev/null +++ b/themes/src/shaders/renderer3d.vert @@ -0,0 +1,15 @@ +attribute vec4 position; +attribute vec4 color; +attribute vec4 normal; +uniform mat4 projection; +uniform mat4 view; +uniform mat4 model; +varying lowp vec4 VertexColor; +varying lowp vec4 VertexNormal; + +void main() { + vec4 fragmentPosition = projection * view * model * position; + gl_Position = fragmentPosition; + VertexColor = color; + VertexNormal = normal; +} diff --git a/themes/src/spring/GrassRenderer.cpp b/themes/src/spring/GrassRenderer.cpp new file mode 100644 index 0000000..b69d111 --- /dev/null +++ b/themes/src/spring/GrassRenderer.cpp @@ -0,0 +1,29 @@ +#include "GrassRenderer.hpp" +#include "Renderer3d.h" + +void GrassRenderer::load(GrassRendererLoadData params, Renderer3d* renderer) { + const f32 COLUMN_INCREMENT = GRASS_BLADES_PER_COL / params.area.x; + const f32 ROW_INCREMENT = GRASS_BLADES_PER_ROW / params.area.y; + for (i32 r = 0; r < GRASS_BLADES_PER_ROW; r++) { + i32 indexOffset = r * GRASS_BLADES_PER_ROW; + f32 y = ROW_INCREMENT * r; + for (i32 c = 0; c < GRASS_BLADES_PER_COL; c++) { + f32 x = COLUMN_INCREMENT * c; + i32 index = indexOffset + c; + grassBlades[index].position = Vector3(x, y, 0); + grassBlades[index].top_offset = Vector2(0, 0); + } + } +} + +void GrassRenderer::update(f32 seconds) { + +} + +void GrassRenderer::render(Renderer3d* renderer) { + +} + +void GrassRenderer::unload() { + +} diff --git a/themes/src/spring/GrassRenderer.hpp b/themes/src/spring/GrassRenderer.hpp new file mode 100644 index 0000000..8c96724 --- /dev/null +++ b/themes/src/spring/GrassRenderer.hpp @@ -0,0 +1,33 @@ +#ifndef GRASS_RENDERER_HPP +#define GRASS_RENDERER_HPP + +#include "Renderer3d.h" +#include "mathlib.h" +#include "types.h" + +const i32 GRASS_BLADES_PER_ROW = 24; +const i32 GRASS_BLADES_PER_COL = 24; +const i32 NUM_GRASS_BLADES = GRASS_BLADES_PER_ROW * GRASS_BLADES_PER_COL; + +struct GrassRendererLoadData { + Vector2 origin = Vector2(0, 0); + Vector2 area = Vector2(480, 480); + f32 grassHeight = 12.f; +}; + +struct GrassUpdateData { + Vector3 position; + Vector2 top_offset; +}; + +struct GrassRenderer { + + GrassUpdateData grassBlades[NUM_GRASS_BLADES]; + + void load(GrassRendererLoadData params, Renderer3d* renderer); + void update(f32 dtSeconds); + void render(Renderer3d* renderer); + void unload(); +}; + +#endif diff --git a/themes/src/spring/SpringTheme.cpp b/themes/src/spring/SpringTheme.cpp new file mode 100644 index 0000000..abe8c6e --- /dev/null +++ b/themes/src/spring/SpringTheme.cpp @@ -0,0 +1,198 @@ +#include "SpringTheme.hpp" +#include "../Renderer3d.h" +#include "../shader_fetcher.hpp" +#include <cstdio> +#include <emscripten/fetch.h> + +void onBunnySuccess(emscripten_fetch_t *fetch) { + SpringTheme* springTheme = (SpringTheme*)fetch->userData; + springTheme->state = SpringThemeState::LoadedBunny; + printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url); + const i32 len = fetch->numBytes; + springTheme->bunnyMesh = Mesh3d_fromObj(&springTheme->renderer, fetch->data, len); + // The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1]; + emscripten_fetch_close(fetch); // Free data associated with the fetch. +} + +void onBunnyFail(emscripten_fetch_t *fetch) { + printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status); + emscripten_fetch_close(fetch); // Also free data on failure. +} + +inline void fetch_bunny(SpringTheme* theme) { + emscripten_fetch_attr_t attr; + emscripten_fetch_attr_init(&attr); + strcpy(attr.requestMethod, "GET"); + attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; + attr.onsuccess = onBunnySuccess; + attr.onerror = onBunnyFail; + auto* bunny_fetch = emscripten_fetch(&attr, "themes/resources/bunny.obj"); + bunny_fetch->userData = theme; +} + +inline void on_shaders_loader(ShaderFetchResult* result) { + SpringTheme* theme = (SpringTheme*)result->user_data; + theme->renderer.load(theme->renderer.context, result->vertex.c_str(), result->fragment.c_str()); + theme->state = SpringThemeState::LoadedShader; + fetch_bunny(theme); +} + +void SpringTheme::load(WebglContext* context) { + state = SpringThemeState::Loading; + renderer.context = context; + renderer.clearColor = Vector4(160, 231, 160, 255.f).toNormalizedColor(); + + fetch_shader( + { + "themes/src/shaders/renderer3d.vert", + "themes/src/shaders/renderer3d.frag" + }, + on_shaders_loader, + this + ); +} + +inline Vector3 bunnyLerp(Vector3& start, Vector3& target, f32 t) { + t = 3 * t *t - 2 * t * t * t; + return start + ((target - start) * t); +} + +inline f32 verticalHopLerp(f32 start, f32 target, f32 t) { + f32 ogt = t; + t = 3 * t *t - 2 * t * t * t; + if (ogt >= 0.5f) t = 1.f - t; + return start + ((target - start) * t); +} + +inline f32 rotationLerp(f32 start, f32 target, f32 t) { + return start + ((target - start) * t); +} + +void SpringTheme::update(f32 dtSeconds) { + switch (state) { + case SpringThemeState::Loading: return; + case SpringThemeState::LoadedShader: return; + case SpringThemeState::LoadedBunny: + state = SpringThemeState::Idle; + stateTimer = 0.f; + bunnyHopAnimationTimer = 0.f; + break; + case SpringThemeState::Idle: { + bunnyHopAnimationTimer += dtSeconds; + const f32 HOP_FREQUENCY = 6.f; + + if (bunnyHopAnimationTimer > stateTimer) { + state = SpringThemeState::PreHop; + f32 xDir = 1; + f32 yDir = 1; + if (bunnyTarget.x > 0) xDir = -1; + if (bunnyTarget.z > 0) yDir = -1; + bunnyTarget = bunnyPosition + Vector3(randomFloatBetween(0, xDir * 25), 0, randomFloatBetween(0, yDir * 25)); + auto direction = (bunnyTarget - bunnyPosition); + auto distance = direction.length(); + direction = direction.normalize(); + numHops = ceil(distance / HOP_FREQUENCY); + hopCount = 0; + + targetRotation = PI - atan2(direction.y, direction.x); + stateTimer = ((bunnyTarget - bunnyPosition).length() / bunnySpeed) / numHops; + bunnyHopAnimationTimer = 0.f; + hopIncrement = (bunnyTarget - bunnyPosition) / numHops; + } + break; + } + case SpringThemeState::PreHop: { + const f32 ROTATION_TIME = 0.5f; + bunnyHopAnimationTimer += dtSeconds; + f32 current = bunnyRotation + (targetRotation - bunnyRotation) * (bunnyHopAnimationTimer / ROTATION_TIME); + bunnyMesh.model = Mat4x4().rotate(0, current, 0).translate(bunnyPosition); + + if (bunnyHopAnimationTimer > ROTATION_TIME) { + bunnyRotation = targetRotation; + bunnyHopAnimationTimer = 0; + state = SpringThemeState::Hopping; + } + break; + } + case SpringThemeState::Hopping: { + bunnyHopAnimationTimer += dtSeconds; + f32 t = bunnyHopAnimationTimer / stateTimer; + + Vector3 nextPosition = bunnyPosition + hopIncrement; + auto renderPos = bunnyLerp(bunnyPosition, nextPosition, t); + if ((renderPos - nextPosition).length() < 0.01f) { + hopCount += 1; + bunnyHopAnimationTimer = 0.f; + bunnyPosition = nextPosition; + } + + renderPos.y = verticalHopLerp(0.f, 4.f, t); + + const f32 RMAX = PI / 16.f; + f32 zRotation = 0; + f32 start = 0.f; + f32 end = PI / 8.f; + f32 startTime = 0.f; + f32 endTime = 0.f; + bool disableRot = false; + + if (t >= 0.9f) { + disableRot = true; + } + else if (t >= 0.7f) { + start = -RMAX; + end = 0.f; + startTime = 0.7f; + endTime = 0.9f; + } + else if (t >= 0.50f) { + start = 0.f; + end = -RMAX; + startTime = 0.50f; + endTime = 0.70f; + } + else if (t >= 0.40f) { + disableRot = true; + } + else if (t >= 0.20f) { + start = RMAX; + end = 0.f; + startTime = 0.20f; + endTime = 0.40f; + } + else { + start = 0.f; + end = RMAX; + startTime = 0.f; + endTime = 0.20f; + } + + + if (!disableRot) { + f32 totalTime = endTime - startTime; + zRotation = rotationLerp(start, end, (totalTime - (endTime - t)) / totalTime); + } + + bunnyMesh.model = Mat4x4().getZRotationMatrix(zRotation).rotate(0, bunnyRotation, 0).translate(renderPos); + if (hopCount == numHops) { + bunnyPosition = bunnyTarget; + bunnyHopAnimationTimer = 0.f; + state = SpringThemeState::Idle; + stateTimer = randomFloatBetween(0.5f, 1.f); + } + break; + } + } +} + +void SpringTheme::render() { + renderer.render(); + if (state != SpringThemeState::Loading) { + bunnyMesh.render(&renderer); + } +} + +void SpringTheme::unload() { + renderer.unload(); + bunnyMesh.unload(); +} diff --git a/themes/src/spring/SpringTheme.hpp b/themes/src/spring/SpringTheme.hpp new file mode 100644 index 0000000..0866921 --- /dev/null +++ b/themes/src/spring/SpringTheme.hpp @@ -0,0 +1,41 @@ +#ifndef SPRING_THEME_HPP +#define SPRING_THEME_HPP + +#include "../mathlib.h" +#include "../types.h" +#include "../Renderer3d.h" + + +enum class SpringThemeState { + Loading = 0, + LoadedShader, + LoadedBunny, + PreHop, + Hopping, + Idle +}; + +struct SpringTheme { + Renderer3d renderer; + SpringThemeState state; + f32 bunnySpeed = 5.f; + Vector3 bunnyPosition = Vector3(0, 0, 0); + Vector3 bunnyTarget = Vector3(0, 0, 0); + Vector3 hopIncrement = Vector3(0, 0, 0); + + f32 numHops = 0; + f32 hopCount = 0; + f32 bunnyHopAnimationTimer = 0.f; + f32 stateTimer = 0.f; + f32 bunnyRotation = 0.f; + f32 targetRotation = 0.f; + + Mesh3d bunnyMesh; + + void load(WebglContext*); + void update(f32 dtSeconds); + void render(); + void unload(); +}; + +#endif
\ No newline at end of file diff --git a/themes/src/SummerTheme.cpp b/themes/src/summer/SummerTheme.cpp index 20bb310..406cd22 100644 --- a/themes/src/SummerTheme.cpp +++ b/themes/src/summer/SummerTheme.cpp @@ -1,7 +1,7 @@ #include "SummerTheme.h" -#include "Renderer2d.h" -#include "list.h" -#include "mathlib.h" +#include "../Renderer2d.h" +#include "../list.h" +#include "../mathlib.h" #include <vector> void SummerTheme::load(Renderer2d* renderer) { diff --git a/themes/src/SummerTheme.h b/themes/src/summer/SummerTheme.h index 1d9093a..4a9f76b 100644 --- a/themes/src/SummerTheme.h +++ b/themes/src/summer/SummerTheme.h @@ -1,6 +1,6 @@ #pragma once -#include "types.h" -#include "Renderer2d.h" +#include "../types.h" +#include "../Renderer2d.h" #include <vector> struct Sun { diff --git a/themes/src/Snowflake.cpp b/themes/src/winter/Snowflake.cpp index 452a716..57f1a8f 100644 --- a/themes/src/Snowflake.cpp +++ b/themes/src/winter/Snowflake.cpp @@ -1,7 +1,7 @@ #include "Snowflake.h" -#include "Renderer2d.h" -#include "mathlib.h" -#include "list.h" +#include "../Renderer2d.h" +#include "../mathlib.h" +#include "../list.h" #include <cstdio> /* @@ -142,7 +142,7 @@ inline void resetFlake(SnowflakeParticleRenderer* renderer, SnowflakeUpdateData* inline void updateFlake(SnowflakeParticleRenderer* renderer, SnowflakeUpdateData* ud, i32 s, f32 dtSeconds) { ud->velocity = ud->velocity + Vector2(0, -(GRAVITY * dtSeconds)); - if (addWind) ud->velocity += renderer->windSpeed; + //if (addWind) ud->velocity += renderer->windSpeed; ud->position += ud->velocity * dtSeconds; ud->rotation += ud->rotateVelocity * dtSeconds; diff --git a/themes/src/Snowflake.h b/themes/src/winter/Snowflake.h index c147469..ad027f6 100644 --- a/themes/src/Snowflake.h +++ b/themes/src/winter/Snowflake.h @@ -1,9 +1,9 @@ #ifndef SNOWFLAKE_H #define SNOWFLAKE_H -#include "types.h" -#include "mathlib.h" -#include "list.h" +#include "../types.h" +#include "../mathlib.h" +#include "../list.h" #include "Windfield.hpp" struct Renderer2d; @@ -31,7 +31,7 @@ struct SnowflakeParticleRenderer { f32 windIntervalSeconds = 1.5; i32 numSnowflakes = 0; f32 timeUntilNextWindSeconds = 0; - WindField wind; + WindField<100, 100, 10> wind; SnowflakeUpdateData* updateData; u32 vao; diff --git a/themes/src/Windfield.cpp b/themes/src/winter/Windfield.cpp index 3a7563f..88fb74b 100644 --- a/themes/src/Windfield.cpp +++ b/themes/src/winter/Windfield.cpp @@ -2,7 +2,7 @@ template <i32 Width, i32 Height, i32 CellDimension> -void WindField<Width, Height, CellDimension>::load(f32 ttl, Vector2 origin) { +void WindField<Width, Height, CellDimension>::load(f32 cellSizePixels, i32 fieldWithCells, i32 fieldHeightCells, f32 ttl, Vector2 origin) { this->ttl = ttl; this->origin = origin; this->end = this->origin + Vector2(Width * CellDimension, Height * CellDimension); @@ -21,7 +21,7 @@ Vector2 WindField<Width, Height, CellDimension>::getWindFactor(Vector2& v) { Vector2 positionInField = v - this->origin; i32 cellX = static_cast<i32>(Width / positionInField.x); i32 cellY = static_cast<i32>(Height / positionInField.y); - return field[cellX, cellY]; + return field[cellX][cellY]; } return Vector2(); diff --git a/themes/src/Windfield.hpp b/themes/src/winter/Windfield.hpp index 5935c5d..5bf0c38 100644 --- a/themes/src/Windfield.hpp +++ b/themes/src/winter/Windfield.hpp @@ -1,13 +1,14 @@ #ifndef WIND_FIELD_HPP #define WIND_FIELD_HPP -#include "types.h" -#include "mathlib.h" +#include "../types.h" +#include "../mathlib.h" /** A Windfield represents a field of vectors in a rectangular region. The Width and Height are given in units of CellDimenions. The CellDimension is given in pixels. */ +template <i32 Width, i32 Height, i32 CellDimension> struct WindField { f32 ttl = 0.f; Vector2 origin; diff --git a/themes/src/winter/WinterTheme.cpp b/themes/src/winter/WinterTheme.cpp new file mode 100644 index 0000000..2686988 --- /dev/null +++ b/themes/src/winter/WinterTheme.cpp @@ -0,0 +1,20 @@ +#include "WinterTheme.hpp" +#include "../Renderer2d.h" + +void WinterTheme::load(Renderer2d* renderer) { + renderer->clearColor = Vector4(200, 229, 239, 255).toNormalizedColor(); + SnowflakeLoadParameters lp; + spr.load(lp, renderer); +} + +void WinterTheme::update(f32 dtSeconds) { + spr.update(dtSeconds); +} + +void WinterTheme::render(Renderer2d* renderer) { + spr.render(renderer); +} + +void WinterTheme::unload() { + spr.unload(); +} diff --git a/themes/src/winter/WinterTheme.hpp b/themes/src/winter/WinterTheme.hpp new file mode 100644 index 0000000..5b8cc95 --- /dev/null +++ b/themes/src/winter/WinterTheme.hpp @@ -0,0 +1,18 @@ +#ifndef WINTER_THEME_HPP +#define WINTER_THEME_HPP + +#include "Snowflake.h" +#include "../types.h" + +struct Renderer2d; + +struct WinterTheme { + SnowflakeParticleRenderer spr; + + void load(Renderer2d* renderer); + void update(f32 dtSeconds); + void render(Renderer2d* renderer); + void unload(); +}; + +#endif
\ No newline at end of file |