a whole load of work in progress
This commit is contained in:
parent
caec0b8ac9
commit
26ba098183
63 changed files with 3234 additions and 321 deletions
198
static/index.js
198
static/index.js
|
@ -1,154 +1,74 @@
|
|||
let panicImpl;
|
||||
let logImpl;
|
||||
import { Painter } from "./painter.js";
|
||||
import { Wall } from "./wall.js";
|
||||
import { Haku } from "./haku.js";
|
||||
import { getUserId, newSession, waitForLogin } from "./session.js";
|
||||
import { debounce } from "./framework.js";
|
||||
|
||||
function makeLogFunction(level) {
|
||||
return (length, pMessage) => {
|
||||
logImpl(level, length, pMessage);
|
||||
};
|
||||
}
|
||||
let main = document.querySelector("main");
|
||||
let canvasRenderer = main.querySelector("rkgk-canvas-renderer");
|
||||
let reticleRenderer = main.querySelector("rkgk-reticle-renderer");
|
||||
let brushEditor = main.querySelector("rkgk-brush-editor");
|
||||
|
||||
let { instance: hakuInstance, module: hakuModule } = await WebAssembly.instantiateStreaming(
|
||||
fetch(import.meta.resolve("./wasm/haku.wasm")),
|
||||
{
|
||||
env: {
|
||||
panic(length, pMessage) {
|
||||
panicImpl(length, pMessage);
|
||||
},
|
||||
trace: makeLogFunction("trace"),
|
||||
debug: makeLogFunction("debug"),
|
||||
info: makeLogFunction("info"),
|
||||
warn: makeLogFunction("warn"),
|
||||
error: makeLogFunction("error"),
|
||||
},
|
||||
},
|
||||
);
|
||||
let haku = new Haku();
|
||||
let painter = new Painter(512);
|
||||
|
||||
let memory = hakuInstance.exports.memory;
|
||||
let w = hakuInstance.exports;
|
||||
reticleRenderer.connectViewport(canvasRenderer.viewport);
|
||||
canvasRenderer.addEventListener(".viewportUpdate", () => reticleRenderer.updateTransform());
|
||||
|
||||
let textEncoder = new TextEncoder();
|
||||
function allocString(string) {
|
||||
let size = string.length * 3;
|
||||
let align = 1;
|
||||
let pString = w.haku_alloc(size, align);
|
||||
// In the background, connect to the server.
|
||||
(async () => {
|
||||
await waitForLogin();
|
||||
console.info("login ready! starting session");
|
||||
|
||||
let buffer = new Uint8Array(memory.buffer, pString, size);
|
||||
let result = textEncoder.encodeInto(string, buffer);
|
||||
let session = await newSession(getUserId(), localStorage.getItem("rkgk.mostRecentWallId"));
|
||||
localStorage.setItem("rkgk.mostRecentWallId", session.wallId);
|
||||
|
||||
return {
|
||||
ptr: pString,
|
||||
length: result.written,
|
||||
size,
|
||||
align,
|
||||
};
|
||||
}
|
||||
let wall = new Wall(session.wallInfo.chunkSize);
|
||||
canvasRenderer.initialize(wall);
|
||||
|
||||
function freeString(alloc) {
|
||||
w.haku_free(alloc.ptr, alloc.size, alloc.align);
|
||||
}
|
||||
|
||||
let textDecoder = new TextDecoder();
|
||||
function readString(size, pString) {
|
||||
let buffer = new Uint8Array(memory.buffer, pString, size);
|
||||
return textDecoder.decode(buffer);
|
||||
}
|
||||
|
||||
function readCString(pCString) {
|
||||
let memoryBuffer = new Uint8Array(memory.buffer);
|
||||
|
||||
let pCursor = pCString;
|
||||
while (memoryBuffer[pCursor] != 0 && memoryBuffer[pCursor] != null) {
|
||||
pCursor++;
|
||||
for (let onlineUser of session.wallInfo.online) {
|
||||
wall.onlineUsers.addUser(onlineUser.sessionId, { nickname: onlineUser.nickname });
|
||||
}
|
||||
|
||||
let size = pCursor - pCString;
|
||||
return readString(size, pCString);
|
||||
}
|
||||
session.addEventListener("error", (event) => console.error(event));
|
||||
session.addEventListener("action", (event) => {
|
||||
if (event.kind.event == "cursor") {
|
||||
let reticle = reticleRenderer.getOrAddReticle(wall.onlineUsers, event.sessionId);
|
||||
let { x, y } = event.kind.position;
|
||||
reticle.setCursor(x, y);
|
||||
}
|
||||
});
|
||||
|
||||
class Panic extends Error {
|
||||
name = "Panic";
|
||||
}
|
||||
let compileBrush = () => haku.setBrush(brushEditor.code);
|
||||
compileBrush();
|
||||
brushEditor.addEventListener(".codeChanged", () => compileBrush());
|
||||
|
||||
panicImpl = (length, pMessage) => {
|
||||
throw new Panic(readString(length, pMessage));
|
||||
};
|
||||
let reportCursor = debounce(1000 / 60, (x, y) => session.reportCursor(x, y));
|
||||
canvasRenderer.addEventListener(".cursor", async (event) => {
|
||||
reportCursor(event.x, event.y);
|
||||
});
|
||||
|
||||
logImpl = (level, length, pMessage) => {
|
||||
console[level](readString(length, pMessage));
|
||||
};
|
||||
canvasRenderer.addEventListener(".paint", async (event) => {
|
||||
painter.renderBrush(haku);
|
||||
let imageBitmap = await painter.createImageBitmap();
|
||||
|
||||
w.haku_init_logging();
|
||||
let left = event.x - painter.paintArea / 2;
|
||||
let top = event.y - painter.paintArea / 2;
|
||||
|
||||
/* ------ */
|
||||
let leftChunk = Math.floor(left / wall.chunkSize);
|
||||
let topChunk = Math.floor(top / wall.chunkSize);
|
||||
let rightChunk = Math.ceil((left + painter.paintArea) / wall.chunkSize);
|
||||
let bottomChunk = Math.ceil((top + painter.paintArea) / wall.chunkSize);
|
||||
for (let chunkY = topChunk; chunkY < bottomChunk; ++chunkY) {
|
||||
for (let chunkX = leftChunk; chunkX < rightChunk; ++chunkX) {
|
||||
let chunk = wall.getOrCreateChunk(chunkX, chunkY);
|
||||
let x = Math.floor(-chunkX * wall.chunkSize + left);
|
||||
let y = Math.floor(-chunkY * wall.chunkSize + top);
|
||||
chunk.ctx.drawImage(imageBitmap, x, y);
|
||||
}
|
||||
}
|
||||
imageBitmap.close();
|
||||
});
|
||||
|
||||
let renderCanvas = document.getElementById("render");
|
||||
let codeTextArea = document.getElementById("code");
|
||||
let outputP = document.getElementById("output");
|
||||
|
||||
let ctx = renderCanvas.getContext("2d");
|
||||
|
||||
function rerender() {
|
||||
console.log("rerender");
|
||||
|
||||
let width = renderCanvas.width;
|
||||
let height = renderCanvas.height;
|
||||
|
||||
let logs = [];
|
||||
|
||||
let pInstance = w.haku_instance_new();
|
||||
let pBrush = w.haku_brush_new();
|
||||
let pBitmap = w.haku_bitmap_new(width, height);
|
||||
let code = allocString(codeTextArea.value);
|
||||
let deallocEverything = () => {
|
||||
freeString(code);
|
||||
w.haku_bitmap_destroy(pBitmap);
|
||||
w.haku_brush_destroy(pBrush);
|
||||
w.haku_instance_destroy(pInstance);
|
||||
outputP.textContent = logs.join("\n");
|
||||
};
|
||||
|
||||
let compileStatusCode = w.haku_compile_brush(pInstance, pBrush, code.length, code.ptr);
|
||||
let pCompileStatusString = w.haku_status_string(compileStatusCode);
|
||||
logs.push(`compile: ${readCString(pCompileStatusString)}`);
|
||||
|
||||
for (let i = 0; i < w.haku_num_diagnostics(pBrush); ++i) {
|
||||
let start = w.haku_diagnostic_start(pBrush, i);
|
||||
let end = w.haku_diagnostic_end(pBrush, i);
|
||||
let length = w.haku_diagnostic_message_len(pBrush, i);
|
||||
let pMessage = w.haku_diagnostic_message(pBrush, i);
|
||||
let message = readString(length, pMessage);
|
||||
logs.push(`${start}..${end}: ${message}`);
|
||||
}
|
||||
|
||||
if (w.haku_num_diagnostics(pBrush) > 0) {
|
||||
deallocEverything();
|
||||
return;
|
||||
}
|
||||
|
||||
let renderStatusCode = w.haku_render_brush(pInstance, pBrush, pBitmap);
|
||||
let pRenderStatusString = w.haku_status_string(renderStatusCode);
|
||||
logs.push(`render: ${readCString(pRenderStatusString)}`);
|
||||
|
||||
if (w.haku_has_exception(pInstance)) {
|
||||
let length = w.haku_exception_message_len(pInstance);
|
||||
let pMessage = w.haku_exception_message(pInstance);
|
||||
let message = readString(length, pMessage);
|
||||
logs.push(`exception: ${message}`);
|
||||
|
||||
deallocEverything();
|
||||
return;
|
||||
}
|
||||
|
||||
let pBitmapData = w.haku_bitmap_data(pBitmap);
|
||||
let bitmapDataBuffer = new Float32Array(memory.buffer, pBitmapData, width * height * 4);
|
||||
let imageData = new ImageData(width, height);
|
||||
for (let i = 0; i < bitmapDataBuffer.length; ++i) {
|
||||
imageData.data[i] = bitmapDataBuffer[i] * 255;
|
||||
}
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
|
||||
deallocEverything();
|
||||
}
|
||||
|
||||
rerender();
|
||||
codeTextArea.addEventListener("input", rerender);
|
||||
session.eventLoop();
|
||||
})();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue