mirror of
https://github.com/zserge/fenster.git
synced 2025-07-20 10:46:08 +03:00
104 lines
2.7 KiB
C
104 lines
2.7 KiB
C
// this is an emscripten-only implementation of fenster
|
|
// make sure to add -sASYNCIFY
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include "emscripten.h"
|
|
|
|
// offsets
|
|
struct fenster { // byte 32bit
|
|
const char *title; // 0 0
|
|
const int width; // 4 1
|
|
const int height; // 8 2
|
|
uint32_t *buf; // 12 3
|
|
int keys[256]; // 16 4
|
|
int mod; // 1040 257
|
|
int x; // 1044 258
|
|
int y; // 1048 259
|
|
int mouse; // 1052 260
|
|
};
|
|
|
|
#define fenster_pixel(f, x, y) ((f)->buf[((y) * (f)->width) + (x)])
|
|
#define fenster_sleep emscripten_sleep
|
|
|
|
static bool running = true;
|
|
|
|
EM_JS(int, fenster_open, (struct fenster *f), {
|
|
if (!Module.canvas) {
|
|
Module.canvas = document.getElementById('canvas');
|
|
if (!Module.canvas) {
|
|
document.createElement("canvas");
|
|
document.appendElement(Module.canvas);
|
|
}
|
|
}
|
|
const p32 = f/4;
|
|
const width = Module.HEAP32[p32 + 1];
|
|
const height = Module.HEAP32[p32 + 2];
|
|
Module.canvas.width = width;
|
|
Module.canvas.height = height;
|
|
Module.ctx = canvas.getContext("2d");
|
|
Module.screen = Module.ctx.getImageData(0, 0, width, height);
|
|
|
|
// TODO: handle mod
|
|
|
|
Module.canvas.addEventListener('mousemove', e => {
|
|
Module.HEAP32[p32 + 258] = e.offsetX;
|
|
Module.HEAP32[p32 + 259] = e.offsetY;
|
|
});
|
|
|
|
Module.canvas.addEventListener('mousedown', e => {
|
|
Module.HEAP32[p32 + 260] = e.which;
|
|
});
|
|
|
|
Module.canvas.addEventListener('mouseup', e => {
|
|
Module.HEAP32[p32 + 260] = 0;
|
|
});
|
|
|
|
Module.canvas.addEventListener('keydown', e => {
|
|
Module.HEAP32[p32 + 4 + e.keyCode] = 1;
|
|
});
|
|
|
|
Module.canvas.addEventListener('keyup', e => {
|
|
Module.HEAP32[p32 + 4 + e.keyCode] = 0;
|
|
});
|
|
});
|
|
|
|
EM_JS(void, emscripten_fenster_loop, (int width, int height, uint32_t* buf), {
|
|
const byteSize = width * height * 4;
|
|
const buffer = Module.HEAPU8.subarray(buf, buf + byteSize);
|
|
// set alpha to 100% and re-arrange RGBA
|
|
let r,g,b = 0;
|
|
for (let i=0;i<byteSize;i+=4) {
|
|
r = buffer[i+2];
|
|
g = buffer[i+1];
|
|
b = buffer[i+0];
|
|
buffer[i+0] = r;
|
|
buffer[i+1] = g;
|
|
buffer[i+2] = b;
|
|
buffer[i+3] = 0xff;
|
|
}
|
|
Module.screen.data.set(buffer);
|
|
Module.ctx.putImageData(Module.screen, 0, 0);
|
|
});
|
|
|
|
int fenster_loop(struct fenster *f) {
|
|
if (running) {
|
|
emscripten_fenster_loop(f->width, f->height, f->buf);
|
|
}
|
|
|
|
// this is hack to make it not pin the main-loop (~60fps)
|
|
// better would be if we can wrap the loop with emscripten_set_main_loop
|
|
// which also does not require ASYNCIFY
|
|
emscripten_sleep(16);
|
|
|
|
return running ? 0 : 1;
|
|
}
|
|
|
|
void fenster_close(struct fenster *f) {
|
|
running = false;
|
|
}
|
|
|
|
EM_JS(int64_t, fenster_time, (void), {
|
|
return (new Date()).time;
|
|
});
|