plugin_api.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. #include "plugin_api.h"
  2. #include "iron_ui.h"
  3. #include "iron_ui_nodes.h"
  4. #include "iron_array.h"
  5. #include "iron_map.h"
  6. #include "iron_armpack.h"
  7. #include "iron_obj.h"
  8. #include "iron_vec4.h"
  9. #include "iron_mat4.h"
  10. void plugin_embed();
  11. // ██╗ ██╗██████╗
  12. // ██║ ██║██╔══██╗
  13. // ██║ ██║██████╔╝
  14. // ██║ ██║██╔══██╗
  15. // ███████╗██║██████╔╝
  16. // ╚══════╝╚═╝╚═════╝
  17. const char *lib = "\
  18. function buffer_to_string(b) {\
  19. let str = \"\";\
  20. let u8a = new Uint8Array(b);\
  21. for (let i = 0; i < u8a.length; ++i) {\
  22. str += String.fromCharCode(u8a[i]);\
  23. }\
  24. return str;\
  25. }\
  26. \
  27. function string_to_buffer(str) {\
  28. let u8a = new Uint8Array(str.length);\
  29. for (let i = 0; i < str.length; ++i) {\
  30. u8a[i] = str.charCodeAt(i);\
  31. }\
  32. return u8a.buffer;\
  33. }\
  34. \
  35. let pos = 0;\
  36. let k_type = \"\";\
  37. \
  38. function armpack_decode(b) {\
  39. pos = 0;\
  40. return read(new DataView(b));\
  41. }\
  42. \
  43. function read_u8(v) {\
  44. let i = v.getUint8(pos);\
  45. pos++;\
  46. return i;\
  47. }\
  48. \
  49. function read_i16(v) {\
  50. let i = v.getInt16(pos, true);\
  51. pos += 2;\
  52. return i;\
  53. }\
  54. \
  55. function read_i32(v) {\
  56. let i = v.getInt32(pos, true);\
  57. pos += 4;\
  58. return i;\
  59. }\
  60. \
  61. function read_u32(v) {\
  62. let i = v.getUint32(pos, true);\
  63. pos += 4;\
  64. return i;\
  65. }\
  66. \
  67. function read_f32(v) {\
  68. let f = v.getFloat32(pos, true);\
  69. pos += 4;\
  70. return f;\
  71. }\
  72. \
  73. function read_string(v, len) {\
  74. let s = \"\";\
  75. for (let i = 0; i < len; ++i) {\
  76. s += String.fromCharCode(read_u8(v));\
  77. }\
  78. return s;\
  79. }\
  80. \
  81. function read(v) {\
  82. let b = read_u8(v);\
  83. switch (b) {\
  84. case 0xc0: return null;\
  85. case 0xc2: return false;\
  86. case 0xc3: return true;\
  87. case 0xca: { k_type = \"__f32\"; return read_f32(v); }\
  88. case 0xd2: return read_i32(v);\
  89. case 0xdb: return read_string(v, read_u32(v));\
  90. case 0xdd: return read_array(v, read_i32(v));\
  91. case 0xdf: return read_map(v, read_i32(v));\
  92. }\
  93. return 0;\
  94. }\
  95. \
  96. function read_array(v, length) {\
  97. let b = read_u8(v);\
  98. \
  99. if (b == 0xca) { /* Typed f32 */ \
  100. let a = new Array(length);\
  101. for (let x = 0; x < length; ++x) a[x] = read_f32(v);\
  102. k_type = \"__f32\";\
  103. return a;\
  104. }\
  105. else if (b == 0xd2) { /* Typed i32 */ \
  106. let a = new Array(length);\
  107. for (let x = 0; x < length; ++x) a[x] = read_i32(v);\
  108. k_type = \"__i32\";\
  109. return a;\
  110. }\
  111. else if (b == 0xd1) { /* Typed i16 */ \
  112. let a = new Array(length);\
  113. for (let x = 0; x < length; ++x) a[x] = read_i16(v);\
  114. k_type = \"__i16\";\
  115. return a;\
  116. }\
  117. else if (b == 0xc4) { /* Typed u8 */ \
  118. let a = new Array(length);\
  119. for (let x = 0; x < length; ++x) a[x] = read_u8(v);\
  120. k_type = \"__u8\";\
  121. return a;\
  122. }\
  123. else { /* Dynamic type-value */ \
  124. pos--;\
  125. let a = new Array(length);\
  126. for (let x = 0; x < length; ++x) a[x] = read(v);\
  127. return a;\
  128. }\
  129. }\
  130. \
  131. function read_map(v, length) {\
  132. let out = {};\
  133. for (let n = 0; n < length; ++n) {\
  134. let k = read(v);\
  135. k_type = \"\";\
  136. let val = read(v);\
  137. k += k_type;\
  138. k_type = \"\";\
  139. out[k] = val;\
  140. }\
  141. return out;\
  142. }\
  143. \
  144. function armpack_encode(d) {\
  145. pos = 0;\
  146. write_dummy(d);\
  147. let b = new ArrayBuffer(pos);\
  148. let v = new DataView(b);\
  149. pos = 0;\
  150. write(v, d);\
  151. return b;\
  152. }\
  153. \
  154. function write_u8(v, i) {\
  155. v.setUint8(pos, i);\
  156. pos += 1;\
  157. }\
  158. \
  159. function write_i16(v, i) {\
  160. v.setInt16(pos, i, true);\
  161. pos += 2;\
  162. }\
  163. \
  164. function write_i32(v, i) {\
  165. v.setInt32(pos, i, true);\
  166. pos += 4;\
  167. }\
  168. \
  169. function write_f32(v, f) {\
  170. v.setFloat32(pos, f, true);\
  171. pos += 4;\
  172. }\
  173. \
  174. function write_string(v, str) {\
  175. for (let i = 0; i < str.length; ++i) {\
  176. write_u8(v, str.charCodeAt(i));\
  177. }\
  178. }\
  179. \
  180. function write(v, d) {\
  181. if (d == null) {\
  182. write_u8(v, 0xc0);\
  183. }\
  184. else if (typeof d == \"boolean\") {\
  185. write_u8(v, d ? 0xc3 : 0xc2);\
  186. }\
  187. else if (typeof d == \"number\") {\
  188. if (Number.isInteger(d) && k_type != \"__f32\") {\
  189. write_u8(v, 0xd2);\
  190. write_i32(v, d);\
  191. }\
  192. else {\
  193. write_u8(v, 0xca);\
  194. write_f32(v, d);\
  195. }\
  196. }\
  197. else if (typeof d == \"string\") {\
  198. write_u8(v, 0xdb);\
  199. write_i32(v, d.length);\
  200. write_string(v, d);\
  201. }\
  202. else if (Array.isArray(d)) {\
  203. write_u8(v, 0xdd);\
  204. write_i32(v, d.length);\
  205. if (k_type == \"__u8\") {\
  206. write_u8(v, 0xc4);\
  207. for (let i = 0; i < d.length; ++i) {\
  208. write_u8(v, d[i]);\
  209. }\
  210. }\
  211. else if (k_type == \"__i16\") {\
  212. write_u8(v, 0xd1);\
  213. for (let i = 0; i < d.length; ++i) {\
  214. write_i16(v, d[i]);\
  215. }\
  216. }\
  217. else if (k_type == \"__f32\") {\
  218. write_u8(v, 0xca);\
  219. for (let i = 0; i < d.length; ++i) {\
  220. write_f32(v, d[i]);\
  221. }\
  222. }\
  223. else if (k_type == \"__i32\") {\
  224. write_u8(v, 0xd2);\
  225. for (let i = 0; i < d.length; ++i) {\
  226. write_i32(v, d[i]);\
  227. }\
  228. }\
  229. else {\
  230. for (let i = 0; i < d.length; ++i) {\
  231. write(v, d[i]);\
  232. }\
  233. }\
  234. }\
  235. else {\
  236. write_object(v, d);\
  237. }\
  238. }\
  239. \
  240. function write_object(v, d) {\
  241. let f = Object.keys(d);\
  242. write_u8(v, 0xdf);\
  243. write_i32(v, f.length);\
  244. for (let i = 0; i < f.length; ++i) {\
  245. let k = f[i];\
  246. \
  247. k_type = \"\";\
  248. if (k.endsWith(\"__f32\")) {\
  249. k_type = \"__f32\";\
  250. }\
  251. else if (k.endsWith(\"__i32\")) {\
  252. k_type = \"__i32\";\
  253. }\
  254. else if (k.endsWith(\"__i16\")) {\
  255. k_type = \"__i16\";\
  256. }\
  257. else if (k.endsWith(\"__u8\")) {\
  258. k_type = \"__u8\";\
  259. }\
  260. \
  261. write_u8(v, 0xdb);\
  262. write_i32(v, k.length - k_type.length);\
  263. \
  264. write_string(v, k.substring(0, k.length - k_type.length));\
  265. write(v, d[k]);\
  266. k_type = \"\";\
  267. }\
  268. }\
  269. \
  270. function write_dummy(d) {\
  271. if (d == null) {\
  272. pos += 1;\
  273. }\
  274. else if (typeof d == \"boolean\") {\
  275. pos += 1;\
  276. }\
  277. else if (typeof d == \"number\") {\
  278. pos += 1;\
  279. pos += 4;\
  280. }\
  281. else if (typeof d == \"string\") {\
  282. pos += 1;\
  283. pos += 4;\
  284. pos += d.length;\
  285. }\
  286. else if (Array.isArray(d)) {\
  287. pos += 1;\
  288. pos += 4;\
  289. if (k_type == \"__u8\") {\
  290. pos += 1;\
  291. for (let i = 0; i < d.length; ++i) {\
  292. pos += 1;\
  293. }\
  294. }\
  295. else if (k_type == \"__i16\") {\
  296. pos += 1;\
  297. for (let i = 0; i < d.length; ++i) {\
  298. pos += 2;\
  299. }\
  300. }\
  301. else if (k_type == \"__f32\") {\
  302. pos += 1;\
  303. for (let i = 0; i < d.length; ++i) {\
  304. pos += 4;\
  305. }\
  306. }\
  307. else if (k_type == \"__i32\") {\
  308. pos += 1;\
  309. for (let i = 0; i < d.length; ++i) {\
  310. pos += 4;\
  311. }\
  312. }\
  313. else {\
  314. for (let i = 0; i < d.length; ++i) {\
  315. write_dummy(d[i]);\
  316. }\
  317. }\
  318. }\
  319. else {\
  320. write_object_dummy(d);\
  321. }\
  322. }\
  323. \
  324. function write_object_dummy(d) {\
  325. let f = Object.keys(d);\
  326. pos += 1;\
  327. pos += 4;\
  328. for (let i = 0; i < f.length; ++i) {\
  329. let k = f[i];\
  330. pos += 1;\
  331. pos += 4;\
  332. \
  333. k_type = \"\";\
  334. if (k.endsWith(\"__f32\")) {\
  335. k_type = \"__f32\";\
  336. }\
  337. else if (k.endsWith(\"__i32\")) {\
  338. k_type = \"__i32\";\
  339. }\
  340. else if (k.endsWith(\"__i16\")) {\
  341. k_type = \"__i16\";\
  342. }\
  343. else if (k.endsWith(\"__u8\")) {\
  344. k_type = \"__u8\";\
  345. }\
  346. \
  347. pos += k.length - k_type.length;\
  348. write_dummy(d[k]);\
  349. k_type = \"\";\
  350. }\
  351. }\
  352. \
  353. globalThis.armpack_encode = armpack_encode;\
  354. globalThis.armpack_decode = armpack_decode;\
  355. globalThis.string_to_buffer = string_to_buffer;\
  356. globalThis.buffer_to_string = buffer_to_string;\
  357. ";
  358. // ██████╗ ██╗███╗ ██╗██████╗ ██╗███╗ ██╗ ██████╗ ███████╗
  359. // ██╔══██╗██║████╗ ██║██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝
  360. // ██████╔╝██║██╔██╗ ██║██║ ██║██║██╔██╗ ██║██║ ███╗███████╗
  361. // ██╔══██╗██║██║╚██╗██║██║ ██║██║██║╚██╗██║██║ ██║╚════██║
  362. // ██████╔╝██║██║ ╚████║██████╔╝██║██║ ╚████║╚██████╔╝███████║
  363. // ╚═════╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝
  364. any_array_t *plugin_gc;
  365. void gc_root(void *ptr);
  366. void gc_run();
  367. // These could be auto-generated by alang
  368. VOID_FN(gc_run)
  369. VOID_FN_STR(console_log)
  370. VOID_FN_STR(console_info)
  371. PTR_FN(plugin_create)
  372. VOID_FN_PTR_CB(plugin_notify_on_ui)
  373. VOID_FN_PTR_CB(plugin_notify_on_update)
  374. VOID_FN_PTR_CB(plugin_notify_on_delete)
  375. static JSObject *ui_files_cb;
  376. static void ui_files_done(char *path) {
  377. JSValue path_val = JS_NewString(js_ctx, path);
  378. JSValue argv[] = { path_val };
  379. js_call_arg(ui_files_cb, 1, argv);
  380. }
  381. void ui_files_show(char *s, bool b0, bool b1, void(*f)(char *));
  382. FN(ui_files_show) {
  383. char *filters = (char *)JS_ToCString(ctx, argv[0]);
  384. bool is_save = JS_ToBool(ctx, argv[1]);
  385. bool open_multiple = JS_ToBool(ctx, argv[2]);
  386. ui_files_cb = malloc(sizeof(JSValue));
  387. JSValue dup = JS_DupValue(ctx, argv[3]);
  388. memcpy(ui_files_cb, &dup, sizeof(JSValue));
  389. ui_files_show(filters, is_save, open_multiple, ui_files_done);
  390. return JS_UNDEFINED;
  391. }
  392. void ui_box_show_message(char *s0, char *s1, bool b);
  393. extern bool ui_box_click_to_hide;
  394. FN(ui_box_show_message) {
  395. char *title = (char *)JS_ToCString(ctx, argv[0]);
  396. char *message = (char *)JS_ToCString(ctx, argv[1]);
  397. ui_box_show_message(title, message, true);
  398. ui_box_click_to_hide = false;
  399. return JS_UNDEFINED;
  400. }
  401. void *data_get_blob(char *s);
  402. FN(data_get_blob) {
  403. char *s = (char *)JS_ToCString(ctx, argv[0]);
  404. buffer_t *b = data_get_blob(s);
  405. JSValue val = JS_NewArrayBuffer(ctx, b->buffer, b->length, NULL, NULL, 0);
  406. return val;
  407. }
  408. void *data_delete_blob(char *s);
  409. FN(data_delete_blob) {
  410. char *s = (char *)JS_ToCString(ctx, argv[0]);
  411. data_delete_blob(s);
  412. return JS_UNDEFINED;
  413. }
  414. void *iron_file_save_bytes(char *s, buffer_t *b, int l);
  415. FN(iron_file_save_bytes) {
  416. char *to = (char *)JS_ToCString(ctx, argv[0]);
  417. size_t len;
  418. void *ab = JS_GetArrayBuffer(ctx, &len, argv[1]);
  419. buffer_t b = { .buffer = ab, .length = len, .capacity = len };
  420. iron_file_save_bytes(to, &b, len);
  421. return JS_UNDEFINED;
  422. }
  423. VOID_FN_CB(context_set_viewport_shader)
  424. void node_shader_add_constant(void *p, char *s0, char *s1, bool b);
  425. FN(node_shader_add_constant) {
  426. int64_t p;
  427. JS_ToInt64(ctx, &p, argv[0]);
  428. char *s0 = (char *)JS_ToCString(ctx, argv[1]);
  429. char *s1 = (char *)JS_ToCString(ctx, argv[2]);
  430. node_shader_add_constant((void *)p, s0, s1, false);
  431. return JS_UNDEFINED;
  432. }
  433. VOID_FN_PTR_STR(node_shader_write_frag)
  434. void *gpu_create_texture_from_bytes(void *p, int w, int h, int format);
  435. FN(gpu_create_texture_from_bytes) {
  436. size_t len;
  437. void *ab = JS_GetArrayBuffer(ctx, &len, argv[0]);
  438. buffer_t b = { .buffer = ab, .length = len, .capacity = len };
  439. int64_t w;
  440. JS_ToInt64(ctx, &w, argv[1]);
  441. int64_t h;
  442. JS_ToInt64(ctx, &h, argv[2]);
  443. int64_t result = (int64_t)gpu_create_texture_from_bytes(&b, w, h, 0);
  444. return JS_NewInt64(ctx, result);
  445. }
  446. extern char *project_filepath;
  447. FN(project_filepath_get) {
  448. return JS_NewString(ctx, project_filepath);
  449. }
  450. void project_save(bool b);
  451. FN(project_save) {
  452. project_save(false);
  453. return JS_UNDEFINED;
  454. }
  455. FN(ui_handle_create) {
  456. int64_t result = (int64_t)ui_handle_create();
  457. any_array_push(plugin_gc, (void *)result);
  458. return JS_NewInt64(ctx, result);
  459. }
  460. FN(ui_handle_set_value) {
  461. int64_t p;
  462. JS_ToInt64(ctx, &p, argv[0]);
  463. ui_handle_t *h = (ui_handle_t *)p;
  464. double d;
  465. JS_ToFloat64(ctx, &d, argv[1]);
  466. h->value = d;
  467. return JS_UNDEFINED;
  468. }
  469. FN(ui_handle_get_value) {
  470. int64_t p;
  471. JS_ToInt64(ctx, &p, argv[0]);
  472. ui_handle_t *h = (ui_handle_t *)p;
  473. return JS_NewFloat64(ctx, h->value);
  474. }
  475. FN(ui_panel) {
  476. int64_t p;
  477. JS_ToInt64(ctx, &p, argv[0]);
  478. char *s = (char *)JS_ToCString(ctx, argv[1]);
  479. bool result = ui_panel((void *)p, s, false, false);
  480. return JS_NewBool(ctx, result);
  481. }
  482. FN(ui_button) {
  483. char *s = (char *)JS_ToCString(ctx, argv[0]);
  484. bool result = ui_button(s, UI_ALIGN_CENTER, "");
  485. return JS_NewBool(ctx, result);
  486. }
  487. FN(ui_text) {
  488. char *s = (char *)JS_ToCString(ctx, argv[0]);
  489. ui_text(s, UI_ALIGN_LEFT, 0);
  490. return JS_UNDEFINED;
  491. }
  492. FN(ui_text_input) {
  493. int64_t p;
  494. JS_ToInt64(ctx, &p, argv[0]);
  495. char *s = (char *)JS_ToCString(ctx, argv[1]);
  496. ui_text_input((void *)p, s, UI_ALIGN_LEFT, true, false);
  497. return JS_UNDEFINED;
  498. }
  499. FN(ui_slider) {
  500. int64_t p;
  501. JS_ToInt64(ctx, &p, argv[0]);
  502. char *s = (char *)JS_ToCString(ctx, argv[1]);
  503. double from = 0.0;
  504. double to = 1.0;
  505. bool filled = true;
  506. double prec = 100.0;
  507. if (argc > 2) {
  508. JS_ToFloat64(ctx, &from, argv[2]);
  509. }
  510. if (argc > 3) {
  511. JS_ToFloat64(ctx, &to, argv[3]);
  512. }
  513. if (argc > 4) {
  514. filled = JS_ToBool(ctx, argv[4]);
  515. }
  516. if (argc > 5) {
  517. JS_ToFloat64(ctx, &prec, argv[5]);
  518. }
  519. ui_slider((void *)p, s, from, to, filled, prec, true, UI_ALIGN_LEFT, true);
  520. return JS_UNDEFINED;
  521. }
  522. FN(ui_check) {
  523. int64_t p;
  524. JS_ToInt64(ctx, &p, argv[0]);
  525. char *s = (char *)JS_ToCString(ctx, argv[1]);
  526. ui_check((void *)p, s, "");
  527. return JS_UNDEFINED;
  528. }
  529. FN(ui_radio) {
  530. int64_t p;
  531. JS_ToInt64(ctx, &p, argv[0]);
  532. int32_t pos;
  533. JS_ToInt32(ctx, &pos, argv[1]);
  534. char *s = (char *)JS_ToCString(ctx, argv[2]);
  535. ui_radio((void *)p, pos, s, "");
  536. return JS_UNDEFINED;
  537. }
  538. FN(ui_row) {
  539. JSValue val_len = JS_GetPropertyStr(ctx, argv[0], "length");
  540. int len;
  541. JS_ToInt32(ctx, &len, val_len);
  542. f32_array_t *ratios = f32_array_create(len);
  543. for (int i = 0; i < len; ++i) {
  544. JSValue val = JS_GetPropertyUint32(ctx, argv[0], i);
  545. double f;
  546. JS_ToFloat64(ctx, &f, val);
  547. ratios->buffer[i] = f;
  548. }
  549. ui_row(ratios);
  550. return JS_UNDEFINED;
  551. }
  552. FN(ui_combo) {
  553. int64_t p;
  554. JS_ToInt64(ctx, &p, argv[0]);
  555. JSValue val_len = JS_GetPropertyStr(ctx, argv[1], "length");
  556. int len;
  557. JS_ToInt32(ctx, &len, val_len);
  558. char_ptr_array_t *texts = any_array_create(len);
  559. for (int i = 0; i < len; ++i) {
  560. JSValue val = JS_GetPropertyUint32(ctx, argv[1], i);
  561. char *s = (char *)JS_ToCString(ctx, val);
  562. texts->buffer[i] = s;
  563. }
  564. char *label = (char *)JS_ToCString(ctx, argv[2]);
  565. ui_combo((void *)p, texts, label, true, UI_ALIGN_LEFT, true);
  566. return JS_UNDEFINED;
  567. }
  568. extern any_array_t *nodes_material_categories;
  569. extern any_array_t *nodes_material_list;
  570. FN(nodes_material_category_add) {
  571. char *category_name = (char *)JS_ToCString(ctx, argv[0]);
  572. any_array_push(nodes_material_categories, category_name);
  573. size_t len;
  574. void *ab = JS_GetArrayBuffer(ctx, &len, argv[1]);
  575. buffer_t b = { .buffer = ab, .length = len, .capacity = len };
  576. any_array_push(nodes_material_list, armpack_decode(&b));
  577. return JS_UNDEFINED;
  578. }
  579. FN(nodes_material_category_remove) {
  580. char *category_name = (char *)JS_ToCString(ctx, argv[0]);
  581. int i = array_index_of(nodes_material_categories, category_name);
  582. array_splice(nodes_material_list, i, 1);
  583. array_splice(nodes_material_categories, i, 1);
  584. return JS_UNDEFINED;
  585. }
  586. extern any_map_t *parser_material_custom_nodes;
  587. FN(parser_material_custom_nodes_set) {
  588. char *node_type = (char *)JS_ToCString(ctx, argv[0]);
  589. JSValue *p = malloc(sizeof(JSValue));\
  590. JSValue dup = JS_DupValue(ctx, argv[1]);\
  591. memcpy(p, &dup, sizeof(JSValue));\
  592. any_map_set(parser_material_custom_nodes, node_type, p);
  593. return JS_UNDEFINED;
  594. }
  595. FN(parser_material_custom_nodes_delete) {
  596. char *node_type = (char *)JS_ToCString(ctx, argv[0]);
  597. map_delete(parser_material_custom_nodes, node_type);
  598. return JS_UNDEFINED;
  599. }
  600. extern void *parser_material_kong;
  601. FN(parser_material_kong_get) {
  602. return JS_NewInt64(ctx, (int64_t)parser_material_kong);
  603. }
  604. char *parser_material_parse_value_input(void *inp, bool vector_as_grayscale);
  605. FN(parser_material_parse_value_input) {
  606. int64_t *node;
  607. JS_ToInt64(ctx, &node, argv[0]);
  608. int64_t i;
  609. JS_ToInt64(ctx, &i, argv[1]);
  610. char *s = parser_material_parse_value_input(((ui_node_t *)node)->inputs->buffer[i], false);
  611. return JS_NewString(ctx, s);
  612. }
  613. extern any_array_t *nodes_brush_categories;
  614. extern any_array_t *nodes_brush_list;
  615. void nodes_brush_list_init();
  616. FN(nodes_brush_category_add) {
  617. char *category_name = (char *)JS_ToCString(ctx, argv[0]);
  618. any_array_push(nodes_brush_categories, category_name);
  619. size_t len;
  620. void *ab = JS_GetArrayBuffer(ctx, &len, argv[1]);
  621. buffer_t b = { .buffer = ab, .length = len, .capacity = len };
  622. nodes_brush_list_init();
  623. any_array_push(nodes_brush_list, armpack_decode(&b));
  624. return JS_UNDEFINED;
  625. }
  626. FN(nodes_brush_category_remove) {
  627. char *category_name = (char *)JS_ToCString(ctx, argv[0]);
  628. int i = array_index_of(nodes_brush_categories, category_name);
  629. array_splice(nodes_brush_list, i, 1);
  630. array_splice(nodes_brush_categories, i, 1);
  631. return JS_UNDEFINED;
  632. }
  633. extern any_map_t *parser_logic_custom_nodes;
  634. FN(parser_logic_custom_nodes_set) {
  635. char *node_type = (char *)JS_ToCString(ctx, argv[0]);
  636. JSValue *p = malloc(sizeof(JSValue));\
  637. JSValue dup = JS_DupValue(ctx, argv[1]);\
  638. memcpy(p, &dup, sizeof(JSValue));\
  639. any_map_set(parser_logic_custom_nodes, node_type, p);
  640. return JS_UNDEFINED;
  641. }
  642. FN(parser_logic_custom_nodes_delete) {
  643. char *node_type = (char *)JS_ToCString(ctx, argv[0]);
  644. map_delete(parser_logic_custom_nodes, node_type);
  645. return JS_UNDEFINED;
  646. }
  647. extern any_map_t *util_mesh_unwrappers;
  648. FN(util_mesh_unwrappers_set) {
  649. char *plugin_name = (char *)JS_ToCString(ctx, argv[0]);
  650. JSValue *p = malloc(sizeof(JSValue));\
  651. JSValue dup = JS_DupValue(ctx, argv[1]);\
  652. memcpy(p, &dup, sizeof(JSValue));\
  653. any_map_set(util_mesh_unwrappers, plugin_name, p);
  654. return JS_UNDEFINED;
  655. }
  656. FN(util_mesh_unwrappers_delete) {
  657. char *plugin_name = (char *)JS_ToCString(ctx, argv[0]);
  658. map_delete(util_mesh_unwrappers, plugin_name);
  659. return JS_UNDEFINED;
  660. }
  661. extern any_map_t *path_mesh_importers;
  662. extern char_ptr_array_t *path_mesh_formats;
  663. FN(path_mesh_importers_set) {
  664. char *format_name = (char *)JS_ToCString(ctx, argv[0]);
  665. JSValue *p = malloc(sizeof(JSValue));\
  666. JSValue dup = JS_DupValue(ctx, argv[1]);\
  667. memcpy(p, &dup, sizeof(JSValue));\
  668. any_map_set(path_mesh_importers, format_name, p);
  669. any_array_push(path_mesh_formats, format_name);
  670. return JS_UNDEFINED;
  671. }
  672. FN(path_mesh_importers_delete) {
  673. char *format_name = (char *)JS_ToCString(ctx, argv[0]);
  674. map_delete(path_mesh_importers, format_name);
  675. array_splice(path_mesh_formats, char_ptr_array_index_of(path_mesh_formats, format_name), 1);
  676. return JS_UNDEFINED;
  677. }
  678. extern any_map_t *path_texture_importers;
  679. extern char_ptr_array_t *path_texture_formats;
  680. FN(path_texture_importers_set) {
  681. char *format_name = (char *)JS_ToCString(ctx, argv[0]);
  682. JSValue *p = malloc(sizeof(JSValue));\
  683. JSValue dup = JS_DupValue(ctx, argv[1]);\
  684. memcpy(p, &dup, sizeof(JSValue));\
  685. any_map_set(path_texture_importers, format_name, p);
  686. any_array_push(path_texture_formats, format_name);
  687. return JS_UNDEFINED;
  688. }
  689. FN(path_texture_importers_delete) {
  690. char *format_name = (char *)JS_ToCString(ctx, argv[0]);
  691. map_delete(path_texture_importers, format_name);
  692. array_splice(path_texture_formats, char_ptr_array_index_of(path_texture_formats, format_name), 1);
  693. return JS_UNDEFINED;
  694. }
  695. FN(plugin_api_make_raw_mesh) {
  696. raw_mesh_t *mesh = calloc(sizeof(raw_mesh_t), 1);
  697. mesh->name = (char *)JS_ToCString(ctx, argv[0]);
  698. size_t len;
  699. void *ab = JS_GetArrayBuffer(ctx, &len, argv[1]);
  700. mesh->posa = malloc(sizeof(i16_array_t));
  701. mesh->posa->buffer = malloc(len);
  702. memcpy(mesh->posa->buffer, ab, len);
  703. mesh->posa->length = len / 2;
  704. ab = JS_GetArrayBuffer(ctx, &len, argv[2]);
  705. mesh->nora = malloc(sizeof(i16_array_t));
  706. mesh->nora->buffer = malloc(len);
  707. memcpy(mesh->nora->buffer, ab, len);
  708. mesh->nora->length = len / 2;
  709. ab = JS_GetArrayBuffer(ctx, &len, argv[3]);
  710. mesh->inda = malloc(sizeof(u32_array_t));
  711. mesh->inda->buffer = malloc(len);
  712. memcpy(mesh->inda->buffer, ab, len);
  713. mesh->inda->length = len / 4;
  714. double d;
  715. JS_ToFloat64(ctx, &d, argv[4]);
  716. mesh->scale_pos = d;
  717. mesh->scale_tex = 1.0;
  718. return JS_NewInt64(ctx, (int64_t)mesh);
  719. }
  720. void transform_rotate(void *raw, vec4_t axis, float f);
  721. FN(transform_rotate) {
  722. int64_t p;
  723. JS_ToInt64(ctx, &p, argv[0]);
  724. vec4_t axis;
  725. axis.x = 0.0;
  726. axis.y = 0.0;
  727. axis.z = 1.0;
  728. double d;
  729. JS_ToFloat64(ctx, &d, argv[1]);
  730. transform_rotate((void *)p, axis, d);
  731. return JS_UNDEFINED;
  732. }
  733. void plugin_api_init() {
  734. JSValue global_obj = JS_GetGlobalObject(js_ctx);
  735. js_eval(lib);
  736. plugin_gc = any_array_create(0);
  737. gc_root(plugin_gc);
  738. BIND(gc_run, 0);
  739. BIND(console_log, 1);
  740. BIND(console_info, 1);
  741. BIND(plugin_create, 0);
  742. BIND(plugin_notify_on_ui, 2);
  743. BIND(plugin_notify_on_update, 2);
  744. BIND(plugin_notify_on_delete, 2);
  745. BIND(ui_files_show, 4);
  746. BIND(ui_box_show_message, 2);
  747. BIND(data_get_blob, 1);
  748. BIND(data_delete_blob, 1);
  749. BIND(iron_file_save_bytes, 3);
  750. BIND(context_set_viewport_shader, 1);
  751. BIND(node_shader_add_constant, 3);
  752. BIND(node_shader_write_frag, 2);
  753. BIND(gpu_create_texture_from_bytes, 3);
  754. BIND(project_filepath_get, 0);
  755. BIND(project_save, 0);
  756. BIND(ui_handle_create, 0);
  757. BIND(ui_handle_set_value, 2);
  758. BIND(ui_handle_get_value, 1);
  759. BIND(ui_panel, 2);
  760. BIND(ui_button, 1);
  761. BIND(ui_text, 1);
  762. BIND(ui_text_input, 2);
  763. BIND(ui_slider, 5);
  764. BIND(ui_check, 2);
  765. BIND(ui_radio, 3);
  766. BIND(ui_row, 1);
  767. BIND(ui_combo, 3);
  768. BIND(nodes_material_category_add, 2);
  769. BIND(nodes_material_category_remove, 1);
  770. BIND(parser_material_custom_nodes_set, 2);
  771. BIND(parser_material_custom_nodes_delete, 1);
  772. BIND(parser_material_kong_get, 0);
  773. BIND(parser_material_parse_value_input, 2);
  774. BIND(nodes_brush_category_add, 2);
  775. BIND(nodes_brush_category_remove, 1);
  776. BIND(parser_logic_custom_nodes_set, 2);
  777. BIND(parser_logic_custom_nodes_delete, 1);
  778. BIND(util_mesh_unwrappers_set, 2);
  779. BIND(util_mesh_unwrappers_delete, 1);
  780. BIND(path_mesh_importers_set, 2);
  781. BIND(path_mesh_importers_delete, 1);
  782. BIND(path_texture_importers_set, 2);
  783. BIND(path_texture_importers_delete, 1);
  784. BIND(plugin_api_make_raw_mesh, 5);
  785. BIND(transform_rotate, 3);
  786. plugin_embed();
  787. JS_FreeValue(js_ctx, global_obj);
  788. }