diff options
author | alaric <alaric@netmythos.org> | 2024-04-14 21:07:25 -0700 |
---|---|---|
committer | alaric <alaric@netmythos.org> | 2024-04-14 21:07:25 -0700 |
commit | 72b43b36111f21d4625dfdb33b67a963ce23bcb8 (patch) | |
tree | d39fc68ca624302b2dda6f1e8e2a5dfbaa5fa1d7 | |
parent | 4c4b5a6ae33c363b0f0a21ee3de136aae99919d9 (diff) | |
download | engine-72b43b36111f21d4625dfdb33b67a963ce23bcb8.tar.gz engine-72b43b36111f21d4625dfdb33b67a963ce23bcb8.zip |
Make game loading more easily applicable to a variety of web shells
-rw-r--r-- | build.zig | 1 | ||||
-rw-r--r-- | src/engine.zig | 12 | ||||
-rw-r--r-- | src/shell/engine.js | 126 | ||||
-rw-r--r-- | src/shell/shell.html | 136 | ||||
-rw-r--r-- | src/shell/webgl.js | 866 | ||||
-rw-r--r-- | src/wasm.zig | 12 |
6 files changed, 733 insertions, 420 deletions
@@ -6,6 +6,7 @@ pub fn build(b: *std.Build) void { const shell = b.addNamedWriteFiles("shell"); _ = shell.addCopyFile(.{ .path = "src/shell/shell.html" }, "index.html"); + _ = shell.addCopyFile(.{ .path = "src/shell/engine.js" }, "engine.js"); _ = shell.addCopyFile(.{ .path = "src/shell/webgl.js" }, "webgl.js"); b.install_tls.step.dependOn(&shell.step); diff --git a/src/engine.zig b/src/engine.zig index bc39f55..b807326 100644 --- a/src/engine.zig +++ b/src/engine.zig @@ -4,6 +4,7 @@ const root = @import("root"); pub const math = @import("math.zig"); pub const webgl = @import("webgl.zig"); +pub const wasm = @import("wasm.zig"); pub const matrix = @import("matrix.zig"); pub const random = @import("random.zig"); pub const input = @import("input.zig"); @@ -14,7 +15,6 @@ comptime { @compileError("This engine only supports wasm32-freestanding as its target"); } - const wasm = @import("wasm.zig"); _ = wasm; } } @@ -38,6 +38,8 @@ pub const Color = struct { b: f32 = 0, a: f32 = 1, + pub const black: Color = Color.fromVec(.{ 0, 0, 0, 1 }); + pub const white: Color = Color.fromVec(.{ 1, 1, 1, 1 }); pub const red: Color = Color.fromVec(.{ 1, 0, 0, 1 }); pub const green: Color = Color.fromVec(.{ 0, 1, 0, 1 }); pub const blue: Color = Color.fromVec(.{ 0, 0, 1, 1 }); @@ -66,6 +68,14 @@ pub const Color = struct { const out = l + (r - l) * e; return Color.fromVec(out); } + + pub fn lerp(lhs: Color, rhs: Color, pct: f32) Color { + const l = lhs.toVec(); + const r = rhs.toVec(); + const e: @Vector(4, f32) = @splat(pct); + const out = l + (r - l) * e; + return Color.fromVec(out); + } }; pub const Cursor = enum(u8) { diff --git a/src/shell/engine.js b/src/shell/engine.js new file mode 100644 index 0000000..31371f8 --- /dev/null +++ b/src/shell/engine.js @@ -0,0 +1,126 @@ +const createEngineCtx = (canvas) => { + this.canvas = canvas; + this.memory = null; + this.last_frame_time = Date.now(); + + const specialKeymaps = { + "Shift": 0xE000, + }; + + + canvas.onbeforeunload = function (e) { + // Cancel the event + e.preventDefault(); + + // Chrome requires returnValue to be set + e.returnValue = 'Really want to quit the game?'; + }; + + const registerInputEvents = (obj) => { + const canvas = this.canvas; + const mouseHandler = (ev) => { + obj.instance.exports.mouseEvent(ev.x, ev.y, ev.movementX, ev.movementY, ev.buttons); + }; + + const keyHandler = (is_pressed) => { + return (ev) => { + //TODO: Do something for special keycodes, which don't have normal codepoints + var codepoint = 0xFFFD; + const chars = new TextEncoder().encode(ev.key); + if (specialKeymaps[ev.key]) { + codepoint = specialKeymaps[ev.key]; + } else if (chars.length <= 4) { + const inter = new Uint8Array(4); + inter.set(chars); + const num = new Uint32Array(inter); + codepoint = num[0]; + } + obj.instance.exports.keyEvent(codepoint, is_pressed, ev.repeat); + }; + }; + + canvas.oncontextmenu = (ev) => { return false; }; + canvas.addEventListener("mousedown", mouseHandler); + canvas.addEventListener("mouseup", mouseHandler); + canvas.addEventListener("pointermove", mouseHandler); + canvas.addEventListener("keydown", keyHandler(true)); + canvas.addEventListener("keyup", keyHandler(false)); + }; + + this.writeString = (str, pointer, length) => { + if (!memory) { + return null; + } + + const l = Math.min(length, str.length); + const from = new TextEncoder().encode(str.slice(0, l)); + const to = new Uint8Array(memory.buffer, pointer, length); + to.set(from); + return l; + }; + + this.readString = (pointer, length) => { + if (!memory) { + return null; + } + + // Memory in WASM is one big buffer. We can read a string from the + // Zig/WASM space if we know the pointer and length. + return new TextDecoder().decode( + new Uint8Array(memory.buffer, pointer, length), + ); + }; + + const rand = () => { + return Math.random(); + }; + + const consoleLog = (ptr, len) => { + console.log(this.readString(ptr, len)); + } + + const cursors = { + 0: "default", + 1: "grab", + 2: "grabbing", + }; + const setCursor = (c_idx) => { + const c = cursors[c_idx]; + if (c) { + canvas.style.cursor = c; + } + }; + + const webgl = createWebglBindings(this, canvas); + + this.importObject = { + env: { + ...webgl, + consoleLog, + rand, + setCursor, + }, + }; + + this.wasmCallback = (obj) => { + this.memory = obj.instance.exports.memory; + registerInputEvents(obj); + obj.instance.exports.init(); + + const update = obj.instance.exports.update; + function step() { + const canvas_style = window.getComputedStyle(canvas); + canvas.width = parseFloat(canvas_style.getPropertyValue("width")); + canvas.height = parseFloat(canvas_style.getPropertyValue("height")); + const time = Date.now(); + const elapsed = time - this.last_frame_time; + update(elapsed / 1000); + this.last_frame_time = time; + window.requestAnimationFrame(step); + } + + window.requestAnimationFrame(step); + }; + return this; +}; + diff --git a/src/shell/shell.html b/src/shell/shell.html index d0faf3a..69d4448 100644 --- a/src/shell/shell.html +++ b/src/shell/shell.html @@ -27,139 +27,13 @@ <body> <canvas id="app-canvas" tabindex="0"></canvas> <script src="webgl.js"></script> + <script src="engine.js"></script> <script> - let memory = null; - let last_frame_time = Date.now(); + const canvas = document.getElementById("app-canvas"); + const engineCtx = createEngineCtx(canvas); - const writeString = (str, pointer, length) => { - if (!memory) { - return null; - } - - const l = Math.min(length, str.length); - const from = new TextEncoder().encode(str.slice(0, l)); - const to = new Uint8Array(memory.buffer, pointer, length); - to.set(from); - return l; - }; - - const readString = (pointer, length) => { - if (!memory) { - return null; - } - - // Memory in WASM is one big buffer. We can read a string from the - // Zig/WASM space if we know the pointer and length. - return new TextDecoder().decode( - new Uint8Array(memory.buffer, pointer, length), - ); - }; - - - const consoleLog = (ptr, len) => { - console.log(readString(ptr, len)); - } - - const rand = () => { - return Math.random(); - }; - - const loadTexture = (ptr, len, tex_id, ret_ptr) => { - const path = readString(ptr, len); - var image = new Image(); - image.src = path; - console.log("loading ", path); - image.addEventListener('load', function() { - const ret_list = new Uint32Array(memory.buffer, ret_ptr, 3); - ret_list[0] = 1; - ret_list[1] = image.width; - ret_list[2] = image.height; - console.log(path, " loaded"); - const tex = glTextures.get(tex_id); - gfx_ctx.bindTexture(gfx_ctx.TEXTURE_2D, tex); - gfx_ctx.texImage2D(gfx_ctx.TEXTURE_2D, 0, gfx_ctx.RGBA, gfx_ctx.RGBA, gfx_ctx.UNSIGNED_BYTE, image); - gfx_ctx.generateMipmap(gfx_ctx.TEXTURE_2D); - }); - }; - - canvas.onbeforeunload = function (e) { - // Cancel the event - e.preventDefault(); - - // Chrome requires returnValue to be set - e.returnValue = 'Really want to quit the game?'; - }; - - const cursors = { - 0: "default", - 1: "grab", - 2: "grabbing", - }; - const setCursor = (c_idx) => { - const c = cursors[c_idx]; - if (c) { - canvas.style.cursor = c; - } - }; - - const importObject = { - env: { - ...webgl, - consoleLog, - rand, - loadTexture, - setCursor, - }, - }; - - const registerInputEvents = (obj) => { - const mouseHandler = (ev) => { - obj.instance.exports.mouseEvent(ev.x, ev.y, ev.movementX, ev.movementY, ev.buttons); - }; - - const keyHandler = (is_pressed) => { - return (ev) => { - //TODO: Do something for special keycodes, which don't have normal codepoints - var codepoint = 0xFFFD; - if (ev.key.length <= 4) { - const chars = new TextEncoder().encode(ev.key); - const inter = new Uint8Array(4); - inter.set(chars); - const num = new Uint32Array(inter); - codepoint = num[0]; - } - obj.instance.exports.keyEvent(codepoint, is_pressed, ev.repeat); - }; - }; - - canvas.oncontextmenu = (ev) => { return false; }; - canvas.addEventListener("mousedown", mouseHandler); - canvas.addEventListener("mouseup", mouseHandler); - canvas.addEventListener("pointermove", mouseHandler); - canvas.addEventListener("keydown", keyHandler(true)); - canvas.addEventListener("keyup", keyHandler(false)); - }; - - WebAssembly.instantiateStreaming(fetch("bin/game.wasm"), importObject).then( - (obj) => { - memory = obj.instance.exports.memory; - registerInputEvents(obj); - obj.instance.exports.init(); - - const update = obj.instance.exports.update; - function step() { - const canvas_style = window.getComputedStyle(canvas); - canvas.width = parseFloat(canvas_style.getPropertyValue("width")); - canvas.height = parseFloat(canvas_style.getPropertyValue("height")); - const time = Date.now(); - const elapsed = time - last_frame_time; - update(elapsed / 1000); - last_frame_time = time; - window.requestAnimationFrame(step); - } - - window.requestAnimationFrame(step); - } + WebAssembly.instantiateStreaming(fetch("bin/game.wasm"), engineCtx.importObject).then( + engineCtx.wasmCallback ); </script> </body> diff --git a/src/shell/webgl.js b/src/shell/webgl.js index 49b864c..f58ba03 100644 --- a/src/shell/webgl.js +++ b/src/shell/webgl.js @@ -1,288 +1,578 @@ -const canvas = document.getElementById("app-canvas"); -const gfx_ctx = canvas.getContext("webgl2"); -if (gfx_ctx === null) { - alert("There was a problem initializing WebGL. Your browser or machine may not support it."); -} - -let next_id = 0; -const getId = () => { - next_id += 1; - return next_id - 1; -}; - -const glBuffers = new Map(); -const glShaders = new Map(); -const glPrograms = new Map(); -const glVertexArrays = new Map(); -const glUniformLocations = new Map(); -const glTextures = new Map(); - -const attachShader = (program_id, shader_id) => { - const program = glPrograms.get(program_id); - const shader = glShaders.get(shader_id); - gfx_ctx.attachShader(program, shader); -}; - -const blendFunc = (sfactor, dfactor) => { - gfx_ctx.blendFunc(sfactor, dfactor); -}; - -const bindBuffer = (target, id) => { - gfx_ctx.bindBuffer(target, glBuffers.get(id)); -}; - -const bufferData = (target, ptr, len, usage) => { - const floats = new Float32Array(memory.buffer, ptr, len); - gfx_ctx.bufferData(target, floats, usage); -}; - -const bindVertexArray = (vao) => { - gfx_ctx.bindVertexArray(glVertexArrays.get(vao)); -}; - -const createVertexArray = () => { - const id = getId(); - glVertexArrays.set(id, gfx_ctx.createVertexArray()); - return id; -}; - -const clearColor = (r, g, b, a) => { - gfx_ctx.clearColor(r, g, b, a); -}; - -const clear = (mask) => { - gfx_ctx.clear(mask); -}; - -const createBuffer = () => { - const id = getId(); - glBuffers.set(id, gfx_ctx.createBuffer()); - return id; -}; - -const createShader = (type) => { - const id = getId(); - glShaders.set(id, gfx_ctx.createShader(type)); - return id; -}; - -const compileShader = (shader) => { - gfx_ctx.compileShader(glShaders.get(shader)); -}; - -const createProgram = (type) => { - const id = getId(); - glPrograms.set(id, gfx_ctx.createProgram()); - return id; -}; - -const deleteShader = (shader) => { - gfx_ctx.deleteShader(glShaders.get(shader)); -}; - -const deleteProgram = (program) => { - gfx_ctx.deleteProgram(glPrograms.get(program)); -}; - -const enable = (cap) => { - gfx_ctx.enable(cap); -}; - - -const enableVertexAttribArray = (attrib_location) => { - gfx_ctx.enableVertexAttribArray(attrib_location); -}; - -const getShaderParameter = (shader, info) => { - return gfx_ctx.getShaderParameter(glShaders.get(shader), info); -}; - -const getShaderInfoLog = (shader, ptr, len) => { - const msg = gfx_ctx.getShaderInfoLog(glShaders.get(shader)); - const r = writeString(msg, ptr, len); - return r; -}; - -const getProgramParameter = (program_id, info) => { - const program = glPrograms.get(program_id); - return gfx_ctx.getProgramParameter(program, info); -}; - -const getProgramInfoLog = (program, ptr, len) => { - const msg = gfx_ctx.getProgramInfoLog(glPrograms.get(program)); - const r = writeString(msg, ptr, len); - return r; -}; - -const getAttribLocation = (program, ptr, len) => { - const attrib = readString(ptr, len); - return gfx_ctx.getAttribLocation(glPrograms.get(program), attrib); -}; - -const getUniformLocation = (program, ptr, len) => { - const uniform = readString(ptr, len); - const loc = gfx_ctx.getUniformLocation(glPrograms.get(program), uniform); - if (!loc) console.log("Uniform ", uniform, " could not be found"); - if (!loc) return -1; - - const id = getId(); - glUniformLocations.set(id, loc); - return id; -}; - -const linkProgram = (program) => { - gfx_ctx.linkProgram(glPrograms.get(program)); -}; - -const shaderSource = (shader, ptr, len) => { - const source = readString(ptr, len); - gfx_ctx.shaderSource(glShaders.get(shader), source); -}; - -const useProgram = (prog) => { - gfx_ctx.useProgram(glPrograms.get(prog)); -}; - -const uniform1i = (location, v0) => { - gfx_ctx.uniform1i(glUniformLocations.get(location), v0); -}; - -const uniform1f = (location, v0) => { - gfx_ctx.uniform1f(glUniformLocations.get(location), v0); -}; - -const uniform2i = (location, v0, v1) => { - gfx_ctx.uniform2i(glUniformLocations.get(location), v0, v1); -}; - -const uniform2f = (location, v0, v1) => { - gfx_ctx.uniform2f(glUniformLocations.get(location), v0, v1); -}; - -const uniform3f = (location, v0, v1, v2) => { - gfx_ctx.uniform3f(glUniformLocations.get(location), v0, v1, v2); -}; - -const uniform4f = (location, v0, v1, v2, v3) => { - gfx_ctx.uniform4f(glUniformLocations.get(location), v0, v1, v2, v3); -}; - -const uniformMatrix3fv = (location, ptr) => { - const u = glUniformLocations.get(location); - const floats = new Float32Array(memory.buffer, ptr, 9); - - gfx_ctx.uniformMatrix3fv(glUniformLocations.get(location), false, floats); -}; - -const uniformMatrix4fv = (location, ptr) => { - const u = glUniformLocations.get(location); - const floats = new Float32Array(memory.buffer, ptr, 16); - - gfx_ctx.uniformMatrix4fv(glUniformLocations.get(location), false, floats); -}; - -const vertexAttribPointer = (loc, size, type, normalize, stride, offset) => { - gfx_ctx.vertexAttribPointer(loc, size, type, normalize, stride, offset); -}; - -const viewport = (x, y, width, height) => { - gfx_ctx.viewport(x, y, width, height); -}; - -const drawArrays = (mode, first, count) => { - gfx_ctx.drawArrays(mode, first, count); -}; - -const createTexture = () => { - const id = getId(); - glTextures.set(id, gfx_ctx.createTexture()); - return id; -}; - -const bindTexture = (target, tex_id) => { - const texture = glTextures.get(tex_id); - gfx_ctx.bindTexture(target, texture); -}; - -const texImage2D = (target, level, interal_format, - width, height, border, format, - data_type, ptr, count, offset) => { - const data = new Uint8Array(memory.buffer, ptr, count); - gfx_ctx.texImage2D(target, level, interal_format, width, height, border, format, data_type, data, offset); -}; - -const activeTexture = (tex_id) => { - gfx_ctx.activeTexture(tex_id); -}; - -const vertexAttribDivisor = (loc, divisor) => { - gfx_ctx.vertexAttribDivisor(loc, divisor); -}; - -const drawArraysInstanced = (mode, first, count, instanceCount) => { - gfx_ctx.drawArraysInstanced(mode, first, count, instanceCount); -}; - -const getScreenWidth = () => { - return gfx_ctx.drawingBufferWidth; -}; - -const getScreenHeight = () => { - return gfx_ctx.drawingBufferHeight; -}; - -const webgl = { - bindBuffer, - blendFunc, - bufferData, - - createShader, - clear, - clearColor, - createBuffer, - - enable, - - shaderSource, - compileShader, - getShaderParameter, - deleteShader, - getShaderInfoLog, - - createProgram, - deleteProgram, - attachShader, - linkProgram, - getProgramParameter, - getProgramInfoLog, - useProgram, - - getAttribLocation, - getUniformLocation, - createVertexArray, - bindVertexArray, - enableVertexAttribArray, - vertexAttribPointer, - viewport, - drawArrays, - - uniform1i, - uniform1f, - uniform2i, - uniform2f, - uniform3f, - uniform4f, - uniformMatrix3fv, - uniformMatrix4fv, - - createTexture, - bindTexture, - texImage2D, - activeTexture, - - vertexAttribDivisor, - drawArraysInstanced, - - getScreenWidth, - getScreenHeight, -}; +const createWebglBindings = (engine, canvas) => { + const gfx_ctx = canvas.getContext("webgl2"); + if (gfx_ctx === null) { + alert("There was a problem initializing WebGL. Your browser or machine may not support it."); + } + + let next_id = 0; + const getId = () => { + next_id += 1; + return next_id - 1; + }; + + const glBuffers = new Map(); + const glShaders = new Map(); + const glPrograms = new Map(); + const glVertexArrays = new Map(); + const glUniformLocations = new Map(); + const glTextures = new Map(); + + const attachShader = (program_id, shader_id) => { + const program = glPrograms.get(program_id); + const shader = glShaders.get(shader_id); + gfx_ctx.attachShader(program, shader); + }; + + const blendFunc = (sfactor, dfactor) => { + gfx_ctx.blendFunc(sfactor, dfactor); + }; + + const bindBuffer = (target, id) => { + gfx_ctx.bindBuffer(target, glBuffers.get(id)); + }; + + const bufferData = (target, ptr, len, usage) => { + const floats = new Float32Array(memory.buffer, ptr, len); + gfx_ctx.bufferData(target, floats, usage); + }; + + const bindVertexArray = (vao) => { + gfx_ctx.bindVertexArray(glVertexArrays.get(vao)); + }; + + const createVertexArray = () => { + const id = getId(); + glVertexArrays.set(id, gfx_ctx.createVertexArray()); + return id; + }; + + const clearColor = (r, g, b, a) => { + gfx_ctx.clearColor(r, g, b, a); + }; + + const clear = (mask) => { + gfx_ctx.clear(mask); + }; + + const createBuffer = () => { + const id = getId(); + glBuffers.set(id, gfx_ctx.createBuffer()); + return id; + }; + + const createShader = (type) => { + const id = getId(); + glShaders.set(id, gfx_ctx.createShader(type)); + return id; + }; + + const compileShader = (shader) => { + gfx_ctx.compileShader(glShaders.get(shader)); + }; + + const createProgram = (type) => { + const id = getId(); + glPrograms.set(id, gfx_ctx.createProgram()); + return id; + }; + + const deleteShader = (shader) => { + gfx_ctx.deleteShader(glShaders.get(shader)); + }; + + const deleteProgram = (program) => { + gfx_ctx.deleteProgram(glPrograms.get(program)); + }; + + const enable = (cap) => { + gfx_ctx.enable(cap); + }; + + + const enableVertexAttribArray = (attrib_location) => { + gfx_ctx.enableVertexAttribArray(attrib_location); + }; + + const getShaderParameter = (shader, info) => { + return gfx_ctx.getShaderParameter(glShaders.get(shader), info); + }; + + const getShaderInfoLog = (shader, ptr, len) => { + const msg = gfx_ctx.getShaderInfoLog(glShaders.get(shader)); + const r = engine.writeString(msg, ptr, len); + return r; + }; + + const getProgramParameter = (program_id, info) => { + const program = glPrograms.get(program_id); + return gfx_ctx.getProgramParameter(program, info); + }; + + const getProgramInfoLog = (program, ptr, len) => { + const msg = gfx_ctx.getProgramInfoLog(glPrograms.get(program)); + const r = engine.writeString(msg, ptr, len); + return r; + }; + + const getAttribLocation = (program, ptr, len) => { + const attrib = engine.readString(ptr, len); + return gfx_ctx.getAttribLocation(glPrograms.get(program), attrib); + }; + + const getUniformLocation = (program, ptr, len) => { + const uniform = engine.readString(ptr, len); + const loc = gfx_ctx.getUniformLocation(glPrograms.get(program), uniform); + if (!loc) console.log("Uniform ", uniform, " could not be found"); + if (!loc) return -1; + + const id = getId(); + glUniformLocations.set(id, loc); + return id; + }; + + const linkProgram = (program) => { + gfx_ctx.linkProgram(glPrograms.get(program)); + }; + + const shaderSource = (shader, ptr, len) => { + const source = engine.readString(ptr, len); + gfx_ctx.shaderSource(glShaders.get(shader), source); + }; + + const useProgram = (prog) => { + gfx_ctx.useProgram(glPrograms.get(prog)); + }; + + const uniform1i = (location, v0) => { + gfx_ctx.uniform1i(glUniformLocations.get(location), v0); + }; + + const uniform1f = (location, v0) => { + gfx_ctx.uniform1f(glUniformLocations.get(location), v0); + }; + + const uniform2i = (location, v0, v1) => { + gfx_ctx.uniform2i(glUniformLocations.get(location), v0, v1); + }; + + const uniform2f = (location, v0, v1) => { + gfx_ctx.uniform2f(glUniformLocations.get(location), v0, v1); + }; + + const uniform3f = (location, v0, v1, v2) => { + gfx_ctx.uniform3f(glUniformLocations.get(location), v0, v1, v2); + }; + + const uniform4f = (location, v0, v1, v2, v3) => { + gfx_ctx.uniform4f(glUniformLocations.get(location), v0, v1, v2, v3); + }; + + const uniformMatrix3fv = (location, ptr) => { + const u = glUniformLocations.get(location); + const floats = new Float32Array(memory.buffer, ptr, 9); + + gfx_ctx.uniformMatrix3fv(glUniformLocations.get(location), false, floats); + }; + + const uniformMatrix4fv = (location, ptr) => { + const u = glUniformLocations.get(location); + const floats = new Float32Array(memory.buffer, ptr, 16); + + gfx_ctx.uniformMatrix4fv(glUniformLocations.get(location), false, floats); + }; + + const vertexAttribPointer = (loc, size, type, normalize, stride, offset) => { + gfx_ctx.vertexAttribPointer(loc, size, type, normalize, stride, offset); + }; + + const viewport = (x, y, width, height) => { + gfx_ctx.viewport(x, y, width, height); + }; + + const drawArrays = (mode, first, count) => { + gfx_ctx.drawArrays(mode, first, count); + }; + + const createTexture = () => { + const id = getId(); + glTextures.set(id, gfx_ctx.createTexture()); + return id; + }; + + const bindTexture = (target, tex_id) => { + const texture = glTextures.get(tex_id); + gfx_ctx.bindTexture(target, texture); + }; + + const texImage2D = (target, level, interal_format, + width, height, border, format, + data_type, ptr, count, offset) => { + const data = new Uint8Array(memory.buffer, ptr, count); + gfx_ctx.texImage2D(target, level, interal_format, width, height, border, format, data_type, data, offset); + }; + + const activeTexture = (tex_id) => { + gfx_ctx.activeTexture(tex_id); + }; + + const vertexAttribDivisor = (loc, divisor) => { + gfx_ctx.vertexAttribDivisor(loc, divisor); + }; + + const drawArraysInstanced = (mode, first, count, instanceCount) => { + gfx_ctx.drawArraysInstanced(mode, first, count, instanceCount); + }; + + const getScreenWidth = () => { + return gfx_ctx.drawingBufferWidth; + }; + + const getScreenHeight = () => { + return gfx_ctx.drawingBufferHeight; + }; + + return { + bindBuffer, + blendFunc, + bufferData, + + createShader, + clear, + clearColor, + createBuffer, + + enable, + + shaderSource, + compileShader, + getShaderParameter, + deleteShader, + getShaderInfoLog, + + createProgram, + deleteProgram, + attachShader, + linkProgram, + getProgramParameter, + getProgramInfoLog, + useProgram, + + getAttribLocation, + getUniformLocation, + createVertexArray, + bindVertexArray, + enableVertexAttribArray, + vertexAttribPointer, + viewport, + drawArrays, + + uniform1i, + uniform1f, + uniform2i, + uniform2f, + uniform3f, + uniform4f, + uniformMatrix3fv, + uniformMatrix4fv, + + createTexture, + bindTexture, + texImage2D, + activeTexture, + + vertexAttribDivisor, + drawArraysInstanced, + + getScreenWidth, + getScreenHeight, + }; +}; + +//const canvas = document.getElementById("app-canvas"); +//const gfx_ctx = canvas.getContext("webgl2"); +//if (gfx_ctx === null) { + // alert("There was a problem initializing WebGL. Your browser or machine may not support it."); + //} +// + //let next_id = 0; +//const getId = () => { + // next_id += 1; + // return next_id - 1; + //}; +// + //const glBuffers = new Map(); +//const glShaders = new Map(); +//const glPrograms = new Map(); +//const glVertexArrays = new Map(); +//const glUniformLocations = new Map(); +//const glTextures = new Map(); +// + //const attachShader = (program_id, shader_id) => { + // const program = glPrograms.get(program_id); + // const shader = glShaders.get(shader_id); + // gfx_ctx.attachShader(program, shader); + //}; +// + //const blendFunc = (sfactor, dfactor) => { + // gfx_ctx.blendFunc(sfactor, dfactor); + //}; +// + //const bindBuffer = (target, id) => { + // gfx_ctx.bindBuffer(target, glBuffers.get(id)); + //}; +// + //const bufferData = (target, ptr, len, usage) => { + // const floats = new Float32Array(memory.buffer, ptr, len); + // gfx_ctx.bufferData(target, floats, usage); + //}; +// + //const bindVertexArray = (vao) => { + // gfx_ctx.bindVertexArray(glVertexArrays.get(vao)); + //}; +// + //const createVertexArray = () => { + // const id = getId(); + // glVertexArrays.set(id, gfx_ctx.createVertexArray()); + // return id; + //}; +// + //const clearColor = (r, g, b, a) => { + // gfx_ctx.clearColor(r, g, b, a); + //}; +// + //const clear = (mask) => { + // gfx_ctx.clear(mask); + //}; +// + //const createBuffer = () => { + // const id = getId(); + // glBuffers.set(id, gfx_ctx.createBuffer()); + // return id; + //}; +// + //const createShader = (type) => { + // const id = getId(); + // glShaders.set(id, gfx_ctx.createShader(type)); + // return id; + //}; +// + //const compileShader = (shader) => { + // gfx_ctx.compileShader(glShaders.get(shader)); + //}; +// + //const createProgram = (type) => { + // const id = getId(); + // glPrograms.set(id, gfx_ctx.createProgram()); + // return id; + //}; +// + //const deleteShader = (shader) => { + // gfx_ctx.deleteShader(glShaders.get(shader)); + //}; +// + //const deleteProgram = (program) => { + // gfx_ctx.deleteProgram(glPrograms.get(program)); + //}; +// + //const enable = (cap) => { + // gfx_ctx.enable(cap); + //}; +// + // + //const enableVertexAttribArray = (attrib_location) => { + // gfx_ctx.enableVertexAttribArray(attrib_location); + //}; +// + //const getShaderParameter = (shader, info) => { + // return gfx_ctx.getShaderParameter(glShaders.get(shader), info); + //}; +// + //const getShaderInfoLog = (shader, ptr, len) => { + // const msg = gfx_ctx.getShaderInfoLog(glShaders.get(shader)); + // const r = writeString(msg, ptr, len); + // return r; + //}; +// + //const getProgramParameter = (program_id, info) => { + // const program = glPrograms.get(program_id); + // return gfx_ctx.getProgramParameter(program, info); + //}; +// + //const getProgramInfoLog = (program, ptr, len) => { + // const msg = gfx_ctx.getProgramInfoLog(glPrograms.get(program)); + // const r = writeString(msg, ptr, len); + // return r; + //}; +// + //const getAttribLocation = (program, ptr, len) => { + // const attrib = readString(ptr, len); + // return gfx_ctx.getAttribLocation(glPrograms.get(program), attrib); + //}; +// + //const getUniformLocation = (program, ptr, len) => { + // const uniform = readString(ptr, len); + // const loc = gfx_ctx.getUniformLocation(glPrograms.get(program), uniform); + // if (!loc) console.log("Uniform ", uniform, " could not be found"); + // if (!loc) return -1; + // + // const id = getId(); + // glUniformLocations.set(id, loc); + // return id; + //}; +// + //const linkProgram = (program) => { + // gfx_ctx.linkProgram(glPrograms.get(program)); + //}; +// + //const shaderSource = (shader, ptr, len) => { + // const source = readString(ptr, len); + // gfx_ctx.shaderSource(glShaders.get(shader), source); + //}; +// + //const useProgram = (prog) => { + // gfx_ctx.useProgram(glPrograms.get(prog)); + //}; +// + //const uniform1i = (location, v0) => { + // gfx_ctx.uniform1i(glUniformLocations.get(location), v0); + //}; +// + //const uniform1f = (location, v0) => { + // gfx_ctx.uniform1f(glUniformLocations.get(location), v0); + //}; +// + //const uniform2i = (location, v0, v1) => { + // gfx_ctx.uniform2i(glUniformLocations.get(location), v0, v1); + //}; +// + //const uniform2f = (location, v0, v1) => { + // gfx_ctx.uniform2f(glUniformLocations.get(location), v0, v1); + //}; +// + //const uniform3f = (location, v0, v1, v2) => { + // gfx_ctx.uniform3f(glUniformLocations.get(location), v0, v1, v2); + //}; +// + //const uniform4f = (location, v0, v1, v2, v3) => { + // gfx_ctx.uniform4f(glUniformLocations.get(location), v0, v1, v2, v3); + //}; +// + //const uniformMatrix3fv = (location, ptr) => { + // const u = glUniformLocations.get(location); + // const floats = new Float32Array(memory.buffer, ptr, 9); + // + // gfx_ctx.uniformMatrix3fv(glUniformLocations.get(location), false, floats); + //}; +// + //const uniformMatrix4fv = (location, ptr) => { + // const u = glUniformLocations.get(location); + // const floats = new Float32Array(memory.buffer, ptr, 16); + // + // gfx_ctx.uniformMatrix4fv(glUniformLocations.get(location), false, floats); + //}; +// + //const vertexAttribPointer = (loc, size, type, normalize, stride, offset) => { + // gfx_ctx.vertexAttribPointer(loc, size, type, normalize, stride, offset); + //}; +// + //const viewport = (x, y, width, height) => { + // gfx_ctx.viewport(x, y, width, height); + //}; +// + //const drawArrays = (mode, first, count) => { + // gfx_ctx.drawArrays(mode, first, count); + //}; +// + //const createTexture = () => { + // const id = getId(); + // glTextures.set(id, gfx_ctx.createTexture()); + // return id; + //}; +// + //const bindTexture = (target, tex_id) => { + // const texture = glTextures.get(tex_id); + // gfx_ctx.bindTexture(target, texture); + //}; +// + //const texImage2D = (target, level, interal_format, + // width, height, border, format, + // data_type, ptr, count, offset) => { + // const data = new Uint8Array(memory.buffer, ptr, count); + // gfx_ctx.texImage2D(target, level, interal_format, width, height, border, format, data_type, data, offset); + //}; +// + //const activeTexture = (tex_id) => { + // gfx_ctx.activeTexture(tex_id); + //}; +// + //const vertexAttribDivisor = (loc, divisor) => { + // gfx_ctx.vertexAttribDivisor(loc, divisor); + //}; +// + //const drawArraysInstanced = (mode, first, count, instanceCount) => { + // gfx_ctx.drawArraysInstanced(mode, first, count, instanceCount); + //}; +// + //const getScreenWidth = () => { + // return gfx_ctx.drawingBufferWidth; + //}; +// + //const getScreenHeight = () => { + // return gfx_ctx.drawingBufferHeight; + //}; +// + //const webgl = { + // bindBuffer, + // blendFunc, + // bufferData, + // + // createShader, + // clear, + // clearColor, + // createBuffer, + // + // enable, + // + // shaderSource, + // compileShader, + // getShaderParameter, + // deleteShader, + // getShaderInfoLog, + // + // createProgram, + // deleteProgram, + // attachShader, + // linkProgram, + // getProgramParameter, + // getProgramInfoLog, + // useProgram, + // + // getAttribLocation, + // getUniformLocation, + // createVertexArray, + // bindVertexArray, + // enableVertexAttribArray, + // vertexAttribPointer, + // viewport, + // drawArrays, + // + // uniform1i, + // uniform1f, + // uniform2i, + // uniform2f, + // uniform3f, + // uniform4f, + // uniformMatrix3fv, + // uniformMatrix4fv, + // + // createTexture, + // bindTexture, + // texImage2D, + // activeTexture, + // + // vertexAttribDivisor, + // drawArraysInstanced, + // + // getScreenWidth, + // getScreenHeight, + //}; diff --git a/src/wasm.zig b/src/wasm.zig index e1ddaab..b149d60 100644 --- a/src/wasm.zig +++ b/src/wasm.zig @@ -36,6 +36,18 @@ export fn mouseEvent( } }); } +/// Javascript always fills the event.key property. For keys that can be represented +/// in text, it simply fills the value with the text representation of that key, +/// but for special keys like Alt, Shift, and others, it fills the key property with +/// a string with the name of the key (???? Psychotic.) So the web shell converts +/// those string representations to values in the private use area of unicode codepoints. +/// +/// Those representations are then repeated here. In the event that the codepoint +/// property is used for user text input, these values should be filtered out somehow. +pub const SpecialKeyCodepoints = enum(u32) { + shift = 0xE000, +}; + export fn keyEvent(codepoint: u32, is_press: bool, is_repeat: bool) void { handleInput(.{ .key = .{ .codepoint = codepoint, |