| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- #include "plugin_api.h"
- #include "iron_armpack.h"
- #include "iron_array.h"
- #include "iron_map.h"
- #include "iron_mat4.h"
- #include "iron_obj.h"
- #include "iron_ui.h"
- #include "iron_ui_nodes.h"
- #include "iron_vec4.h"
- void plugin_embed();
- // ██╗ ██╗██████╗
- // ██║ ██║██╔══██╗
- // ██║ ██║██████╔╝
- // ██║ ██║██╔══██╗
- // ███████╗██║██████╔╝
- // ╚══════╝╚═╝╚═════╝
- const char *lib = "\
- function buffer_to_string(b) {\
- let str = \"\";\
- let u8a = new Uint8Array(b);\
- for (let i = 0; i < u8a.length; ++i) {\
- str += String.fromCharCode(u8a[i]);\
- }\
- return str;\
- }\
- \
- function string_to_buffer(str) {\
- let u8a = new Uint8Array(str.length);\
- for (let i = 0; i < str.length; ++i) {\
- u8a[i] = str.charCodeAt(i);\
- }\
- return u8a.buffer;\
- }\
- \
- let pos = 0;\
- let k_type = \"\";\
- \
- function armpack_decode(b) {\
- pos = 0;\
- return read(new DataView(b));\
- }\
- \
- function read_u8(v) {\
- let i = v.getUint8(pos);\
- pos++;\
- return i;\
- }\
- \
- function read_i16(v) {\
- let i = v.getInt16(pos, true);\
- pos += 2;\
- return i;\
- }\
- \
- function read_i32(v) {\
- let i = v.getInt32(pos, true);\
- pos += 4;\
- return i;\
- }\
- \
- function read_u32(v) {\
- let i = v.getUint32(pos, true);\
- pos += 4;\
- return i;\
- }\
- \
- function read_f32(v) {\
- let f = v.getFloat32(pos, true);\
- pos += 4;\
- return f;\
- }\
- \
- function read_string(v, len) {\
- let s = \"\";\
- for (let i = 0; i < len; ++i) {\
- s += String.fromCharCode(read_u8(v));\
- }\
- return s;\
- }\
- \
- function read(v) {\
- let b = read_u8(v);\
- switch (b) {\
- case 0xc0: return null;\
- case 0xc2: return false;\
- case 0xc3: return true;\
- case 0xca: { k_type = \"__f32\"; return read_f32(v); }\
- case 0xd2: return read_i32(v);\
- case 0xdb: return read_string(v, read_u32(v));\
- case 0xdd: return read_array(v, read_i32(v));\
- case 0xdf: return read_map(v, read_i32(v));\
- }\
- return 0;\
- }\
- \
- function read_array(v, length) {\
- let b = read_u8(v);\
- \
- if (b == 0xca) { /* Typed f32 */ \
- let a = new Array(length);\
- for (let x = 0; x < length; ++x) a[x] = read_f32(v);\
- k_type = \"__f32\";\
- return a;\
- }\
- else if (b == 0xd2) { /* Typed i32 */ \
- let a = new Array(length);\
- for (let x = 0; x < length; ++x) a[x] = read_i32(v);\
- k_type = \"__i32\";\
- return a;\
- }\
- else if (b == 0xd1) { /* Typed i16 */ \
- let a = new Array(length);\
- for (let x = 0; x < length; ++x) a[x] = read_i16(v);\
- k_type = \"__i16\";\
- return a;\
- }\
- else if (b == 0xc4) { /* Typed u8 */ \
- let a = new Array(length);\
- for (let x = 0; x < length; ++x) a[x] = read_u8(v);\
- k_type = \"__u8\";\
- return a;\
- }\
- else { /* Dynamic type-value */ \
- pos--;\
- let a = new Array(length);\
- for (let x = 0; x < length; ++x) a[x] = read(v);\
- return a;\
- }\
- }\
- \
- function read_map(v, length) {\
- let out = {};\
- for (let n = 0; n < length; ++n) {\
- let k = read(v);\
- k_type = \"\";\
- let val = read(v);\
- k += k_type;\
- k_type = \"\";\
- out[k] = val;\
- }\
- return out;\
- }\
- \
- function armpack_encode(d) {\
- pos = 0;\
- write_dummy(d);\
- let b = new ArrayBuffer(pos);\
- let v = new DataView(b);\
- pos = 0;\
- write(v, d);\
- return b;\
- }\
- \
- function write_u8(v, i) {\
- v.setUint8(pos, i);\
- pos += 1;\
- }\
- \
- function write_i16(v, i) {\
- v.setInt16(pos, i, true);\
- pos += 2;\
- }\
- \
- function write_i32(v, i) {\
- v.setInt32(pos, i, true);\
- pos += 4;\
- }\
- \
- function write_f32(v, f) {\
- v.setFloat32(pos, f, true);\
- pos += 4;\
- }\
- \
- function write_string(v, str) {\
- for (let i = 0; i < str.length; ++i) {\
- write_u8(v, str.charCodeAt(i));\
- }\
- }\
- \
- function write(v, d) {\
- if (d == null) {\
- write_u8(v, 0xc0);\
- }\
- else if (typeof d == \"boolean\") {\
- write_u8(v, d ? 0xc3 : 0xc2);\
- }\
- else if (typeof d == \"number\") {\
- if (Number.isInteger(d) && k_type != \"__f32\") {\
- write_u8(v, 0xd2);\
- write_i32(v, d);\
- }\
- else {\
- write_u8(v, 0xca);\
- write_f32(v, d);\
- }\
- }\
- else if (typeof d == \"string\") {\
- write_u8(v, 0xdb);\
- write_i32(v, d.length);\
- write_string(v, d);\
- }\
- else if (Array.isArray(d)) {\
- write_u8(v, 0xdd);\
- write_i32(v, d.length);\
- if (k_type == \"__u8\") {\
- write_u8(v, 0xc4);\
- for (let i = 0; i < d.length; ++i) {\
- write_u8(v, d[i]);\
- }\
- }\
- else if (k_type == \"__i16\") {\
- write_u8(v, 0xd1);\
- for (let i = 0; i < d.length; ++i) {\
- write_i16(v, d[i]);\
- }\
- }\
- else if (k_type == \"__f32\") {\
- write_u8(v, 0xca);\
- for (let i = 0; i < d.length; ++i) {\
- write_f32(v, d[i]);\
- }\
- }\
- else if (k_type == \"__i32\") {\
- write_u8(v, 0xd2);\
- for (let i = 0; i < d.length; ++i) {\
- write_i32(v, d[i]);\
- }\
- }\
- else {\
- for (let i = 0; i < d.length; ++i) {\
- write(v, d[i]);\
- }\
- }\
- }\
- else {\
- write_object(v, d);\
- }\
- }\
- \
- function write_object(v, d) {\
- let f = Object.keys(d);\
- write_u8(v, 0xdf);\
- write_i32(v, f.length);\
- for (let i = 0; i < f.length; ++i) {\
- let k = f[i];\
- \
- k_type = \"\";\
- if (k.endsWith(\"__f32\")) {\
- k_type = \"__f32\";\
- }\
- else if (k.endsWith(\"__i32\")) {\
- k_type = \"__i32\";\
- }\
- else if (k.endsWith(\"__i16\")) {\
- k_type = \"__i16\";\
- }\
- else if (k.endsWith(\"__u8\")) {\
- k_type = \"__u8\";\
- }\
- \
- write_u8(v, 0xdb);\
- write_i32(v, k.length - k_type.length);\
- \
- write_string(v, k.substring(0, k.length - k_type.length));\
- write(v, d[k]);\
- k_type = \"\";\
- }\
- }\
- \
- function write_dummy(d) {\
- if (d == null) {\
- pos += 1;\
- }\
- else if (typeof d == \"boolean\") {\
- pos += 1;\
- }\
- else if (typeof d == \"number\") {\
- pos += 1;\
- pos += 4;\
- }\
- else if (typeof d == \"string\") {\
- pos += 1;\
- pos += 4;\
- pos += d.length;\
- }\
- else if (Array.isArray(d)) {\
- pos += 1;\
- pos += 4;\
- if (k_type == \"__u8\") {\
- pos += 1;\
- for (let i = 0; i < d.length; ++i) {\
- pos += 1;\
- }\
- }\
- else if (k_type == \"__i16\") {\
- pos += 1;\
- for (let i = 0; i < d.length; ++i) {\
- pos += 2;\
- }\
- }\
- else if (k_type == \"__f32\") {\
- pos += 1;\
- for (let i = 0; i < d.length; ++i) {\
- pos += 4;\
- }\
- }\
- else if (k_type == \"__i32\") {\
- pos += 1;\
- for (let i = 0; i < d.length; ++i) {\
- pos += 4;\
- }\
- }\
- else {\
- for (let i = 0; i < d.length; ++i) {\
- write_dummy(d[i]);\
- }\
- }\
- }\
- else {\
- write_object_dummy(d);\
- }\
- }\
- \
- function write_object_dummy(d) {\
- let f = Object.keys(d);\
- pos += 1;\
- pos += 4;\
- for (let i = 0; i < f.length; ++i) {\
- let k = f[i];\
- pos += 1;\
- pos += 4;\
- \
- k_type = \"\";\
- if (k.endsWith(\"__f32\")) {\
- k_type = \"__f32\";\
- }\
- else if (k.endsWith(\"__i32\")) {\
- k_type = \"__i32\";\
- }\
- else if (k.endsWith(\"__i16\")) {\
- k_type = \"__i16\";\
- }\
- else if (k.endsWith(\"__u8\")) {\
- k_type = \"__u8\";\
- }\
- \
- pos += k.length - k_type.length;\
- write_dummy(d[k]);\
- k_type = \"\";\
- }\
- }\
- \
- globalThis.armpack_encode = armpack_encode;\
- globalThis.armpack_decode = armpack_decode;\
- globalThis.string_to_buffer = string_to_buffer;\
- globalThis.buffer_to_string = buffer_to_string;\
- ";
- // ██████╗ ██╗███╗ ██╗██████╗ ██╗███╗ ██╗ ██████╗ ███████╗
- // ██╔══██╗██║████╗ ██║██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝
- // ██████╔╝██║██╔██╗ ██║██║ ██║██║██╔██╗ ██║██║ ███╗███████╗
- // ██╔══██╗██║██║╚██╗██║██║ ██║██║██║╚██╗██║██║ ██║╚════██║
- // ██████╔╝██║██║ ╚████║██████╔╝██║██║ ╚████║╚██████╔╝███████║
- // ╚═════╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝
- any_array_t *plugin_gc;
- void gc_root(void *ptr);
- void gc_run();
- // These could be auto-generated by alang
- VOID_FN(gc_run)
- void *data_get_blob(char *s);
- FN(data_get_blob) {
- char *s = (char *)JS_ToCString(ctx, argv[0]);
- buffer_t *b = data_get_blob(s);
- JSValue val = JS_NewArrayBuffer(ctx, b->buffer, b->length, NULL, NULL, 0);
- return val;
- }
- void *data_delete_blob(char *s);
- FN(data_delete_blob) {
- char *s = (char *)JS_ToCString(ctx, argv[0]);
- data_delete_blob(s);
- return JS_UNDEFINED;
- }
- void *iron_file_save_bytes(char *s, buffer_t *b, int l);
- FN(iron_file_save_bytes) {
- char *to = (char *)JS_ToCString(ctx, argv[0]);
- size_t len;
- void *ab = JS_GetArrayBuffer(ctx, &len, argv[1]);
- buffer_t b = {.buffer = ab, .length = len, .capacity = len};
- iron_file_save_bytes(to, &b, len);
- return JS_UNDEFINED;
- }
- void *gpu_create_texture_from_bytes(void *p, int w, int h, int format);
- FN(gpu_create_texture_from_bytes) {
- size_t len;
- void *ab = JS_GetArrayBuffer(ctx, &len, argv[0]);
- buffer_t b = {.buffer = ab, .length = len, .capacity = len};
- int64_t w;
- JS_ToInt64(ctx, &w, argv[1]);
- int64_t h;
- JS_ToInt64(ctx, &h, argv[2]);
- int64_t format = 0;
- if (argc > 3) {
- JS_ToInt64(ctx, &format, argv[3]);
- }
- uint64_t result = (uint64_t)gpu_create_texture_from_bytes(&b, w, h, format);
- return JS_NewBigUint64(ctx, result);
- }
- FN(ui_handle_create) {
- uint64_t result = (uint64_t)ui_handle_create();
- any_array_push(plugin_gc, (void *)result);
- return JS_NewBigUint64(ctx, result);
- }
- FN(ui_handle_set_value) {
- uint64_t p;
- JS_ToBigUint64(ctx, &p, argv[0]);
- ui_handle_t *h = (ui_handle_t *)p;
- double d;
- JS_ToFloat64(ctx, &d, argv[1]);
- h->f = d;
- return JS_UNDEFINED;
- }
- FN(ui_handle_get_value) {
- uint64_t p;
- JS_ToBigUint64(ctx, &p, argv[0]);
- ui_handle_t *h = (ui_handle_t *)p;
- return JS_NewFloat64(ctx, h->f);
- }
- FN(ui_panel) {
- uint64_t p;
- JS_ToBigUint64(ctx, &p, argv[0]);
- char *s = (char *)JS_ToCString(ctx, argv[1]);
- bool result = ui_panel((void *)p, s, false, false);
- return JS_NewBool(ctx, result);
- }
- FN(ui_button) {
- char *s = (char *)JS_ToCString(ctx, argv[0]);
- bool result = ui_button(s, UI_ALIGN_CENTER, "");
- return JS_NewBool(ctx, result);
- }
- FN(ui_text) {
- char *s = (char *)JS_ToCString(ctx, argv[0]);
- ui_text(s, UI_ALIGN_LEFT, 0);
- return JS_UNDEFINED;
- }
- FN(ui_text_input) {
- uint64_t p;
- JS_ToBigUint64(ctx, &p, argv[0]);
- char *s = (char *)JS_ToCString(ctx, argv[1]);
- ui_text_input((void *)p, s, UI_ALIGN_LEFT, true, false);
- return JS_UNDEFINED;
- }
- FN(ui_slider) {
- uint64_t p;
- JS_ToBigUint64(ctx, &p, argv[0]);
- char *s = (char *)JS_ToCString(ctx, argv[1]);
- double from = 0.0;
- double to = 1.0;
- bool filled = true;
- double prec = 100.0;
- if (argc > 2) {
- JS_ToFloat64(ctx, &from, argv[2]);
- }
- if (argc > 3) {
- JS_ToFloat64(ctx, &to, argv[3]);
- }
- if (argc > 4) {
- filled = JS_ToBool(ctx, argv[4]);
- }
- if (argc > 5) {
- JS_ToFloat64(ctx, &prec, argv[5]);
- }
- ui_slider((void *)p, s, from, to, filled, prec, true, UI_ALIGN_LEFT, true);
- return JS_UNDEFINED;
- }
- FN(ui_check) {
- uint64_t p;
- JS_ToBigUint64(ctx, &p, argv[0]);
- char *s = (char *)JS_ToCString(ctx, argv[1]);
- ui_check((void *)p, s, "");
- return JS_UNDEFINED;
- }
- FN(ui_radio) {
- uint64_t p;
- JS_ToBigUint64(ctx, &p, argv[0]);
- int32_t pos;
- JS_ToInt32(ctx, &pos, argv[1]);
- char *s = (char *)JS_ToCString(ctx, argv[2]);
- ui_radio((void *)p, pos, s, "");
- return JS_UNDEFINED;
- }
- FN(ui_row) {
- JSValue val_len = JS_GetPropertyStr(ctx, argv[0], "length");
- int len;
- JS_ToInt32(ctx, &len, val_len);
- f32_array_t *ratios = f32_array_create(len);
- for (int i = 0; i < len; ++i) {
- JSValue val = JS_GetPropertyUint32(ctx, argv[0], i);
- double f;
- JS_ToFloat64(ctx, &f, val);
- ratios->buffer[i] = f;
- }
- ui_row(ratios);
- return JS_UNDEFINED;
- }
- FN(ui_combo) {
- uint64_t p;
- JS_ToBigUint64(ctx, &p, argv[0]);
- JSValue val_len = JS_GetPropertyStr(ctx, argv[1], "length");
- int len;
- JS_ToInt32(ctx, &len, val_len);
- char_ptr_array_t *texts = any_array_create(len);
- for (int i = 0; i < len; ++i) {
- JSValue val = JS_GetPropertyUint32(ctx, argv[1], i);
- char *s = (char *)JS_ToCString(ctx, val);
- texts->buffer[i] = s;
- }
- char *label = (char *)JS_ToCString(ctx, argv[2]);
- ui_combo((void *)p, texts, label, true, UI_ALIGN_LEFT, true);
- return JS_UNDEFINED;
- }
- FN(plugin_api_make_raw_mesh) {
- raw_mesh_t *mesh = calloc(sizeof(raw_mesh_t), 1);
- mesh->name = (char *)JS_ToCString(ctx, argv[0]);
- size_t len;
- void *ab = JS_GetArrayBuffer(ctx, &len, argv[1]);
- mesh->posa = malloc(sizeof(i16_array_t));
- mesh->posa->buffer = malloc(len);
- memcpy(mesh->posa->buffer, ab, len);
- mesh->posa->length = len / 2;
- ab = JS_GetArrayBuffer(ctx, &len, argv[2]);
- mesh->nora = malloc(sizeof(i16_array_t));
- mesh->nora->buffer = malloc(len);
- memcpy(mesh->nora->buffer, ab, len);
- mesh->nora->length = len / 2;
- ab = JS_GetArrayBuffer(ctx, &len, argv[3]);
- mesh->inda = malloc(sizeof(u32_array_t));
- mesh->inda->buffer = malloc(len);
- memcpy(mesh->inda->buffer, ab, len);
- mesh->inda->length = len / 4;
- double d;
- JS_ToFloat64(ctx, &d, argv[4]);
- mesh->scale_pos = d;
- mesh->scale_tex = 1.0;
- return JS_NewBigUint64(ctx, (uint64_t)mesh);
- }
- void transform_rotate(void *raw, vec4_t axis, float f);
- FN(transform_rotate) {
- uint64_t p;
- JS_ToBigUint64(ctx, &p, argv[0]);
- vec4_t axis;
- axis.x = 0.0;
- axis.y = 0.0;
- axis.z = 1.0;
- double d;
- JS_ToFloat64(ctx, &d, argv[1]);
- transform_rotate((void *)p, axis, d);
- return JS_UNDEFINED;
- }
- void plugin_api_init() {
- JSValue global_obj = JS_GetGlobalObject(js_ctx);
- js_eval(lib);
- plugin_gc = any_array_create(0);
- gc_root(plugin_gc);
- BIND(gc_run, 0);
- BIND(data_get_blob, 1);
- BIND(data_delete_blob, 1);
- BIND(iron_file_save_bytes, 3);
- BIND(gpu_create_texture_from_bytes, 4);
- BIND(ui_handle_create, 0);
- BIND(ui_handle_set_value, 2);
- BIND(ui_handle_get_value, 1);
- BIND(ui_panel, 2);
- BIND(ui_button, 1);
- BIND(ui_text, 1);
- BIND(ui_text_input, 2);
- BIND(ui_slider, 5);
- BIND(ui_check, 2);
- BIND(ui_radio, 3);
- BIND(ui_row, 1);
- BIND(ui_combo, 3);
- BIND(plugin_api_make_raw_mesh, 5);
- BIND(transform_rotate, 3);
- plugin_embed();
- JS_FreeValue(js_ctx, global_obj);
- }
|