@cimplify/sdk 0.108.0 → 0.110.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (608) hide show
  1. package/LICENSE +21 -0
  2. package/dist/advanced.d.mts +4 -3
  3. package/dist/advanced.d.ts +4 -3
  4. package/dist/advanced.js +24 -24
  5. package/dist/advanced.mjs +5 -5
  6. package/dist/animation-4EXBXRVX.js +27 -0
  7. package/dist/animation-6DICNWUP.mjs +6 -0
  8. package/dist/audio-DhvyjqdA.d.mts +249 -0
  9. package/dist/audio-m0w8cnxq.d.ts +249 -0
  10. package/dist/avatars.d.mts +110 -0
  11. package/dist/avatars.d.ts +110 -0
  12. package/dist/avatars.js +82 -0
  13. package/dist/avatars.mjs +5 -0
  14. package/dist/backend-gUCzs5Kg.d.mts +3866 -0
  15. package/dist/backend-gUCzs5Kg.d.ts +3866 -0
  16. package/dist/{catalogue-B4eLL8Mi.d.ts → catalogue-CPTMyBUz.d.mts} +109 -221
  17. package/dist/catalogue-DzrTXP3v.d.mts +541 -0
  18. package/dist/catalogue-DzrTXP3v.d.ts +541 -0
  19. package/dist/{catalogue-OT89_Ifs.d.mts → catalogue-OTuS5zp-.d.ts} +109 -221
  20. package/dist/chunk-22BD3RHN.mjs +1809 -0
  21. package/dist/chunk-25T4JHEA.mjs +21 -0
  22. package/dist/chunk-2AQ237Y4.js +508 -0
  23. package/dist/chunk-2IC4H6OV.mjs +48 -0
  24. package/dist/chunk-2LHLG4OB.mjs +71 -0
  25. package/dist/chunk-2O2CG465.js +1709 -0
  26. package/dist/chunk-2Q4DTHXK.js +316 -0
  27. package/dist/chunk-2QTQ6BUH.mjs +46 -0
  28. package/dist/chunk-2UN4SFLR.mjs +100 -0
  29. package/dist/chunk-2V75I7K3.js +454 -0
  30. package/dist/chunk-2V7IL4HC.js +10 -0
  31. package/dist/chunk-34XBXUMW.js +296 -0
  32. package/dist/chunk-3C4C654I.js +71 -0
  33. package/dist/chunk-3DAD2LDF.mjs +72 -0
  34. package/dist/chunk-3GXH2NFD.mjs +4 -0
  35. package/dist/chunk-3O47ZFW3.js +961 -0
  36. package/dist/chunk-3OY3VYNF.mjs +11 -0
  37. package/dist/chunk-3S6WPBZL.js +2936 -0
  38. package/dist/chunk-3TUOUP5T.js +399 -0
  39. package/dist/chunk-3VEH23I5.mjs +1380 -0
  40. package/dist/chunk-3ZYSAW2T.mjs +263 -0
  41. package/dist/chunk-4ANVF274.js +103 -0
  42. package/dist/chunk-4C7I3ELN.js +388 -0
  43. package/dist/chunk-4DYKAYFO.mjs +8 -0
  44. package/dist/chunk-4ZDR72SG.js +329 -0
  45. package/dist/chunk-52YS45RR.js +1066 -0
  46. package/dist/chunk-5325XSCH.js +107 -0
  47. package/dist/chunk-5AD5X6AV.js +13 -0
  48. package/dist/chunk-5BYDGGWO.mjs +197 -0
  49. package/dist/chunk-5C3C7VDM.mjs +55 -0
  50. package/dist/chunk-5HFMY3D7.js +660 -0
  51. package/dist/chunk-5LH2QN3T.js +1862 -0
  52. package/dist/chunk-5PJEXSOW.js +44 -0
  53. package/dist/chunk-5SXDH3Y7.js +90 -0
  54. package/dist/chunk-5YFBGGCK.mjs +502 -0
  55. package/dist/chunk-5YWN6H5Q.mjs +133 -0
  56. package/dist/chunk-66QP3SMN.js +402 -0
  57. package/dist/chunk-6DAEZKIG.mjs +385 -0
  58. package/dist/chunk-6DATW7TB.mjs +420 -0
  59. package/dist/{chunk-JRGK3NXR.mjs → chunk-6ETDAU62.mjs} +72 -212
  60. package/dist/chunk-6H254EVP.mjs +178 -0
  61. package/dist/chunk-6PFNJPBJ.mjs +820 -0
  62. package/dist/chunk-6PJWXIFX.mjs +357 -0
  63. package/dist/chunk-6SWKWCMS.js +80 -0
  64. package/dist/chunk-6VVXXX7S.js +808 -0
  65. package/dist/chunk-6WUBSMTX.js +1403 -0
  66. package/dist/chunk-73SGZLAQ.mjs +35 -0
  67. package/dist/chunk-76L2V6KD.mjs +4 -0
  68. package/dist/chunk-7AAIAVAA.js +1531 -0
  69. package/dist/chunk-7ARSJPV3.mjs +93 -0
  70. package/dist/chunk-7BHW5GTC.mjs +1234 -0
  71. package/dist/chunk-7DQSDKDU.js +6 -0
  72. package/dist/chunk-7IQQQENP.mjs +401 -0
  73. package/dist/chunk-7KFTYENS.js +11357 -0
  74. package/dist/chunk-7SM6XSPZ.js +3171 -0
  75. package/dist/chunk-7SXOHAIR.mjs +28 -0
  76. package/dist/chunk-A2MAX6S4.js +90 -0
  77. package/dist/chunk-A33OORT7.mjs +1530 -0
  78. package/dist/{chunk-U6ACF76H.mjs → chunk-A36JRXXH.mjs} +1075 -1845
  79. package/dist/chunk-A7BU3BK4.js +52 -0
  80. package/dist/chunk-A7MQSN2V.mjs +77 -0
  81. package/dist/chunk-A7V4L2IT.mjs +416 -0
  82. package/dist/chunk-AABEK6XU.js +226 -0
  83. package/dist/chunk-AGV33FWC.mjs +5005 -0
  84. package/dist/chunk-AHNR3BXI.js +108 -0
  85. package/dist/chunk-AQ5RLBU2.mjs +286 -0
  86. package/dist/chunk-AQOE6WCG.js +1270 -0
  87. package/dist/chunk-ATAWRACV.mjs +62 -0
  88. package/dist/chunk-ATCURNUV.js +14 -0
  89. package/dist/chunk-AWPV33OO.js +6 -0
  90. package/dist/chunk-AYJPHKYV.js +337 -0
  91. package/dist/chunk-AZ5BGWHB.js +162 -0
  92. package/dist/chunk-AZAXD44P.js +1373 -0
  93. package/dist/chunk-BBGKQIJJ.mjs +406 -0
  94. package/dist/chunk-BP4JLSUA.js +1453 -0
  95. package/dist/{chunk-SUCE7FWA.mjs → chunk-BTUSVHIE.mjs} +539 -978
  96. package/dist/chunk-BU6OK542.mjs +818 -0
  97. package/dist/chunk-CVSRWM6W.js +418 -0
  98. package/dist/chunk-CYBMFMJD.mjs +247 -0
  99. package/dist/chunk-DDJLDOUX.mjs +217 -0
  100. package/dist/{chunk-V32BCG7M.js → chunk-DFZWHNRG.js} +75 -215
  101. package/dist/chunk-DJ2C7AVG.js +644 -0
  102. package/dist/chunk-DS2VU4WW.mjs +102 -0
  103. package/dist/chunk-DSAG7T5P.js +7290 -0
  104. package/dist/chunk-E2QPPH7I.js +327 -0
  105. package/dist/chunk-E65WCTIG.mjs +1187 -0
  106. package/dist/{chunk-33VCYWVL.mjs → chunk-E6QQKDNE.mjs} +30 -42
  107. package/dist/chunk-ECDK6QBF.mjs +981 -0
  108. package/dist/chunk-EIB4OWVQ.mjs +620 -0
  109. package/dist/chunk-EQUZYCGO.js +250 -0
  110. package/dist/chunk-F3UJ6ZRM.mjs +313 -0
  111. package/dist/chunk-F63N2ZTQ.js +7023 -0
  112. package/dist/chunk-F6XRYEM3.mjs +26 -0
  113. package/dist/chunk-FE6VCE4K.js +5030 -0
  114. package/dist/chunk-FLWD6GRR.js +1372 -0
  115. package/dist/chunk-FQBFWJBS.mjs +110 -0
  116. package/dist/chunk-FXVJ2HFU.js +26 -0
  117. package/dist/chunk-FZMQMQBW.js +312 -0
  118. package/dist/chunk-G3EEC44R.js +53 -0
  119. package/dist/{chunk-KG3WT4PR.mjs → chunk-GCKWKLZF.mjs} +73 -104
  120. package/dist/chunk-GCX7TY4D.mjs +6826 -0
  121. package/dist/chunk-GDB6TCSD.js +450 -0
  122. package/dist/chunk-GDCV4IWO.mjs +21 -0
  123. package/dist/chunk-GDZT5LZ5.js +170 -0
  124. package/dist/chunk-GHPUYD4I.mjs +213 -0
  125. package/dist/chunk-GHS6MIL6.mjs +1432 -0
  126. package/dist/chunk-GPS2THCL.mjs +11 -0
  127. package/dist/{chunk-EV2EVOYS.js → chunk-GTJWQAGU.js} +31 -42
  128. package/dist/chunk-GVTI6UJQ.mjs +130 -0
  129. package/dist/chunk-GXKI64OT.mjs +1138 -0
  130. package/dist/chunk-GYDYF2WX.js +275 -0
  131. package/dist/chunk-GYLP6UG4.mjs +705 -0
  132. package/dist/chunk-H3OQKK6X.js +1158 -0
  133. package/dist/chunk-H5DFSCJ6.js +40 -0
  134. package/dist/chunk-HAGEIC2L.mjs +186 -0
  135. package/dist/chunk-HAJ4JRFO.js +293 -0
  136. package/dist/chunk-HDR72GB6.js +188 -0
  137. package/dist/chunk-HF5HPS4T.mjs +40 -0
  138. package/dist/chunk-HK6LOFDS.js +218 -0
  139. package/dist/chunk-HMWYTXCY.mjs +143 -0
  140. package/dist/chunk-HPCSRCMA.js +89 -0
  141. package/dist/chunk-HSEO6TPU.js +247 -0
  142. package/dist/chunk-I5FOHCLH.js +132 -0
  143. package/dist/chunk-IDLW4NWA.mjs +85 -0
  144. package/dist/chunk-IIDZ5WUX.js +61 -0
  145. package/dist/chunk-IR74FJHU.js +2332 -0
  146. package/dist/chunk-IRVFYAKP.mjs +100 -0
  147. package/dist/{chunk-XBL3TMPC.mjs → chunk-IZDWAL53.mjs} +1795 -3287
  148. package/dist/chunk-J2KZXIU3.js +51 -0
  149. package/dist/chunk-J2U6PJSO.js +91 -0
  150. package/dist/chunk-J5AJNY2N.js +283 -0
  151. package/dist/chunk-J6KQZ4FO.mjs +821 -0
  152. package/dist/{chunk-OWW5GUSB.js → chunk-JGBCIKJV.js} +7 -6
  153. package/dist/chunk-JKGTBMU7.mjs +25 -0
  154. package/dist/chunk-JR3TNEQC.js +422 -0
  155. package/dist/chunk-JURRXY2J.mjs +29 -0
  156. package/dist/chunk-K3HW5I2A.mjs +317 -0
  157. package/dist/chunk-K46SMZ66.mjs +103 -0
  158. package/dist/chunk-K4UDGE3Z.mjs +6 -0
  159. package/dist/chunk-KDQOR4QQ.mjs +350 -0
  160. package/dist/chunk-KDTVOLHI.mjs +288 -0
  161. package/dist/chunk-KGHJH5KJ.mjs +35 -0
  162. package/dist/chunk-KIZOA5LX.mjs +140 -0
  163. package/dist/chunk-KK6HYVBI.mjs +242 -0
  164. package/dist/chunk-KMKWGXMK.js +856 -0
  165. package/dist/chunk-KPA6K5IB.js +80 -0
  166. package/dist/chunk-KU7O4IXU.mjs +260 -0
  167. package/dist/chunk-KVFNRJOR.mjs +11142 -0
  168. package/dist/chunk-KZJRSXHK.js +2432 -0
  169. package/dist/chunk-LHWPRUJL.js +79 -0
  170. package/dist/chunk-LIV3KXJG.mjs +369 -0
  171. package/dist/chunk-LKV4LACG.js +21 -0
  172. package/dist/chunk-LUY45X3U.mjs +263 -0
  173. package/dist/chunk-LYEZZEEF.mjs +17 -0
  174. package/dist/chunk-M5EXQZYY.mjs +1519 -0
  175. package/dist/chunk-ME6HGG4I.mjs +1338 -0
  176. package/dist/chunk-MEXP6DA6.js +31 -0
  177. package/dist/chunk-MG52AW3H.js +902 -0
  178. package/dist/chunk-MIPO6F72.js +334 -0
  179. package/dist/{chunk-5QW7CQBA.js → chunk-MKIJQL5Q.js} +211 -321
  180. package/dist/chunk-MN3YETVN.mjs +17 -0
  181. package/dist/chunk-MOBSBXVE.mjs +2391 -0
  182. package/dist/chunk-MOMOZEUM.mjs +88 -0
  183. package/dist/chunk-MRFUNRAP.js +62 -0
  184. package/dist/chunk-MTIHEW2M.js +433 -0
  185. package/dist/chunk-N4RGGDEL.mjs +73 -0
  186. package/dist/chunk-NH654HAT.js +10 -0
  187. package/dist/chunk-NHJUGZUR.mjs +253 -0
  188. package/dist/chunk-NMQT4HG3.mjs +757 -0
  189. package/dist/chunk-NPSYB6DC.mjs +906 -0
  190. package/dist/chunk-NW2GPMSO.js +857 -0
  191. package/dist/chunk-NXKQOQ6L.js +76 -0
  192. package/dist/chunk-NXLAZIJZ.js +309 -0
  193. package/dist/chunk-NYWNA5CF.js +148 -0
  194. package/dist/chunk-NZTKLY2W.js +1442 -0
  195. package/dist/chunk-O2ICABUD.js +36 -0
  196. package/dist/chunk-OIVVQQ22.js +862 -0
  197. package/dist/chunk-OKC2B4O3.mjs +312 -0
  198. package/dist/chunk-OLWFPDBK.js +2220 -0
  199. package/dist/chunk-OMTVH334.js +3779 -0
  200. package/dist/chunk-OQRVEM56.mjs +362 -0
  201. package/dist/chunk-OXMIBOD4.js +337 -0
  202. package/dist/chunk-PBL6YL5L.mjs +288 -0
  203. package/dist/chunk-PDOELNNQ.js +97 -0
  204. package/dist/chunk-PDQJY2GZ.js +136 -0
  205. package/dist/chunk-PKOZXD2Q.js +1274 -0
  206. package/dist/chunk-PPF2BYFL.mjs +2191 -0
  207. package/dist/chunk-PQTQKNKD.js +539 -0
  208. package/dist/chunk-PRSR4FAV.mjs +81 -0
  209. package/dist/chunk-PTRNO5UD.js +95 -0
  210. package/dist/chunk-Q2Y3VMKH.js +2000 -0
  211. package/dist/chunk-QCZOE65N.js +96 -0
  212. package/dist/chunk-QDYFLATW.mjs +52 -0
  213. package/dist/chunk-QQABGCMM.js +22 -0
  214. package/dist/chunk-QS6TRHMR.js +345 -0
  215. package/dist/chunk-R56P64LB.mjs +208 -0
  216. package/dist/chunk-RCQ2MPBV.js +428 -0
  217. package/dist/chunk-RFVRPYR2.mjs +856 -0
  218. package/dist/chunk-RKBLPGPV.js +11521 -0
  219. package/dist/chunk-RM2V4IND.mjs +327 -0
  220. package/dist/chunk-RQXN5A34.mjs +613 -0
  221. package/dist/chunk-RUVGVNOF.mjs +2687 -0
  222. package/dist/chunk-SAFJIGYB.mjs +165 -0
  223. package/dist/chunk-SKQFLBDD.js +263 -0
  224. package/dist/chunk-SMK6JU2F.mjs +2092 -0
  225. package/dist/{chunk-UVRPC2P7.js → chunk-SNNEOS5Z.js} +1984 -3476
  226. package/dist/chunk-SPCRQ6NO.mjs +1246 -0
  227. package/dist/chunk-SWX4SALA.mjs +19 -0
  228. package/dist/{chunk-JVODCGFP.mjs → chunk-SYEO2WV4.mjs} +128 -238
  229. package/dist/chunk-T2QQMX2N.js +10 -0
  230. package/dist/chunk-T3AFF3L7.mjs +57 -0
  231. package/dist/chunk-T6Z2EXYL.js +712 -0
  232. package/dist/chunk-T7LOXGYX.js +118 -0
  233. package/dist/chunk-TJCAE7RC.mjs +1315 -0
  234. package/dist/chunk-TJI3K6RP.js +137 -0
  235. package/dist/chunk-TL2SVO4P.mjs +55 -0
  236. package/dist/chunk-TM63CYGN.mjs +399 -0
  237. package/dist/chunk-TU5RYTYU.mjs +13 -0
  238. package/dist/chunk-TVJZ4GPS.js +1553 -0
  239. package/dist/chunk-TWM6DLYF.js +371 -0
  240. package/dist/chunk-U63OC4TQ.js +30 -0
  241. package/dist/{chunk-L5GKVQVJ.js → chunk-U6BVSJZ6.js} +25 -57
  242. package/dist/chunk-U6UVWEAK.mjs +792 -0
  243. package/dist/chunk-UCEPNO6N.mjs +11048 -0
  244. package/dist/{chunk-ANT574FD.js → chunk-UCR5HRYM.js} +74 -105
  245. package/dist/chunk-UG5BTOTF.mjs +334 -0
  246. package/dist/chunk-UGH37BQW.mjs +157 -0
  247. package/dist/chunk-V7ZRH3PY.mjs +271 -0
  248. package/dist/chunk-VBGHBL3E.mjs +1394 -0
  249. package/dist/chunk-VRBDAS5I.js +920 -0
  250. package/dist/chunk-VVE3Y76O.js +230 -0
  251. package/dist/chunk-W65JIRI4.mjs +1182 -0
  252. package/dist/chunk-WHYKAT7G.js +62 -0
  253. package/dist/{chunk-YOIVZ6OA.mjs → chunk-WIZRUIZB.mjs} +25 -57
  254. package/dist/chunk-WKWTDZS7.js +385 -0
  255. package/dist/chunk-WLMINRC4.mjs +78 -0
  256. package/dist/chunk-WOF3AD3J.js +22 -0
  257. package/dist/chunk-WWKMOA76.js +1262 -0
  258. package/dist/chunk-X5A5FOWW.js +615 -0
  259. package/dist/chunk-X6CN6KQF.mjs +192 -0
  260. package/dist/chunk-XD2PMH46.mjs +517 -0
  261. package/dist/chunk-XJA2NGTI.mjs +88 -0
  262. package/dist/chunk-XJIHN3BY.mjs +8 -0
  263. package/dist/chunk-XK6UDWJS.js +203 -0
  264. package/dist/chunk-XPG3N5CF.mjs +415 -0
  265. package/dist/chunk-XVZ2NKSU.mjs +74 -0
  266. package/dist/chunk-XYP45OLE.js +117 -0
  267. package/dist/chunk-XZSDGZX6.mjs +301 -0
  268. package/dist/chunk-Y2EMGN4T.mjs +120 -0
  269. package/dist/chunk-Y3XWP5XW.mjs +298 -0
  270. package/dist/chunk-Y4K22JL6.js +228 -0
  271. package/dist/chunk-Y65LXQGA.mjs +3164 -0
  272. package/dist/chunk-Y66WVMO5.mjs +87 -0
  273. package/dist/chunk-Y7JWLB25.mjs +7280 -0
  274. package/dist/chunk-YCDXAJKU.js +175 -0
  275. package/dist/chunk-YRDQCCIS.js +152 -0
  276. package/dist/chunk-YV52DGSA.js +111 -0
  277. package/dist/chunk-YXGZQPUD.js +94 -0
  278. package/dist/chunk-Z3A3AFVU.mjs +102 -0
  279. package/dist/chunk-ZCY6YKKP.mjs +475 -0
  280. package/dist/chunk-ZEQHXVU5.js +215 -0
  281. package/dist/chunk-ZF7JCXCI.js +284 -0
  282. package/dist/chunk-ZJBRUH6V.js +29 -0
  283. package/dist/chunk-ZMIL4ZOA.js +365 -0
  284. package/dist/chunk-ZR5ULMN2.mjs +337 -0
  285. package/dist/chunk-ZXREOYOW.js +87 -0
  286. package/dist/{client-BSP9U1O1.d.mts → client-CX_WR0-J.d.mts} +2 -2
  287. package/dist/client-Dytx_ZTC.d.ts +230 -0
  288. package/dist/{client-B878xeAP.d.ts → client-dqOhP9Nc.d.ts} +2 -2
  289. package/dist/client-hTKbCuhG.d.mts +230 -0
  290. package/dist/clock-B-UAjkKa.d.mts +5 -0
  291. package/dist/clock-B-UAjkKa.d.ts +5 -0
  292. package/dist/config-BlXQluJR.d.mts +36 -0
  293. package/dist/config-BlXQluJR.d.ts +36 -0
  294. package/dist/courier-Cnn-edJ4.d.ts +95 -0
  295. package/dist/courier-FmGfkvIN.d.mts +95 -0
  296. package/dist/crowd-DdHFbqKK.d.ts +186 -0
  297. package/dist/crowd-hOVSAmA3.d.mts +186 -0
  298. package/dist/danfo-BEBapFlX.d.mts +146 -0
  299. package/dist/danfo-UQ_PTIIx.d.ts +146 -0
  300. package/dist/{elements-Bty6Qs_N.d.mts → elements-DdsRig-2.d.mts} +1548 -257
  301. package/dist/{elements-Bty6Qs_N.d.ts → elements-DdsRig-2.d.ts} +1548 -257
  302. package/dist/engines/godot.d.mts +56 -0
  303. package/dist/engines/godot.d.ts +56 -0
  304. package/dist/engines/godot.js +28 -0
  305. package/dist/engines/godot.mjs +3 -0
  306. package/dist/engines/wasm.d.mts +11 -0
  307. package/dist/engines/wasm.d.ts +11 -0
  308. package/dist/engines/wasm.js +178 -0
  309. package/dist/engines/wasm.mjs +176 -0
  310. package/dist/fallback-CrG_lTFk.d.mts +270 -0
  311. package/dist/fallback-CrG_lTFk.d.ts +270 -0
  312. package/dist/fallback-KDB4Y2CE.mjs +6 -0
  313. package/dist/fallback-Y26TQENE.js +19 -0
  314. package/dist/features-CZB4rmcD.d.mts +118 -0
  315. package/dist/features-CZB4rmcD.d.ts +118 -0
  316. package/dist/fit-BWiE7rgA.d.mts +44 -0
  317. package/dist/fit-DK0oT7zO.d.ts +44 -0
  318. package/dist/five-a-side-Bv1AOUy3.d.mts +115 -0
  319. package/dist/five-a-side-EC51SJY1.d.ts +115 -0
  320. package/dist/fluid-ARr0qUIL.d.ts +939 -0
  321. package/dist/fluid-DLlEj2cs.d.mts +939 -0
  322. package/dist/game/conformance.d.mts +84 -0
  323. package/dist/game/conformance.d.ts +84 -0
  324. package/dist/game/conformance.js +1025 -0
  325. package/dist/game/conformance.mjs +994 -0
  326. package/dist/game/heap.d.mts +40 -0
  327. package/dist/game/heap.d.ts +40 -0
  328. package/dist/game/heap.js +48 -0
  329. package/dist/game/heap.mjs +7 -0
  330. package/dist/game/kit/canvas.d.mts +240 -0
  331. package/dist/game/kit/canvas.d.ts +240 -0
  332. package/dist/game/kit/canvas.js +3566 -0
  333. package/dist/game/kit/canvas.mjs +1039 -0
  334. package/dist/game/kit/courier.d.mts +17 -0
  335. package/dist/game/kit/courier.d.ts +17 -0
  336. package/dist/game/kit/courier.js +66 -0
  337. package/dist/game/kit/courier.mjs +49 -0
  338. package/dist/game/kit/danfo.d.mts +11 -0
  339. package/dist/game/kit/danfo.d.ts +11 -0
  340. package/dist/game/kit/danfo.js +109 -0
  341. package/dist/game/kit/danfo.mjs +44 -0
  342. package/dist/game/kit/engine.d.mts +29 -0
  343. package/dist/game/kit/engine.d.ts +29 -0
  344. package/dist/game/kit/engine.js +183 -0
  345. package/dist/game/kit/engine.mjs +30 -0
  346. package/dist/game/kit/five-a-side.d.mts +11 -0
  347. package/dist/game/kit/five-a-side.d.ts +11 -0
  348. package/dist/game/kit/five-a-side.js +86 -0
  349. package/dist/game/kit/five-a-side.mjs +41 -0
  350. package/dist/game/kit/frontier.d.mts +344 -0
  351. package/dist/game/kit/frontier.d.ts +344 -0
  352. package/dist/game/kit/frontier.js +435 -0
  353. package/dist/game/kit/frontier.mjs +14 -0
  354. package/dist/game/kit/genesis.d.mts +752 -0
  355. package/dist/game/kit/genesis.d.ts +752 -0
  356. package/dist/game/kit/genesis.js +380 -0
  357. package/dist/game/kit/genesis.mjs +15 -0
  358. package/dist/game/kit/ludo.d.mts +15 -0
  359. package/dist/game/kit/ludo.d.ts +15 -0
  360. package/dist/game/kit/ludo.js +87 -0
  361. package/dist/game/kit/ludo.mjs +42 -0
  362. package/dist/game/kit/runner.d.mts +12 -0
  363. package/dist/game/kit/runner.d.ts +12 -0
  364. package/dist/game/kit/runner.js +83 -0
  365. package/dist/game/kit/runner.mjs +46 -0
  366. package/dist/game/kit/shootout.d.mts +13 -0
  367. package/dist/game/kit/shootout.d.ts +13 -0
  368. package/dist/game/kit/shootout.js +122 -0
  369. package/dist/game/kit/shootout.mjs +57 -0
  370. package/dist/game/kit/slots.d.mts +392 -0
  371. package/dist/game/kit/slots.d.ts +392 -0
  372. package/dist/game/kit/slots.js +215 -0
  373. package/dist/game/kit/slots.mjs +6 -0
  374. package/dist/game/kit/tycoon.d.mts +16 -0
  375. package/dist/game/kit/tycoon.d.ts +16 -0
  376. package/dist/game/kit/tycoon.js +145 -0
  377. package/dist/game/kit/tycoon.mjs +44 -0
  378. package/dist/game/kit/word.d.mts +11 -0
  379. package/dist/game/kit/word.d.ts +11 -0
  380. package/dist/game/kit/word.js +78 -0
  381. package/dist/game/kit/word.mjs +41 -0
  382. package/dist/game/kit/worlds.d.mts +18 -0
  383. package/dist/game/kit/worlds.d.ts +18 -0
  384. package/dist/game/kit/worlds.js +74 -0
  385. package/dist/game/kit/worlds.mjs +49 -0
  386. package/dist/game/kit.d.mts +53 -0
  387. package/dist/game/kit.d.ts +53 -0
  388. package/dist/game/kit.js +2610 -0
  389. package/dist/game/kit.mjs +101 -0
  390. package/dist/game/prepared.d.mts +14 -0
  391. package/dist/game/prepared.d.ts +14 -0
  392. package/dist/game/prepared.js +81 -0
  393. package/dist/game/prepared.mjs +32 -0
  394. package/dist/game-Bx8onkhX.d.mts +1451 -0
  395. package/dist/game-fgQy2YIm.d.ts +1451 -0
  396. package/dist/game-theme-CBTw1b_d.d.mts +35 -0
  397. package/dist/game-theme-Dg-ict5A.d.ts +35 -0
  398. package/dist/game.d.mts +3546 -0
  399. package/dist/game.d.ts +3546 -0
  400. package/dist/game.js +4455 -0
  401. package/dist/game.mjs +50 -0
  402. package/dist/graphics-C6YjWYvP.d.ts +5 -0
  403. package/dist/graphics-Dk2yQnYN.d.mts +5 -0
  404. package/dist/guest-DrsA00XD.d.mts +732 -0
  405. package/dist/guest-wIdfoT05.d.ts +732 -0
  406. package/dist/hit-stop-BKkVwTq7.d.mts +43 -0
  407. package/dist/hit-stop-D-8pPYnM.d.ts +43 -0
  408. package/dist/hot-Crn9XpHJ.d.ts +29 -0
  409. package/dist/hot-DH3nOhQD.d.mts +29 -0
  410. package/dist/{index-CQStGb3B.d.mts → index-6gkHMGAq.d.mts} +2 -2
  411. package/dist/index-B8ybCKJI.d.ts +41 -0
  412. package/dist/{index-DJwXmoaP.d.ts → index-B98Xac8e.d.ts} +2 -2
  413. package/dist/{index-B7oA_1XI.d.ts → index-B_ByTtIT.d.ts} +2 -2
  414. package/dist/index-DHjNHb1c.d.mts +41 -0
  415. package/dist/{index-DhUSTAhT.d.mts → index-DbAN_VQE.d.mts} +2 -2
  416. package/dist/index.d.mts +134 -24
  417. package/dist/index.d.ts +134 -24
  418. package/dist/index.js +407 -248
  419. package/dist/index.mjs +184 -58
  420. package/dist/interactives-authoring.d.mts +231 -0
  421. package/dist/interactives-authoring.d.ts +231 -0
  422. package/dist/interactives-authoring.js +1743 -0
  423. package/dist/interactives-authoring.mjs +1704 -0
  424. package/dist/interactives-canvas.global.js +148 -0
  425. package/dist/interactives-guest.d.mts +20 -0
  426. package/dist/interactives-guest.d.ts +20 -0
  427. package/dist/interactives-guest.js +63 -0
  428. package/dist/interactives-guest.json +1 -0
  429. package/dist/interactives-guest.mjs +61 -0
  430. package/dist/interactives-jsc.global.js +9357 -0
  431. package/dist/interactives-meters.d.mts +93 -0
  432. package/dist/interactives-meters.d.ts +93 -0
  433. package/dist/interactives-meters.js +252 -0
  434. package/dist/interactives-meters.mjs +68 -0
  435. package/dist/interactives-production.d.mts +430 -0
  436. package/dist/interactives-production.d.ts +430 -0
  437. package/dist/interactives-production.js +1231 -0
  438. package/dist/interactives-production.mjs +1170 -0
  439. package/dist/interactives-record.d.mts +112 -0
  440. package/dist/interactives-record.d.ts +112 -0
  441. package/dist/interactives-record.js +302 -0
  442. package/dist/interactives-record.mjs +295 -0
  443. package/dist/interactives-runtime.d.mts +61 -0
  444. package/dist/interactives-runtime.d.ts +61 -0
  445. package/dist/interactives-runtime.js +442 -0
  446. package/dist/interactives-runtime.mjs +25 -0
  447. package/dist/interactives-studio-kernel.global.js +1 -0
  448. package/dist/interactives-studio.d.mts +806 -0
  449. package/dist/interactives-studio.d.ts +806 -0
  450. package/dist/interactives-studio.js +5741 -0
  451. package/dist/interactives-studio.mjs +5651 -0
  452. package/dist/interactives-tick.d.mts +90 -0
  453. package/dist/interactives-tick.d.ts +90 -0
  454. package/dist/interactives-tick.js +203 -0
  455. package/dist/interactives-tick.mjs +6 -0
  456. package/dist/interactives-web.d.mts +762 -0
  457. package/dist/interactives-web.d.ts +762 -0
  458. package/dist/interactives-web.js +5000 -0
  459. package/dist/interactives-web.mjs +4628 -0
  460. package/dist/interactives.d.mts +2430 -0
  461. package/dist/interactives.d.ts +2430 -0
  462. package/dist/interactives.js +5723 -0
  463. package/dist/interactives.mjs +4333 -0
  464. package/dist/juice-CoHxlpKA.d.ts +42 -0
  465. package/dist/juice-DQztFS43.d.mts +42 -0
  466. package/dist/launch-T2f4_Di4.d.mts +151 -0
  467. package/dist/launch-d6oreMzR.d.ts +151 -0
  468. package/dist/library-DXYaMFhi.d.mts +69 -0
  469. package/dist/library-DXYaMFhi.d.ts +69 -0
  470. package/dist/link-BUTqGmyi.d.mts +38 -0
  471. package/dist/link-BUTqGmyi.d.ts +38 -0
  472. package/dist/lint.js +104 -204
  473. package/dist/lint.mjs +103 -203
  474. package/dist/local-D8_I6UeL.d.mts +6967 -0
  475. package/dist/local-VZkqsCzR.d.ts +6967 -0
  476. package/dist/lockstep-BLf6dglI.d.mts +321 -0
  477. package/dist/lockstep-D50Ia0JW.d.ts +321 -0
  478. package/dist/ludo-B8ClkDqr.d.ts +205 -0
  479. package/dist/ludo-BOuohQ-M.d.mts +205 -0
  480. package/dist/mock/cli.mjs +200 -56
  481. package/dist/mock/library.js +200 -56
  482. package/dist/mock/library.mjs +200 -56
  483. package/dist/mock/msw.js +200 -56
  484. package/dist/mock/msw.mjs +200 -56
  485. package/dist/native-BodxSh03.d.mts +16 -0
  486. package/dist/native-DUHMT8gA.d.ts +16 -0
  487. package/dist/network-ZXLD7l1b.d.mts +19 -0
  488. package/dist/network-ZXLD7l1b.d.ts +19 -0
  489. package/dist/online-XeymeM9s.d.ts +381 -0
  490. package/dist/online-d7W_Al9a.d.mts +381 -0
  491. package/dist/params-DxFb5G_U.d.mts +155 -0
  492. package/dist/params-DxFb5G_U.d.ts +155 -0
  493. package/dist/play-BRRlfLhX.d.ts +940 -0
  494. package/dist/play-ClrMd_e8.d.mts +940 -0
  495. package/dist/policy-CCw8tXLm.d.mts +3078 -0
  496. package/dist/policy-CMqOSQIu.d.ts +3078 -0
  497. package/dist/ports-B_0v_P3A.d.mts +13 -0
  498. package/dist/ports-CGU_3e_0.d.ts +13 -0
  499. package/dist/prefetch-BHnicOQj.d.ts +117 -0
  500. package/dist/prefetch-CBXgYacv.d.mts +117 -0
  501. package/dist/{price-CSztR02F.d.mts → price-BOzexBww.d.mts} +1 -1
  502. package/dist/{price-C_vasx9A.d.ts → price-C1h9sPxE.d.ts} +1 -1
  503. package/dist/protocol-C8qbpUbT.d.mts +242 -0
  504. package/dist/protocol-C8qbpUbT.d.ts +242 -0
  505. package/dist/rapier-AZHT4YI7.js +7886 -0
  506. package/dist/rapier-ODEPCQA6.mjs +7792 -0
  507. package/dist/react.d.mts +157 -15
  508. package/dist/react.d.ts +157 -15
  509. package/dist/react.js +5564 -5904
  510. package/dist/react.mjs +5451 -5808
  511. package/dist/runner-CQcLL7By.d.ts +189 -0
  512. package/dist/runner-D46Yj-wE.d.mts +189 -0
  513. package/dist/runtime-BRWfkf_q.d.mts +51 -0
  514. package/dist/runtime-DyuBMkKM.d.ts +51 -0
  515. package/dist/scheduling-D2ajXpMC.d.ts +224 -0
  516. package/dist/scheduling-DSRbbaZb.d.mts +224 -0
  517. package/dist/schema-BrWxzKp6.d.mts +63 -0
  518. package/dist/schema-BrWxzKp6.d.ts +63 -0
  519. package/dist/server/evict.js +34 -37
  520. package/dist/server/evict.mjs +34 -37
  521. package/dist/server/tanstack.d.mts +49 -3
  522. package/dist/server/tanstack.d.ts +49 -3
  523. package/dist/server/tanstack.js +169 -117
  524. package/dist/server/tanstack.mjs +166 -118
  525. package/dist/{server-Dckg4Vdr.d.ts → server-D29IIuDV.d.ts} +136 -130
  526. package/dist/{server-B6dW7-Lj.d.mts → server-DQMWPnc8.d.mts} +136 -130
  527. package/dist/server.d.mts +45 -5
  528. package/dist/server.d.ts +45 -5
  529. package/dist/server.js +171 -227
  530. package/dist/server.mjs +165 -225
  531. package/dist/session-grant-CJ27DwrT.d.mts +19 -0
  532. package/dist/session-grant-CJ27DwrT.d.ts +19 -0
  533. package/dist/shootout-BJZeX6FG.d.ts +140 -0
  534. package/dist/shootout-tcZd1Rxt.d.mts +140 -0
  535. package/dist/state-replica-stMtdkVD.d.mts +42 -0
  536. package/dist/state-replica-stMtdkVD.d.ts +42 -0
  537. package/dist/studio-CowqWqez.d.mts +14 -0
  538. package/dist/studio-CowqWqez.d.ts +14 -0
  539. package/dist/styles.css +1 -1
  540. package/dist/template-AhCdB1kW.d.mts +190 -0
  541. package/dist/template-BkEGVTQj.d.ts +190 -0
  542. package/dist/terrain-BMxEc6Oc.d.ts +429 -0
  543. package/dist/terrain-C-XC1Oui.d.mts +429 -0
  544. package/dist/testing/msw.d.mts +28 -4
  545. package/dist/testing/msw.d.ts +28 -4
  546. package/dist/testing/msw.js +15 -21
  547. package/dist/testing/msw.mjs +15 -21
  548. package/dist/testing/suite.d.mts +6 -5
  549. package/dist/testing/suite.d.ts +6 -5
  550. package/dist/testing/suite.js +89 -124
  551. package/dist/testing/suite.mjs +81 -116
  552. package/dist/testing.d.mts +27 -1227
  553. package/dist/testing.d.ts +27 -1227
  554. package/dist/testing.js +127 -131
  555. package/dist/testing.mjs +19 -23
  556. package/dist/tick-transport-C8QEh8Uw.d.mts +50 -0
  557. package/dist/tick-transport-UjHY3xK1.d.ts +50 -0
  558. package/dist/timeline-protocol-hp6e8zFB.d.mts +47 -0
  559. package/dist/timeline-protocol-hp6e8zFB.d.ts +47 -0
  560. package/dist/tokens-DhanQRQS.d.mts +21 -0
  561. package/dist/tokens-K8yxwd6G.d.ts +21 -0
  562. package/dist/tree-C-Io2Hbx.d.mts +35 -0
  563. package/dist/tree-CP_qSW4H.d.ts +35 -0
  564. package/dist/tycoon-B5KHk2Xx.d.mts +255 -0
  565. package/dist/tycoon-hmHo-3HX.d.ts +255 -0
  566. package/dist/types-BQkxPwZP.d.mts +219 -0
  567. package/dist/types-D_f6UUxM.d.ts +219 -0
  568. package/dist/ui-DwHicuFv.d.mts +563 -0
  569. package/dist/ui-hi7S2YcH.d.ts +563 -0
  570. package/dist/{sign-in-DQlIdqsi.d.mts → url-52ndUruG.d.mts} +15 -1
  571. package/dist/{sign-in-DQlIdqsi.d.ts → url-52ndUruG.d.ts} +15 -1
  572. package/dist/utils.d.mts +3 -3
  573. package/dist/utils.d.ts +3 -3
  574. package/dist/utils.js +37 -37
  575. package/dist/utils.mjs +4 -4
  576. package/dist/vars-Dc_PrhBK.d.mts +511 -0
  577. package/dist/vars-Dc_PrhBK.d.ts +511 -0
  578. package/dist/vm-IUARFFAI.mjs +63 -0
  579. package/dist/vm-N7L6MGGH.js +65 -0
  580. package/dist/weave-delivery-CW-Kstut.d.mts +360 -0
  581. package/dist/weave-delivery-CW-Kstut.d.ts +360 -0
  582. package/dist/web-Dss74a7v.d.ts +883 -0
  583. package/dist/web-f9ZQPoyw.d.mts +883 -0
  584. package/dist/web-transport-C7MkBL0a.d.ts +19 -0
  585. package/dist/web-transport-aYEqXMd9.d.mts +19 -0
  586. package/dist/weight-CPGjsgjV.d.ts +92 -0
  587. package/dist/weight-tF1ODR1p.d.mts +92 -0
  588. package/dist/word-BcX9Jcmv.d.mts +70 -0
  589. package/dist/word-C7sVPLHm.d.ts +70 -0
  590. package/dist/world-PvILHDR1.d.ts +2285 -0
  591. package/dist/world-qekkXjJv.d.mts +2285 -0
  592. package/dist/worlds-Br2Pb0Cs.d.ts +109 -0
  593. package/dist/worlds-D5ydYr7d.d.mts +109 -0
  594. package/engines/c/cimplify.h +108 -0
  595. package/engines/c/cimplify.lib.js +11 -0
  596. package/engines/godot/addons/cimplify/cimplify.gd +97 -0
  597. package/engines/rust/interactives-ctx/Cargo.toml +9 -0
  598. package/engines/rust/interactives-ctx/src/lib.rs +189 -0
  599. package/package.json +189 -3
  600. package/vendor/rapier3d-compat/LICENSE +201 -0
  601. package/vendor/rapier3d-compat/PATCHES.md +61 -0
  602. package/dist/chunk-2P4KXFB6.js +0 -274
  603. package/dist/chunk-3G6RQLXK.mjs +0 -21
  604. package/dist/chunk-3V4DVXV3.mjs +0 -254
  605. package/dist/chunk-EDK3LNM6.js +0 -2436
  606. package/dist/chunk-F7J3HK27.js +0 -4549
  607. package/dist/chunk-U4MW6PYU.mjs +0 -23
  608. package/dist/chunk-XREIZ56K.js +0 -26
@@ -0,0 +1,3164 @@
1
+ import { bakeRate, propertySize, INTERPOLATION_CODES, LOOP_CODES, SYNC_MODE_CODES, checkSyncMarkers, HUMAN_BONES, BLEND_SPACE_CODES, IK_CODES, DEFAULT_IK_ITERATIONS, DEFAULT_IK_TOLERANCE, animationLodInterval, ROOT_MOTION_WORDS, emptyClipEvent, CLIP_EVENT_KINDS } from './chunk-7ARSJPV3.mjs';
2
+ import { createWithDescriptor, EngineFeatures, refuseUndrawnPhysicalFields, MATERIAL_KINDS, writeMaterialExtension, extraTextures, writeMaterialFeatures, materialFeatureFlags, writeMaterialTint, writeCharacterWords, writeTextureTransforms, writePlanes, materialSlotIndex, writeMaterialState, LIGHT_KINDS, writeNodeFeatures, OWNER_STAGING, writeSky, writeTintWords, WebAudioPort, HeadlessAudio, WorkletAudio, engineTerrainExports, EngineTerrain, CAP_CUSTOM_PROJECTION, CAP_POINT_SHADOWS, SHADOW_TYPES, floatBits } from './chunk-7BHW5GTC.mjs';
3
+ import { bindKernelEngine, engineStoryExports, EngineStory, checkColliderClass, packContactRuleHeader, writeContactRulePayload, DEFAULT_EXTENTS, VEHICLE_DESC_WORDS, INPUT_STRIDE, STATE_STRIDE, ENGINE_AI_EXPORT_NAMES, ENGINE_AI_WORLD_STEP, MAX_WAVES, SEA_STATES, WATER_SAMPLE_WORDS } from './chunk-RUVGVNOF.mjs';
4
+ import { bindSoaEngine, castShapeCode } from './chunk-XPG3N5CF.mjs';
5
+ import { writeMediumDesc } from './chunk-ATAWRACV.mjs';
6
+ import { FRAME_SECONDS_SLOT, FRAME_NOW_MS_SLOT, FRAME_ALPHA_SLOT } from './chunk-IDLW4NWA.mjs';
7
+ import { engineVectorSurfaceExports, EngineVectorSurfaces, ENGINE_AUDIO_WORKLET_EXPORTS, ENGINE_AUDIO_EXPORT_NAMES, EngineAudioPort, EngineMemory, WorldSnapshots, DEFAULT_ROLLBACK_FRAMES, hasRollback, ROLLBACK_CONFIG_WORDS, writeRollbackConfig, releaseEngineArena, engineJoints } from './chunk-GXKI64OT.mjs';
8
+ import { engineStreamExports, EngineWorldStreaming, engineSplatExports, EngineScenery } from './chunk-NHJUGZUR.mjs';
9
+ import { BLEND_FACTORS, BUFFER_OWNER_CAPABILITIES, TEXTURE_KIND_EXTERNAL, TEXTURE_FORMAT_RGBA32I, TEXTURE_FORMAT_R32I, TEXTURE_FORMAT_RGBA32UI, TEXTURE_FORMAT_RGBA16UI, TEXTURE_FORMAT_RGBA8UI, TEXTURE_FORMAT_RG32UI, TEXTURE_FORMAT_R32UI, TEXTURE_FORMAT_R16UI, TEXTURE_FORMAT_R8UI, TEXTURE_FORMAT_RG32F, TEXTURE_FORMAT_R32F, TEXTURE_FORMAT_RG16F, TEXTURE_FORMAT_R16F, TEXTURE_FORMAT_RG8, TEXTURE_FORMAT_R8, TEXTURE_KIND_2D_ARRAY, TEXTURE_KIND_3D, TEXTURE_ENCODE_ASTC_4X4, TEXTURE_ENCODE_BC7, TEXTURE_ENCODE_AUTO, OP_MARK_TEXTURE_REGION, MATERIAL_SLOTS, OP_SET_MATERIAL_WORD, OP_MARK_EMITTER, OP_EMIT, OP_SET_EMITTER_RATE, OP_CLEAR_EMITTER, OP_DESTROY_EMITTER, OP_SET_RENDER_ORDER, OP_SET_SHADOW, STAT_THERMAL_TIER, NODE_POSE_FLOATS, MEDIA_VOLUME_FEATURE, FOG_MODES, TONE_MAPPINGS, ENV_TONE_CURVE, ENV_GI, GI_MODES, ENV_GI_INTENSITY, ENV_GI_SPACING, ENV_GI_SUN_ANGLE, OP_SET_VOLUMETRICS, TARGET_KIND_CUBE, TARGET_KIND_ARRAY, TARGET_KIND_2D, TARGET_KIND, TARGET_LAYERS, TARGET_SAMPLED_DEPTH, TARGET_COLORS, TARGET_TEXTURES, TARGET_MAX_COLORS, MAX_CHAIN_EFFECTS, EFFECT_LENS_FLARE, OP_SET_EFFECT, POST_EFFECT_TEXTURES, OP_SET_EFFECT_TEXTURE, OP_SET_WEATHER, OP_SET_TIME_OF_DAY, PASS_SLICE, PASS_FLAGS, PASS_FLAG_CUBE_FACE, PASS_FLAG_REFLECT, PASS_FLAG_ONCE, PASS_PLANE, useTransformEngine, bindTransformEngine, bindChemistryEngine, engineSmokeExports, EngineSmoke, engineReactiveExports, EngineReactive, engineFluidExports, EngineFluids, engineDestructionExports, EngineDestruction, RENDER_CORE_EXPORTS, RENDER_FEATURE_EXPORTS, OP_ANIMATION, ANIM_SET_TIME, ANIM_SET_SPEED, ANIM_SET_LOOP, ANIM_SET_PAUSED, ANIM_SET_RANGE, ANIM_SET_SYNC, ANIM_SET_SYNC_MODE, ANIM_SET_SYNC_MARKERS, ANIM_INERTIALIZE, ANIM_BAKE_RETARGET, ANIM_SET_EVENTS, OP_SET_CLIP_ADDITIVE, ANIM_CROSSFADE, ANIM_FADE, ANIM_CREATE_MASK, OP_SET_CLIP_MASK, ANIM_DESTROY, ANIM_KIND_MASK, ANIM_SET_CLIP_EVENTS, ANIM_CLIP_INFO, ANIM_CREATE_BLEND, ANIM_SET_BLEND, ANIM_KIND_BLEND, ANIM_CREATE_IK, ANIM_SET_IK_TARGET, ANIM_SET_IK_POLE, ANIM_KIND_IK, ANIM_HUMANOID, ANIM_RETARGET, ANIM_KIND_RETARGET, ANIM_SET_LOD, ROOT_MOTION_XZ, ROOT_MOTION_Y, ROOT_MOTION_YAW, ROOT_MOTION_APPLY, ANIM_ROOT_MOTION, ANIM_KIND_ROOT_MOTION, ANIMATION_BUFFER_ROOT_MOTION, ANIMATION_BUFFER_ACTIONS, ANIM_ACTION_RUNNING, ANIM_ACTION_PAUSED, ANIM_ACTION_FINISHED, ANIMATION_BUFFER_EVENTS, ANIM_MAX_EVENTS, EMITTER_SHAPES, EMITTER_COLLISIONS, OP_RAW_MARK_BUFFER, OP_RAW_MARK_TEXTURE, OP_RAW_COPY_TEXTURE, OP_RAW_DESTROY_TEXTURE, OP_RAW_DISPATCH, OP_RAW_DRAW, OP_RAW_COPY, OP_RAW_DESTROY_BUFFER, ANIM_ACTION_WORDS, ANIM_EVENT_WORDS, RENDER_KERNEL_INSTANCES_FEATURE, RENDER_FEED_POSE_FEATURE } from './chunk-E65WCTIG.mjs';
10
+ import { engineClothExports, EngineCloths, engineSoftBodyExports, EngineSoftBodies, SOFT_BODY_FEATURE, CRUMPLE_IMPACT_FLOATS } from './chunk-5YFBGGCK.mjs';
11
+ import { engineSessionFailure, hasPhysics, requireEngineMemoryHeld } from './chunk-GHS6MIL6.mjs';
12
+ import { COLUMN_ALIGN, ERROR_INVALID_ARGUMENT, WORD_BYTES, ERROR_UNSUPPORTED, ERROR_UNKNOWN_RESOURCE, ERROR_DEAD_ENTITY, ERROR_CAPACITY_EXCEEDED, DESC_WORDS, WORLD_GRAVITY, WORLD_STEP_SECONDS, WORLD_MAX_BODIES, WORLD_MAX_COLLIDERS, WORLD_MAX_JOINTS, WORLD_MAX_CONTACTS, WORLD_MAX_CONTROLLERS, DEFAULT_MAX_COMMANDS, WORLD_MAX_COMMANDS, REGISTER_WORDS, COMMAND_WORDS, COMMAND_OP, COMMAND_BODY, COMMAND_PAYLOAD, LAYOUT_POSITION, LAYOUT_ROTATION, LAYOUT_SCALE, LAYOUT_PREVIOUS_POSITION, LAYOUT_PREVIOUS_ROTATION, LAYOUT_PREVIOUS_SCALE, LAYOUT_PARENT, LAYOUT_RENDER, LAYOUT_ENTITIES, LAYOUT_SPARSE, LAYOUT_CAPACITY, LAYOUT_SPARSE_LEN, OP_SET_GRAVITY, BODY_KIND_DYNAMIC, BODY_KIND_KINEMATIC, BODY_KIND_FIXED, BODY_KIND, BODY_LINEAR_DAMPING, BODY_ANGULAR_DAMPING, BODY_GRAVITY_SCALE, BODY_FLAGS, BODY_FLAG_CCD, BODY_FLAG_CAN_SLEEP, BODY_DOMINANCE, COLLIDER_SHAPE, COLLIDER_DATA_A, COLLIDER_DATA_A_LEN, COLLIDER_ROWS, COLLIDER_COLUMNS, COLLIDER_PARAMS, COLLIDER_DATA_B, COLLIDER_DATA_B_LEN, COLLIDER_BORDER, COLLIDER_OFFSET, COLLIDER_ROTATION, COLLIDER_DENSITY, COLLIDER_MASS, COLLIDER_FRICTION, COLLIDER_RESTITUTION, COLLIDER_FLAGS, COLLIDER_FLAG_SENSOR, COLLIDER_FLAG_EVENTS, COLLIDER_FLAG_GROUPS, COLLISION_GROUP_ALL, COLLIDER_MEMBERSHIP, COLLIDER_FILTER, JOINT_ANCHOR_A, JOINT_ANCHOR_B, JOINT_SIX_DOF, JOINT_KIND, JOINT_CONE, JOINT_AXIS, JOINT_SWING, JOINT_LIMITS, JOINT_SPRING, JOINT_LENGTH, JOINT_STIFFNESS, JOINT_DAMPING, JOINT_ROPE, JOINT_REVOLUTE, JOINT_PRISMATIC, JOINT_HAS_LIMITS, JOINT_SPHERICAL, JOINT_FIXED, REGISTER_MOTOR_VELOCITY, REGISTER_MOTOR_MAX_FORCE, OP_SET_BODY_POSE, OP_SET_LINEAR_VELOCITY, OP_SET_ANGULAR_VELOCITY, OP_APPLY_IMPULSE, OP_APPLY_TORQUE_IMPULSE, OP_ADD_FORCE, OP_APPLY_IMPULSE_AT_POINT, OP_ADD_FORCE_AT_POINT, OP_ADD_TORQUE, VECTOR_OUT, MOTOR_TARGET, MOTOR_STIFFNESS, MOTOR_DAMPING, CAST_SHAPE, CAST_PARAMS, CAST_ROTATION, RAY_ORIGIN, RAY_DIRECTION, RAY_MAX, RAY_INCLUDE_SENSORS, NO_EXCLUDE, RAY_EXCLUDE, RAY_HIT, HIT_COLLIDER, HIT_DISTANCE, HIT_POINT, HIT_NORMAL, OP_RESET_FORCES, OP_WAKE, RAY_SOLID, CONTROLLER_OFFSET, CONTROLLER_MAX_SLOPE_CLIMB, CONTROLLER_MIN_SLOPE_SLIDE, CONTROLLER_AUTOSTEP_HEIGHT, CONTROLLER_AUTOSTEP_WIDTH, CONTROLLER_SNAP, CONTROLLER_SLIDE_UNSET, CONTROLLER_SLIDE, CONTROLLER_HAS_UP, CONTROLLER_UP, GROUNDED_OUT, OP_SET_COLLIDER_CLASS, OP_SET_CONTACT_RULE, OP_SET_COLLIDER_GROUPS, OP_SET_SOLVER, OP_SET_BODY_SOFT_CCD, OP_SET_BODY_SLEEP, REGISTER_FRAME_ALPHA, REGISTER_FRAME_VERSION_LOW, REGISTER_FRAME_VERSION_HIGH, U32_RANGE, ENGINE_EXPORT_ARITY, ENGINE_EXPORT_PROTOTYPES, SHAPE_COMPOUND, SHAPE_ROUND_CONVEX_HULL, SHAPE_ROUND_CONE, SHAPE_ROUND_CYLINDER, SHAPE_ROUND_CUBOID, SHAPE_HEIGHTFIELD, SHAPE_CONVEX_HULL, SHAPE_TRIMESH, SHAPE_CONE, SHAPE_CYLINDER, SHAPE_CAPSULE, SHAPE_CUBOID, SHAPE_BALL, PART_FLOATS, PART_SHAPE, PART_OFFSET, PART_ROTATION, JOINT_FRAME_A, JOINT_FRAME_B, MOTION_FREE, JOINT_AXIS_LIMITS, JOINT_MOTIONS, JOINT_SWING_CONE, PART_BORDER, PART_PARAMS, MOTION_BITS, BODY_TRANSLATION_SHIFT, BODY_ROTATION_SHIFT, MOTION_LOCKED, MOTION_LIMITED } from './chunk-A33OORT7.mjs';
13
+ import { registerFontTable, FontTable } from './chunk-XJA2NGTI.mjs';
14
+ import { noteInspectorWorld } from './chunk-MOMOZEUM.mjs';
15
+ import { GameError } from './chunk-XJIHN3BY.mjs';
16
+
17
+ // src/game/gpu/engine.ts
18
+ var WORD = 4, DEFAULT_WORKGROUP = 1, ENTRY_BYTES = 52 * (4), MAX_TARGETS = 4, PACK_SHIFT = 16, NUL = 0, DEPTH_UNSET = 0, USAGE = {
19
+ storage: 1,
20
+ uniform: 2,
21
+ vertex: 4,
22
+ index: 8,
23
+ indirect: 16,
24
+ copy_src: 32,
25
+ copy_dst: 64,
26
+ map_read: 128
27
+ }, TEXTURE_USAGE = {
28
+ sampled: 1,
29
+ storage: 2,
30
+ target: 4
31
+ }, FORMAT = {
32
+ rgba8: 0,
33
+ rgba16f: 2,
34
+ rgba32f: 1
35
+ }, TEXEL_BYTES = {
36
+ rgba8: 4,
37
+ rgba16f: 8,
38
+ rgba32f: 16
39
+ }, FACTOR = {
40
+ zero: BLEND_FACTORS.indexOf("zero"),
41
+ one: BLEND_FACTORS.indexOf("one"),
42
+ src: BLEND_FACTORS.indexOf("srcColor"),
43
+ "one-minus-src": BLEND_FACTORS.indexOf("oneMinusSrcColor"),
44
+ "src-alpha": BLEND_FACTORS.indexOf("srcAlpha"),
45
+ "one-minus-src-alpha": BLEND_FACTORS.indexOf("oneMinusSrcAlpha"),
46
+ dst: BLEND_FACTORS.indexOf("dstColor"),
47
+ "one-minus-dst": BLEND_FACTORS.indexOf("oneMinusDstColor"),
48
+ "dst-alpha": BLEND_FACTORS.indexOf("dstAlpha"),
49
+ "one-minus-dst-alpha": BLEND_FACTORS.indexOf("oneMinusDstAlpha"),
50
+ "src-alpha-saturated": BLEND_FACTORS.indexOf("srcAlphaSaturate")
51
+ }, TOPOLOGY = {
52
+ "triangle-list": 0,
53
+ "triangle-strip": 1,
54
+ "line-list": 2,
55
+ "point-list": 3
56
+ }, SCENE_COLOR_FORMAT = "rgba16f", HOOK_ORDER = ["beforeScene", "afterOpaque", "afterTransparent", "post", "afterPost"], SCENE = {
57
+ depth: 4294967280,
58
+ motion: 4294967281,
59
+ color: 4294967282,
60
+ instances: 4294967283,
61
+ particles: 4294967284
62
+ }, SCENE_TEXTURE = {
63
+ depth: 4294967280,
64
+ motion: 4294967281,
65
+ color: 4294967282
66
+ };
67
+ function failure(code, what) {
68
+ switch (code) {
69
+ case ERROR_CAPACITY_EXCEEDED:
70
+ return new GameError("capacity_exceeded", `${what}: capacity exceeded`);
71
+ case ERROR_DEAD_ENTITY:
72
+ case ERROR_UNKNOWN_RESOURCE:
73
+ return new GameError("unknown_resource", `${what}: unknown resource`);
74
+ case ERROR_UNSUPPORTED:
75
+ return new GameError("unsupported_feature", `${what}: unsupported`);
76
+ default:
77
+ return new GameError("invalid_argument", `${what}: invalid argument`);
78
+ }
79
+ }
80
+ function packBlend(blend) {
81
+ return blend ? (FACTOR[blend.color.src] << 0 | FACTOR[blend.color.dst] << 5 | FACTOR[blend.alpha.src] << 10 | FACTOR[blend.alpha.dst] << 15) >>> 0 : 0;
82
+ }
83
+ function pack(pair2) {
84
+ return (pair2[0] | pair2[1] << (16)) >>> 0;
85
+ }
86
+ var EngineRaw = class {
87
+ constructor(host) {
88
+ this.api = "wgsl";
89
+ this.shaders = [null];
90
+ this.sizes = /* @__PURE__ */ new Map();
91
+ this.textures = /* @__PURE__ */ new Map();
92
+ this.targetFormats = /* @__PURE__ */ new Map();
93
+ this.encoder = new TextEncoder();
94
+ this.reads = [];
95
+ this.host = host;
96
+ }
97
+ createBuffer(desc) {
98
+ if (desc.size <= 0 || desc.size % (4) !== 0)
99
+ throw new GameError("invalid_argument", `gpu buffer size ${desc.size} must be a positive multiple of ${(4)}`);
100
+ let d = this.host.clearDesc();
101
+ d[0] = desc.size;
102
+ let usage = 0;
103
+ for (let u of desc.usage) usage |= USAGE[u];
104
+ d[1] = usage;
105
+ let id = this.check(this.host.call("engine_render_raw_buffer"), "create gpu buffer");
106
+ return this.sizes.set(id, desc.size), id;
107
+ }
108
+ writeBuffer(buffer, offset, data) {
109
+ let size = this.size(buffer);
110
+ if (offset < 0 || offset % (4) !== 0 || offset + data.byteLength > size)
111
+ throw new GameError("invalid_argument", `write of ${data.byteLength} bytes at ${offset} overflows gpu buffer ${buffer}`);
112
+ this.host.flush(), this.host.bytes(10, buffer, 0).set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength), offset), this.host.command(OP_RAW_MARK_BUFFER, buffer);
113
+ }
114
+ createTexture(desc) {
115
+ let d = this.host.clearDesc();
116
+ d[0] = desc.width, d[1] = desc.height, d[2] = FORMAT[desc.format];
117
+ let usage = 0;
118
+ for (let u of desc.usage) usage |= TEXTURE_USAGE[u];
119
+ d[3] = usage, d[4] = desc.mipLevels ?? 1;
120
+ let id = this.check(this.host.call("engine_render_raw_texture"), "create gpu texture");
121
+ return this.textures.set(id, { width: desc.width, height: desc.height, format: desc.format }), id;
122
+ }
123
+ writeTexture(texture, data) {
124
+ let info = this.texture(texture), bytes = info.width * info.height * TEXEL_BYTES[info.format];
125
+ if (data.byteLength !== bytes)
126
+ throw new GameError("invalid_argument", `texture ${texture} takes exactly ${bytes} bytes`);
127
+ this.host.flush(), this.host.bytes(11, texture, 0).set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength)), this.host.command(OP_RAW_MARK_TEXTURE, texture);
128
+ }
129
+ readTexture(texture, rect, out) {
130
+ let info = this.texture(texture), bytes = rect.width * rect.height * TEXEL_BYTES[info.format];
131
+ if (out.byteLength < bytes) throw new GameError("invalid_argument", `readTexture needs ${bytes} bytes`);
132
+ this.host.flush();
133
+ let request = this.check(
134
+ this.host.call("engine_render_raw_read_texture", texture, rect.x, rect.y, rect.width, rect.height),
135
+ "read gpu texture"
136
+ );
137
+ return new Promise((resolve, reject) => {
138
+ this.reads.push({ request, buffer: null, texture, offset: 0, out: out.subarray(0, bytes), resolve, reject });
139
+ });
140
+ }
141
+ copyTexture(source, target, copy) {
142
+ let info = this.texture(source), a = this.host.command(OP_RAW_COPY_TEXTURE, source), w = this.host.commandWords;
143
+ w[a] = target, w[a + 1] = pack(copy?.from ?? [0, 0]), w[a + 2] = pack(copy?.to ?? [0, 0]), w[a + 3] = pack(copy?.size ?? [info.width, info.height]), w[a + 4] = HOOK_ORDER.indexOf(copy?.hook ?? "beforeScene");
144
+ }
145
+ destroyTexture(texture) {
146
+ this.host.command(OP_RAW_DESTROY_TEXTURE, texture), this.textures.delete(texture), this.reject((read) => read.texture === texture, `gpu texture ${texture} was destroyed`);
147
+ }
148
+ createSampler(desc) {
149
+ let d = this.host.clearDesc();
150
+ return d[0] = desc?.filter === "nearest" ? 1 : 0, d[1] = desc?.wrap === "clamp" ? 1 : desc?.wrap === "mirror" ? 2 : 0, this.check(this.host.call("engine_render_raw_sampler"), "create gpu sampler");
151
+ }
152
+ createShader(wgsl) {
153
+ return this.shaders.push(wgsl), this.shaders.length - 1;
154
+ }
155
+ createComputePipeline(desc) {
156
+ let size = desc.workgroupSize ?? [(1), (1), (1)];
157
+ return this.pipeline(desc.shader, this.encoder.encode(desc.entryPoint), (d) => {
158
+ d[4] = 0, d[1] = size[0], d[2] = size[1], d[3] = size[2];
159
+ });
160
+ }
161
+ createRenderPipeline(desc) {
162
+ if (desc.targets.length === 0 || desc.targets.length > (4))
163
+ throw new GameError("invalid_argument", `render pipelines take 1 to ${(4)} targets`);
164
+ let vertex = this.encoder.encode(desc.vertexEntry), fragment = this.encoder.encode(desc.fragmentEntry), entry = new Uint8Array(vertex.byteLength + 1 + fragment.byteLength);
165
+ entry.set(vertex), entry[vertex.byteLength] = (0), entry.set(fragment, vertex.byteLength + 1);
166
+ let id = this.pipeline(desc.shader, entry, (d) => {
167
+ d[4] = 1, desc.targets.forEach((format, t) => {
168
+ d[5 + t] = FORMAT[format] + 1;
169
+ }), d[9] = packBlend(desc.blend), d[10] = (0), d[11] = TOPOLOGY[desc.topology ?? "triangle-list"];
170
+ });
171
+ return this.targetFormats.set(id, desc.targets[0]), id;
172
+ }
173
+ createBindGroup(pipeline, group, bindings) {
174
+ if (bindings.length > 11)
175
+ throw new GameError("capacity_exceeded", `bind groups take at most ${11} bindings`);
176
+ this.host.flush();
177
+ let d = this.host.clearDesc();
178
+ return d[0] = pipeline, d[1] = group, d[2] = bindings.length, bindings.forEach((b, i) => {
179
+ let at = 3 + i * 5;
180
+ if (d[at + 0] = b.binding, "texture" in b) {
181
+ d[at + 4] = 1, d[at + 1] = typeof b.texture == "string" ? SCENE_TEXTURE[b.texture] : b.texture;
182
+ return;
183
+ }
184
+ if ("sampler" in b) {
185
+ d[at + 4] = 2, d[at + 1] = b.sampler;
186
+ return;
187
+ }
188
+ let scene = typeof b.buffer == "string";
189
+ d[at + 4] = 0, d[at + 1] = scene ? SCENE[b.buffer] : b.buffer, d[at + 2] = b.offset ?? 0, d[at + 3] = b.size ?? (scene ? 0 : this.size(b.buffer) - (b.offset ?? 0));
190
+ }), this.check(this.host.call("engine_render_raw_bindings"), "create bind group");
191
+ }
192
+ dispatch(pipeline, bindGroup, x, y = (1), z = (1), options) {
193
+ let a = this.host.command(OP_RAW_DISPATCH, pipeline), w = this.host.commandWords;
194
+ w[a + 0] = bindGroup, w[a + 1] = x, w[a + 1 + 1] = y, w[a + 1 + 2] = z, w[a + 4] = HOOK_ORDER.indexOf(options?.hook ?? "beforeScene"), w[a + 5] = options?.indirect ?? 0;
195
+ }
196
+ draw(pipeline, bindGroup, vertexCount, options) {
197
+ let target = options?.target ?? "color", hook = options?.hook ?? (target === "color" ? "post" : "afterTransparent");
198
+ if (target === "color") {
199
+ if (hook !== "post")
200
+ throw new GameError("invalid_argument", "draws into scene colour run on the post hook");
201
+ if (this.targetFormats.get(pipeline) !== SCENE_COLOR_FORMAT)
202
+ throw new GameError("invalid_argument", `scene colour draws need a ${SCENE_COLOR_FORMAT} target`);
203
+ }
204
+ let a = this.host.command(OP_RAW_DRAW, pipeline), w = this.host.commandWords;
205
+ w[a + 0] = bindGroup, w[a + 1] = vertexCount, w[a + 2] = options?.instances ?? 1, w[a + 3] = target === "color" ? 4294967282 : target, w[a + 4] = HOOK_ORDER.indexOf(hook), w[a + 5] = 0;
206
+ }
207
+ copyBuffer(source, sourceOffset, target, targetOffset, size) {
208
+ let a = this.host.command(OP_RAW_COPY, source), w = this.host.commandWords;
209
+ w[a] = sourceOffset, w[a + 1] = target, w[a + 2] = targetOffset, w[a + 3] = size;
210
+ }
211
+ submit() {
212
+ this.host.flush(), this.poll();
213
+ }
214
+ readBuffer(buffer, offset, out) {
215
+ this.host.flush();
216
+ let request = this.check(
217
+ this.host.call("engine_render_raw_read", buffer, offset, out.byteLength),
218
+ "read gpu buffer"
219
+ );
220
+ return new Promise((resolve, reject) => {
221
+ this.reads.push({ request, buffer, texture: null, offset, out, resolve, reject });
222
+ });
223
+ }
224
+ destroyBuffer(buffer) {
225
+ this.host.command(OP_RAW_DESTROY_BUFFER, buffer), this.sizes.delete(buffer), this.reject((read) => read.buffer === buffer, `gpu buffer ${buffer} was destroyed`);
226
+ }
227
+ dispose() {
228
+ for (let id of this.sizes.keys()) this.host.command(OP_RAW_DESTROY_BUFFER, id);
229
+ for (let id of this.textures.keys()) this.host.command(OP_RAW_DESTROY_TEXTURE, id);
230
+ this.host.flush(), this.sizes.clear(), this.textures.clear(), this.reject(() => true, "gpu was disposed");
231
+ }
232
+ pipeline(shader, entry, configure) {
233
+ let source = this.shaders[shader];
234
+ if (!source) throw new GameError("unknown_resource", `shader ${shader} does not exist`);
235
+ if (entry.byteLength === 0 || entry.byteLength > ENTRY_BYTES)
236
+ throw new GameError("invalid_argument", `entry point names must fit ${ENTRY_BYTES} bytes`);
237
+ this.host.flush();
238
+ let bytes = this.encoder.encode(source), pointer = this.host.stage(bytes), d = this.host.clearDesc();
239
+ return d[0] = entry.byteLength, configure(d), new Uint8Array(d.buffer, d.byteOffset + 12 * (4), entry.byteLength).set(entry), this.check(
240
+ this.host.call("engine_render_raw_pipeline", pointer, bytes.byteLength),
241
+ "create gpu pipeline"
242
+ );
243
+ }
244
+ reject(matches, message) {
245
+ let kept = [];
246
+ for (let read of this.reads)
247
+ matches(read) ? read.reject(new GameError("unknown_resource", message)) : kept.push(read);
248
+ this.reads = kept;
249
+ }
250
+ poll() {
251
+ if (this.reads.length === 0) return;
252
+ let waiting = [];
253
+ for (let read of this.reads) {
254
+ let pointer = this.host.call("engine_render_raw_poll", read.request);
255
+ if (pointer === 0) {
256
+ waiting.push(read);
257
+ continue;
258
+ }
259
+ if (read.buffer !== null) {
260
+ let source = this.host.bytes(10, read.buffer, 0);
261
+ read.out.set(source.subarray(read.offset, read.offset + read.out.byteLength));
262
+ } else
263
+ read.out.set(this.host.view(pointer, read.out.byteLength));
264
+ read.resolve();
265
+ }
266
+ this.reads = waiting;
267
+ }
268
+ size(buffer) {
269
+ let size = this.sizes.get(buffer);
270
+ if (size === void 0) throw new GameError("unknown_resource", `gpu buffer ${buffer} does not exist`);
271
+ return size;
272
+ }
273
+ texture(texture) {
274
+ let info = this.textures.get(texture);
275
+ if (!info) throw new GameError("unknown_resource", `gpu texture ${texture} does not exist`);
276
+ return info;
277
+ }
278
+ check(code, what) {
279
+ if (code < 0) throw failure(code, what);
280
+ return code;
281
+ }
282
+ };
283
+ function createEngineGpu(host) {
284
+ return (host.capabilities & 8192) === 0 ? null : new EngineRaw(host);
285
+ }
286
+
287
+ // src/game/backends/engine/clips.ts
288
+ var NO_JOINT = 4294967295, IK_HEADER = 8, BLEND_MEMBER_WORDS = 3, CLIP_INFO_WORDS = 4, EXPLICIT_MAP = 1, RETARGET_HEADER = 2, BAKE_HEADER = 4, FULL_TURN = Math.PI * 2, ANIM_CREATE_PROPERTY_CLIP = 40, ANIM_PLAY_PROPERTY_CLIP = 41, ANIM_DESTROY_PROPERTY_CLIP = 42, ANIM_SET_PROPERTY_EVENTS = 43, BIND_COMMAND = 0, BIND_MATERIAL_UNIFORM = 1, PROPERTY_TEMPLATE = 8, PROPERTY_TEMPLATE_WORDS = 6, PROPERTY_TRACK_HEADER = (8) + (6), EngineClips = class {
289
+ constructor(host) {
290
+ this.host = host;
291
+ this.bits = new Float32Array(1);
292
+ this.bitWords = new Uint32Array(this.bits.buffer);
293
+ }
294
+ floatBits(value) {
295
+ return this.bits[0] = value, this.bitWords[0];
296
+ }
297
+ op(target, sub) {
298
+ let at = this.host.command(OP_ANIMATION, target);
299
+ return this.host.commandWords[at] = sub, at + 1;
300
+ }
301
+ joint(root, bone) {
302
+ let index = this.host.model(root).nodeNames.indexOf(bone);
303
+ if (index < 0) throw new GameError("unknown_resource", `model has no bone ${bone}`);
304
+ return index;
305
+ }
306
+ clipIndex(root, clip) {
307
+ let index = this.host.model(root).clipNames.indexOf(clip);
308
+ if (index < 0) throw new GameError("unknown_resource", `model has no clip ${clip}`);
309
+ return index;
310
+ }
311
+ createPropertyClip(desc) {
312
+ let sizes = desc.tracks.map(propertySize), words = 2;
313
+ desc.tracks.forEach((track, i) => {
314
+ words += PROPERTY_TRACK_HEADER + sizes[i] + track.times.length + track.values.length;
315
+ });
316
+ let out = new Uint32Array(words);
317
+ out[0] = this.floatBits(desc.duration), out[1] = desc.tracks.length;
318
+ let at = 2;
319
+ return desc.tracks.forEach((track, i) => {
320
+ let size = sizes[i], header = out.subarray(at, at + PROPERTY_TRACK_HEADER);
321
+ this.bindTarget(track.target, size, header), header[4] = size, header[5] = INTERPOLATION_CODES[track.interpolation ?? "linear"], header[6] = track.times.length, at += PROPERTY_TRACK_HEADER;
322
+ for (let k = 0; k < size; k++) out[at++] = this.floatBits(track.rest[k]);
323
+ for (let k = 0; k < track.times.length; k++) out[at++] = this.floatBits(track.times[k]);
324
+ for (let k = 0; k < track.values.length; k++) out[at++] = this.floatBits(track.values[k]);
325
+ }), this.host.animation((40), 0, out);
326
+ }
327
+ bindTarget(target, size, header) {
328
+ let template = header.subarray((8), (8) + (6));
329
+ switch (target.kind) {
330
+ case "uniform": {
331
+ let slot = this.host.uniformSlot(target.material, target.name);
332
+ if (size > slot.words) throw new GameError("invalid_argument", `uniform ${target.name} holds ${slot.words} values`);
333
+ header[0] = (1), header[1] = 0, header[2] = target.material, header[3] = slot.offset;
334
+ return;
335
+ }
336
+ case "light":
337
+ header[0] = (0), header[1] = 12, header[2] = target.node, header[3] = 1, template[0] = target.color >>> 0;
338
+ return;
339
+ case "post":
340
+ header[0] = (0), header[1] = 24, header[2] = target.chain, header[3] = 2, template[0] = target.effect, template[1] = this.host.postParam(target.chain, target.effect, target.name);
341
+ return;
342
+ case "emitterRate":
343
+ header[0] = (0), header[1] = OP_SET_EMITTER_RATE, header[2] = target.emitter, header[3] = 0;
344
+ return;
345
+ }
346
+ }
347
+ playPropertyClip(clip, loop, fadeSeconds, speed) {
348
+ let words = Uint32Array.of(clip, loop ? 1 : 0, this.floatBits(fadeSeconds), this.floatBits(speed));
349
+ return this.host.animation((41), 0, words);
350
+ }
351
+ setPropertyClipEvents(clip, events) {
352
+ let words = new Uint32Array(1 + events.length * 2);
353
+ words[0] = clip, events.forEach((event, i) => {
354
+ words[1 + i * 2] = this.floatBits(event.time), words[2 + i * 2] = event.id >>> 0;
355
+ }), this.host.animation((43), 0, words);
356
+ }
357
+ destroyPropertyClip(clip) {
358
+ this.host.animation((42), 0, Uint32Array.of(clip));
359
+ }
360
+ setClipTime(action, seconds) {
361
+ this.host.commandFloats[this.op(action, ANIM_SET_TIME)] = seconds;
362
+ }
363
+ setClipSpeed(action, speed) {
364
+ this.host.commandFloats[this.op(action, ANIM_SET_SPEED)] = speed;
365
+ }
366
+ setClipLoop(action, loop, repetitions, clampWhenFinished) {
367
+ let at = this.op(action, ANIM_SET_LOOP), w = this.host.commandWords;
368
+ w[at] = LOOP_CODES[loop], w[at + 1] = Number.isFinite(repetitions) ? Math.max(0, repetitions | 0) : 0, w[at + 2] = clampWhenFinished ? 1 : 0;
369
+ }
370
+ setClipPaused(action, paused) {
371
+ this.host.commandWords[this.op(action, ANIM_SET_PAUSED)] = paused ? 1 : 0;
372
+ }
373
+ setClipRange(action, start, end) {
374
+ let at = this.op(action, ANIM_SET_RANGE);
375
+ this.host.commandFloats[at] = start, this.host.commandFloats[at + 1] = end;
376
+ }
377
+ setClipSync(action, group) {
378
+ this.host.commandWords[this.op(action, ANIM_SET_SYNC)] = group === null ? 0 : (group & 2147483647) + 1;
379
+ }
380
+ setClipSyncMode(action, mode) {
381
+ this.host.commandWords[this.op(action, ANIM_SET_SYNC_MODE)] = SYNC_MODE_CODES[mode];
382
+ }
383
+ setClipSyncMarkers(root, clip, markers) {
384
+ checkSyncMarkers(markers, Number.POSITIVE_INFINITY);
385
+ let words = new Uint32Array(1 + markers.length * 2);
386
+ words[0] = this.clipIndex(root, clip), markers.forEach((marker, i) => {
387
+ words[1 + i * 2] = this.floatBits(marker.time), words[2 + i * 2] = marker.id >>> 0;
388
+ }), this.host.animation(ANIM_SET_SYNC_MARKERS, root, words);
389
+ }
390
+ inertialize(from, to, seconds) {
391
+ let at = this.op(from, ANIM_INERTIALIZE);
392
+ this.host.commandWords[at] = to, this.host.commandFloats[at + 1] = seconds;
393
+ }
394
+ bakeRetarget(target, source, clip, options) {
395
+ let maps = options?.maps, words = new Uint32Array((4) + (maps === void 0 ? 0 : HUMAN_BONES.length * 2)).fill((4294967295));
396
+ words[0] = source, words[1] = this.clipIndex(source, clip), words[2] = this.floatBits(bakeRate(options)), words[3] = maps === void 0 ? 0 : (1), maps !== void 0 && this.writeMaps(words, (4), target, source, maps);
397
+ let index = this.host.animation(ANIM_BAKE_RETARGET, target, words), name = this.host.refreshModel(target).clipNames[index];
398
+ if (name === void 0) throw new GameError("unknown_resource", `baked clip ${index} is missing on the target model`);
399
+ return name;
400
+ }
401
+ writeMaps(words, at, target, source, maps) {
402
+ HUMAN_BONES.forEach((bone, i) => {
403
+ let from = maps.source[bone], to = maps.target[bone];
404
+ from !== void 0 && (words[at + i] = this.joint(source, from)), to !== void 0 && (words[at + HUMAN_BONES.length + i] = this.joint(target, to));
405
+ });
406
+ }
407
+ setClipEventsEnabled(action, enabled) {
408
+ this.host.commandWords[this.op(action, ANIM_SET_EVENTS)] = enabled ? 1 : 0;
409
+ }
410
+ setClipAdditive(action, referenceTime) {
411
+ this.host.commandFloats[this.host.command(OP_SET_CLIP_ADDITIVE, action)] = referenceTime ?? Number.POSITIVE_INFINITY;
412
+ }
413
+ crossFade(from, to, seconds, warp) {
414
+ let at = this.op(from, ANIM_CROSSFADE);
415
+ this.host.commandWords[at] = to, this.host.commandFloats[at + 1] = seconds, this.host.commandWords[at + 2] = warp ? 1 : 0;
416
+ }
417
+ fadeClip(action, weight, seconds) {
418
+ let at = this.op(action, ANIM_FADE);
419
+ this.host.commandFloats[at] = weight, this.host.commandFloats[at + 1] = seconds;
420
+ }
421
+ fadeClipFrom(action, values, offset) {
422
+ let at = this.op(action, ANIM_FADE), f = this.host.commandFloats;
423
+ f[at] = values[offset], f[at + 1] = values[offset + 1];
424
+ }
425
+ createClipMask(root, weights) {
426
+ let names = this.host.model(root).nodeNames, words = new Uint32Array(names.length);
427
+ for (let [bone, weight] of Object.entries(weights)) words[this.joint(root, bone)] = this.floatBits(weight);
428
+ return this.host.animation(ANIM_CREATE_MASK, root, words);
429
+ }
430
+ setClipMask(action, mask) {
431
+ this.host.commandWords[this.host.command(OP_SET_CLIP_MASK, action)] = mask ?? 0;
432
+ }
433
+ destroyClipMask(root, mask) {
434
+ this.host.animation(ANIM_DESTROY, root, Uint32Array.of(ANIM_KIND_MASK, mask));
435
+ }
436
+ setClipEvents(root, clip, events) {
437
+ let words = new Uint32Array(1 + events.length * 2);
438
+ words[0] = this.clipIndex(root, clip), events.forEach((event, i) => {
439
+ words[1 + i * 2] = this.floatBits(event.time), words[2 + i * 2] = event.id >>> 0;
440
+ }), this.host.animation(ANIM_SET_CLIP_EVENTS, root, words);
441
+ }
442
+ clipInfo(root, clip) {
443
+ let words = new Uint32Array((4));
444
+ return words[0] = this.clipIndex(root, clip), this.host.animation(ANIM_CLIP_INFO, root, words), this.bitWords[0] = words[0], { duration: this.bits[0], tracks: words[1], morphWeights: words[2], events: words[3] };
445
+ }
446
+ createBlendSpace(root, desc) {
447
+ let words = new Uint32Array(2 + desc.members.length * (3));
448
+ return words[0] = BLEND_SPACE_CODES[desc.kind], words[1] = desc.members.length, desc.members.forEach((member, i) => {
449
+ let at = 2 + i * (3);
450
+ words[at] = member.action, words[at + 1] = this.floatBits(member.x), words[at + 2] = this.floatBits(member.y ?? 0);
451
+ }), this.host.animation(ANIM_CREATE_BLEND, root, words);
452
+ }
453
+ setBlendParameter(space, x, y, weight) {
454
+ let at = this.op(space, ANIM_SET_BLEND);
455
+ this.host.commandFloats[at] = x, this.host.commandFloats[at + 1] = y, this.host.commandFloats[at + 2] = weight;
456
+ }
457
+ setBlendParameterFrom(space, values, offset) {
458
+ let at = this.op(space, ANIM_SET_BLEND), f = this.host.commandFloats;
459
+ f[at] = values[offset], f[at + 1] = values[offset + 1], f[at + 2] = values[offset + 2];
460
+ }
461
+ destroyBlendSpace(root, space) {
462
+ this.host.animation(ANIM_DESTROY, root, Uint32Array.of(ANIM_KIND_BLEND, space));
463
+ }
464
+ createIk(root, desc) {
465
+ let words = new Uint32Array((8) + desc.bones.length), forward = desc.forward ?? [0, 0, 1];
466
+ return words[0] = IK_CODES[desc.solver], words[1] = desc.iterations ?? DEFAULT_IK_ITERATIONS, words[2] = this.floatBits(desc.tolerance ?? DEFAULT_IK_TOLERANCE), words[3] = this.floatBits(desc.maxAngle ?? FULL_TURN), words[4] = this.floatBits(forward[0]), words[5] = this.floatBits(forward[1]), words[6] = this.floatBits(forward[2]), words[7] = desc.bones.length, desc.bones.forEach((bone, i) => {
467
+ words[(8) + i] = this.joint(root, bone);
468
+ }), this.host.animation(ANIM_CREATE_IK, root, words);
469
+ }
470
+ setIkTarget(chain, x, y, z, weight) {
471
+ let at = this.op(chain, ANIM_SET_IK_TARGET), f = this.host.commandFloats;
472
+ f[at] = x, f[at + 1] = y, f[at + 2] = z, f[at + 3] = weight;
473
+ }
474
+ setIkTargetFrom(chain, values, offset) {
475
+ let at = this.op(chain, ANIM_SET_IK_TARGET), f = this.host.commandFloats;
476
+ f[at] = values[offset], f[at + 1] = values[offset + 1], f[at + 2] = values[offset + 2], f[at + 3] = values[offset + 3];
477
+ }
478
+ setIkPole(chain, x, y, z) {
479
+ let at = this.op(chain, ANIM_SET_IK_POLE), f = this.host.commandFloats;
480
+ f[at] = x, f[at + 1] = y, f[at + 2] = z;
481
+ }
482
+ destroyIk(root, chain) {
483
+ this.host.animation(ANIM_DESTROY, root, Uint32Array.of(ANIM_KIND_IK, chain));
484
+ }
485
+ humanoid(root) {
486
+ let words = new Uint32Array(HUMAN_BONES.length);
487
+ this.host.animation(ANIM_HUMANOID, root, words);
488
+ let names = this.host.model(root).nodeNames, map = {};
489
+ return HUMAN_BONES.forEach((bone, i) => {
490
+ words[i] !== (4294967295) && (map[bone] = names[words[i]]);
491
+ }), map;
492
+ }
493
+ retarget(target, source, maps) {
494
+ if (maps === void 0) {
495
+ this.host.animation(ANIM_RETARGET, target, Uint32Array.of(source, 0));
496
+ return;
497
+ }
498
+ let words = new Uint32Array((2) + HUMAN_BONES.length * 2).fill((4294967295));
499
+ words[0] = source, words[1] = (1), this.writeMaps(words, (2), target, source, maps), this.host.animation(ANIM_RETARGET, target, words);
500
+ }
501
+ stopRetarget(target) {
502
+ this.host.animation(ANIM_DESTROY, target, Uint32Array.of(ANIM_KIND_RETARGET, 0));
503
+ }
504
+ createBoneSet(root, bones) {
505
+ let nodes = new Uint32Array(bones.length);
506
+ return bones.forEach((bone, i) => {
507
+ let node = this.host.findNode(root, bone);
508
+ if (node === null) throw new GameError("unknown_resource", `model has no bone ${bone}`);
509
+ nodes[i] = node;
510
+ }), this.host.createPoseReader(nodes);
511
+ }
512
+ readBonePoses(set, out, offset) {
513
+ this.host.readPoses(set, out, offset);
514
+ }
515
+ destroyBoneSet(set) {
516
+ this.host.destroyPoseReader(set);
517
+ }
518
+ setAnimationLod(root, interval) {
519
+ this.host.animation(ANIM_SET_LOD, root, Uint32Array.of(animationLodInterval(interval)));
520
+ }
521
+ enableRootMotion(root, desc) {
522
+ let flags = (desc.horizontal ?? true ? ROOT_MOTION_XZ : 0) | (desc.vertical ? ROOT_MOTION_Y : 0) | (desc.yaw ? ROOT_MOTION_YAW : 0) | (desc.apply ? ROOT_MOTION_APPLY : 0);
523
+ if (flags === 0 || flags === ROOT_MOTION_APPLY)
524
+ throw new GameError("invalid_argument", "root motion needs at least one extracted axis");
525
+ return this.host.animation(ANIM_ROOT_MOTION, root, Uint32Array.of(flags, this.joint(root, desc.bone)));
526
+ }
527
+ disableRootMotion(root) {
528
+ this.host.animation(ANIM_DESTROY, root, Uint32Array.of(ANIM_KIND_ROOT_MOTION, 0));
529
+ }
530
+ readRootMotion(motion, out, offset) {
531
+ let words = this.host.floats(ANIMATION_BUFFER_ROOT_MOTION);
532
+ out.set(words.subarray(motion * ROOT_MOTION_WORDS, (motion + 1) * ROOT_MOTION_WORDS), offset);
533
+ }
534
+ readClipState(action, out) {
535
+ let floats = this.host.floats(ANIMATION_BUFFER_ACTIONS), at = action * ANIM_ACTION_WORDS;
536
+ this.bits[0] = floats[at + 3];
537
+ let flags = this.bitWords[0];
538
+ out.time = floats[at], out.weight = floats[at + 1], out.speed = floats[at + 2], out.running = (flags & ANIM_ACTION_RUNNING) !== 0, out.paused = (flags & ANIM_ACTION_PAUSED) !== 0, out.finished = (flags & ANIM_ACTION_FINISHED) !== 0;
539
+ }
540
+ readClipEvents(out) {
541
+ let words = this.host.words(ANIMATION_BUFFER_EVENTS), count = Math.min(words[0], ANIM_MAX_EVENTS);
542
+ for (let i = 0; i < count; i++) {
543
+ let at = 1 + i * ANIM_EVENT_WORDS, event = out[i] ?? emptyClipEvent();
544
+ event.action = words[at], event.kind = CLIP_EVENT_KINDS[words[at + 1]] ?? "event", event.id = words[at + 2], this.bitWords[0] = words[at + 3], event.time = this.bits[0], out[i] = event;
545
+ }
546
+ return count;
547
+ }
548
+ };
549
+
550
+ // src/game/backends/engine/emitters.ts
551
+ var CURVE_CHANNELS = 4, DEFAULT_LIFETIME = 1, DEFAULT_SPEED = 1, DEFAULT_SIZE = 0.1, WHITE = 16777215;
552
+ function pair(d, at, value, fallback) {
553
+ d[at] = value?.[0] ?? fallback, d[at + 1] = value?.[1] ?? fallback;
554
+ }
555
+ function writeEmitterDesc(d, f, desc) {
556
+ d[0] = desc.capacity, f[1] = desc.rate ?? 0, d[2] = desc.burst ?? 0, pair(f, 3, desc.lifetime, (1)), pair(f, 5, desc.speed, (1)), pair(f, 7, desc.size, (0.1)), d[9] = desc.color?.[0] ?? (16777215), d[10] = desc.color?.[1] ?? desc.color?.[0] ?? (16777215), f[11] = desc.alpha?.[0] ?? 1, f[12] = desc.alpha?.[1] ?? 1, f.set(desc.gravity ?? [0, 0, 0], 13), f[16] = desc.drag ?? 0, f[17] = desc.noise?.strength ?? 0, f[18] = desc.noise?.scale ?? 1;
557
+ let shape = desc.shape ?? { kind: "point" };
558
+ switch (d[19] = EMITTER_SHAPES.indexOf(shape.kind), shape.kind) {
559
+ case "sphere":
560
+ case "disc":
561
+ f[20] = shape.radius;
562
+ break;
563
+ case "cone":
564
+ f[20] = shape.angle, f[21] = shape.radius ?? 0;
565
+ break;
566
+ case "box":
567
+ f.set(shape.size, 20);
568
+ break;
569
+ }
570
+ let collision = desc.collision ?? { kind: "none" };
571
+ d[24] = EMITTER_COLLISIONS.indexOf(collision.kind), collision.kind === "plane" && f.set(collision.plane, 25), collision.kind !== "none" && (f[29] = collision.bounce ?? 0), d[30] = desc.material ?? 0, d[31] = (desc.soft ? 1 : 0) | (desc.sorted ? 2 : 0) | (desc.localSpace ? 4 : 0) | (desc.deterministic ? 8 : 0) | (desc.additive ? 16 : 0) | (desc.stretch ? 32 : 0) | (desc.oit ? 64 : 0) | (desc.velocityAligned ? 128 : 0), d[32] = desc.seed ?? 0, f[33] = desc.spread ?? 0, f[34] = desc.spin ?? 0, d[36] = desc.sizeCurve || desc.colorCurve ? 32 : 0;
572
+ }
573
+ function channel(point, c) {
574
+ return typeof point.value == "number" ? point.value : point.value[c];
575
+ }
576
+ function sampleCurve(points, out) {
577
+ if (points.length === 0) return;
578
+ let segment = 0;
579
+ for (let i = 0; i < 32; i++) {
580
+ let t = i / 31;
581
+ for (; segment < points.length - 1 && points[segment + 1].t < t; ) segment++;
582
+ let a = points[segment], b = points[Math.min(segment + 1, points.length - 1)], span = b.t - a.t, k = span > 0 ? Math.min(1, Math.max(0, (t - a.t) / span)) : 0;
583
+ for (let c = 0; c < (4); c++) {
584
+ let from = channel(a, c);
585
+ out[i * (4) + c] = from + (channel(b, c) - from) * k;
586
+ }
587
+ }
588
+ }
589
+
590
+ // src/game/render/environment.ts
591
+ var channel2 = (hex, shift) => (hex >> shift & 255) / 255;
592
+ function volumetricChunks(words) {
593
+ let chunks = [];
594
+ for (let at = 0; at < words.length; at += 5)
595
+ chunks.push([at, words.subarray(at, Math.min(at + 5, words.length))]);
596
+ return chunks;
597
+ }
598
+ function volumetricWords(desc) {
599
+ let words = new Float32Array(24).fill(Number.NaN), flags = desc.enabled === false ? 1 : 0, fog = desc.fog;
600
+ if (fog) {
601
+ flags |= 2;
602
+ let albedo = fog.albedo ?? 15132390;
603
+ words.set(
604
+ [
605
+ fog.density ?? UNSET,
606
+ fog.height ?? UNSET,
607
+ fog.falloff ?? UNSET,
608
+ fog.anisotropy ?? UNSET,
609
+ channel2(albedo, 16),
610
+ channel2(albedo, 8),
611
+ channel2(albedo, 0),
612
+ fog.noise ?? UNSET,
613
+ fog.range ?? UNSET,
614
+ fog.ambient ?? UNSET
615
+ ],
616
+ 1
617
+ );
618
+ }
619
+ let clouds = desc.clouds;
620
+ clouds && (flags |= 4, words.set(
621
+ [
622
+ clouds.coverage ?? UNSET,
623
+ clouds.density ?? UNSET,
624
+ clouds.altitude ?? UNSET,
625
+ clouds.thickness ?? UNSET,
626
+ clouds.type ?? UNSET,
627
+ clouds.shadow ?? UNSET,
628
+ clouds.detail ?? UNSET
629
+ ],
630
+ 11
631
+ ));
632
+ let atmosphere = desc.atmosphere;
633
+ return atmosphere && (flags |= 8, words.set(
634
+ [
635
+ atmosphere.rayleigh ?? UNSET,
636
+ atmosphere.mie ?? UNSET,
637
+ atmosphere.mieAnisotropy ?? UNSET,
638
+ atmosphere.ozone ?? UNSET,
639
+ atmosphere.groundAlbedo ?? UNSET,
640
+ atmosphere.sunDiscDegrees ?? UNSET
641
+ ],
642
+ 18
643
+ )), words[0] = flags, words;
644
+ }
645
+ var UNSET_WETNESS = -1, UNSET = Number.NaN, unit = (value) => Math.min(Math.max(value ?? 0, 0), 1);
646
+ function weatherWords(state) {
647
+ return {
648
+ cloudCover: unit(state.cloudCover),
649
+ haze: unit(state.haze),
650
+ precipitation: unit(state.precipitation),
651
+ snow: state.snow ?? false,
652
+ wetness: state.wetness === void 0 ? (-1) : unit(state.wetness),
653
+ windX: state.wind?.[0] ?? 0,
654
+ windZ: state.wind?.[1] ?? 0
655
+ };
656
+ }
657
+
658
+ // src/game/backends/engine/advertised.ts
659
+ function engineAdvertises(runtime, feature) {
660
+ let count = runtime.symbols.engine_feature_count, name = runtime.symbols.engine_feature_name;
661
+ if (typeof count != "function" || typeof name != "function") return false;
662
+ let scratch = runtime.exports.engine_alloc(64, 1);
663
+ if (scratch === 0) return false;
664
+ let found = false;
665
+ for (let i = 0; i < count() && !found; i++) {
666
+ let length = name(i, scratch, 64);
667
+ if (length !== feature.length) continue;
668
+ let bytes = new Uint8Array(runtime.memory.buffer, scratch, length);
669
+ found = true;
670
+ for (let k = 0; k < length && found; k++) found = bytes[k] === feature.charCodeAt(k);
671
+ }
672
+ return runtime.exports.engine_free(scratch, 64, 1), found;
673
+ }
674
+
675
+ // src/game/backends/engine/graphics.ts
676
+ var ENGINE_GRAPHICS_NAME = "cimplify-render", NO_HANDLE = 0, GOVERNOR_TIER_MASK = 255, AUTO_QUALITY_TIER = -1, QUALITY_TIER_FULL = 0, GOVERNOR_PRESSURE_SHIFT = 28, GOVERNOR_PRESSURE_MASK = 15, MIN_REFRESH_INTERVAL_MS = 1, MAX_REFRESH_INTERVAL_MS = 100, REFRESH_WINDOW_FRAMES = 64, MICROS_PER_MS = 1e3, BUDGET_TOLERANCE = 50, NO_PRESENT_YET = -1, REFRESH_PRESENTED = 0, REFRESH_SHORTEST = 1, NO_NODE = 0, SRGB_KNEE = 0.04045, SRGB_SLOPE = 12.92, SRGB_OFFSET = 0.055, SRGB_SCALE = 1.055, SRGB_GAMMA = 2.4, BYTE_MAX = 255, DEFAULT_GROUND = 4473924, DEFAULT_SPOT_ANGLE = Math.PI / 3, DEFAULT_DECAY = 2, DEFAULT_IOR = 1.5, DEFAULT_ROUGHNESS = 1, DEFAULT_POINT_SIZE = 1, POSE_STRIDE2 = 10, NODE_BUFFER_SLOTS = 4, UTF8 = new TextEncoder(), UTF8_BYTES_PER_UNIT = 3, DEFAULT_TEXT_CAPACITY = 128, DEFAULT_TEXT3D_SIZE = 1, DEFAULT_TEXT2D_SIZE = 16, DEFAULT_TEXT_COLOR = 16777215, LINEAR = 0, SRGB = 1, TEXT_ALIGNS = {
677
+ start: 0,
678
+ end: 1,
679
+ left: 2,
680
+ center: 3,
681
+ right: 4
682
+ }, TEXT_DIRECTIONS = {
683
+ auto: 0,
684
+ ltr: 1,
685
+ rtl: 2
686
+ }, PICK_HIT = 1, NAMES = new TextDecoder(), NAME_SEPARATOR = 0, SEMANTICS = {
687
+ position: 0,
688
+ normal: 1,
689
+ uv: 2,
690
+ uv1: 3,
691
+ uv2: 3,
692
+ color: 4,
693
+ tangent: 5,
694
+ skinIndex: 6,
695
+ skinWeight: 7
696
+ }, EFFECT_PARAMETERS = {
697
+ bloom: ["strength", "radius", "threshold", "physical"],
698
+ fxaa: [],
699
+ vignette: ["offset", "darkness"],
700
+ color_grade: ["exposure", "contrast", "saturation"],
701
+ shader: [],
702
+ ao: ["radius", "intensity", "thickness", "quality"],
703
+ smaa: ["threshold", "temporal"],
704
+ taa: ["feedback", "sharpness"],
705
+ outline: ["thickness", "depthThreshold", "normalThreshold", "color"],
706
+ ssr: ["intensity", "maxDistance", "thickness", "fade"],
707
+ dof: ["focus", "aperture", "maxBlur"],
708
+ motion_blur: ["intensity", "samples"],
709
+ lut: ["texture", "intensity", "size"],
710
+ grain: ["intensity"],
711
+ god_rays: ["intensity", "decay", "density", "weight"],
712
+ lens_dirt: ["texture", "intensity"],
713
+ sharpen: ["sharpness"],
714
+ chromatic: ["amount"],
715
+ mask: ["texture", "outline", "bloom", "hidden"],
716
+ weather: ["rain", "snow", "wetness", "night"],
717
+ lens_flare: ["intensity", "ghosts", "halo", "dispersal"]
718
+ }, TEXEL_FORMATS = {
719
+ rgba8: [0, 4],
720
+ rgba16f: [2, 8],
721
+ rgba32f: [1, 16],
722
+ r8: [TEXTURE_FORMAT_R8, 1],
723
+ rg8: [TEXTURE_FORMAT_RG8, 2],
724
+ r16f: [TEXTURE_FORMAT_R16F, 2],
725
+ rg16f: [TEXTURE_FORMAT_RG16F, 4],
726
+ r32f: [TEXTURE_FORMAT_R32F, 4],
727
+ rg32f: [TEXTURE_FORMAT_RG32F, 8],
728
+ r8ui: [TEXTURE_FORMAT_R8UI, 1],
729
+ r16ui: [TEXTURE_FORMAT_R16UI, 2],
730
+ r32ui: [TEXTURE_FORMAT_R32UI, 4],
731
+ rg32ui: [TEXTURE_FORMAT_RG32UI, 8],
732
+ rgba8ui: [TEXTURE_FORMAT_RGBA8UI, 4],
733
+ rgba16ui: [TEXTURE_FORMAT_RGBA16UI, 8],
734
+ rgba32ui: [TEXTURE_FORMAT_RGBA32UI, 16],
735
+ r32i: [TEXTURE_FORMAT_R32I, 4],
736
+ rgba32i: [TEXTURE_FORMAT_RGBA32I, 16]
737
+ }, EFFECT_KINDS = {
738
+ bloom: 0,
739
+ fxaa: 1,
740
+ vignette: 2,
741
+ color_grade: 3,
742
+ shader: 4,
743
+ ao: 5,
744
+ smaa: 6,
745
+ taa: 7,
746
+ outline: 8,
747
+ ssr: 9,
748
+ dof: 10,
749
+ motion_blur: 11,
750
+ lut: 12,
751
+ grain: 13,
752
+ god_rays: 14,
753
+ lens_dirt: 15,
754
+ sharpen: 16,
755
+ chromatic: 17,
756
+ mask: 18,
757
+ weather: 19,
758
+ lens_flare: EFFECT_LENS_FLARE
759
+ }, SCALAR_PARAMS = {
760
+ opacity: 3,
761
+ emissiveIntensity: 7,
762
+ metalness: 8,
763
+ roughness: 9,
764
+ alphaTest: 10,
765
+ size: 11,
766
+ clearcoat: 12,
767
+ clearcoatRoughness: 13,
768
+ transmission: 14,
769
+ ior: 15
770
+ }, POST_PARAM_SLOTS = 4, LANE_NAMES = ["x", "y", "z", "w"], POST_UNIFORM_LANES = {
771
+ f32: 1,
772
+ vec2: 2,
773
+ vec3: 3,
774
+ vec4: 4
775
+ }, UNIFORM_WORDS = {
776
+ f32: 1,
777
+ i32: 1,
778
+ vec2: 2,
779
+ vec3: 3,
780
+ vec4: 4,
781
+ mat4: 16,
782
+ texture: 1
783
+ }, SHADOW_WORDS = {
784
+ cascades: 23,
785
+ split: 24,
786
+ maxFar: 25,
787
+ fade: 26,
788
+ bias: 27,
789
+ normalBias: 28,
790
+ radius: 29,
791
+ blurSamples: 30,
792
+ type: 50
793
+ }, SHADOW_INTEGERS = /* @__PURE__ */ new Set(["cascades", "blurSamples"]);
794
+ function shadowWord(key, value) {
795
+ return typeof value == "string" ? SHADOW_TYPES[value] : SHADOW_INTEGERS.has(key) ? value >>> 0 : floatBits(value);
796
+ }
797
+ function linear(channel3) {
798
+ return channel3 <= (0.04045) ? channel3 / (12.92) : ((channel3 + (0.055)) / (1.055)) ** (2.4);
799
+ }
800
+ function scalarOf(data) {
801
+ return data instanceof Float32Array ? 0 : data instanceof Uint32Array ? 1 : data instanceof Uint16Array ? 2 : data instanceof Uint8Array ? 3 : data instanceof Int16Array ? 4 : 5;
802
+ }
803
+ function failure2(code, what) {
804
+ switch (code) {
805
+ case ERROR_CAPACITY_EXCEEDED:
806
+ return new GameError("capacity_exceeded", `${what}: capacity exceeded`);
807
+ case ERROR_DEAD_ENTITY:
808
+ case ERROR_UNKNOWN_RESOURCE:
809
+ return new GameError("unknown_resource", `${what}: unknown resource`);
810
+ case ERROR_UNSUPPORTED:
811
+ return new GameError("unsupported_feature", `${what}: unsupported`);
812
+ default:
813
+ return new GameError("invalid_argument", `${what}: invalid argument`);
814
+ }
815
+ }
816
+ function bindRenderExports(symbols) {
817
+ let bound = {};
818
+ for (let name of RENDER_CORE_EXPORTS) {
819
+ let value = symbols[name];
820
+ if (typeof value != "function") throw new GameError("not_initialized", `engine module is missing ${name}`);
821
+ bound[name] = value;
822
+ }
823
+ for (let name of Object.keys(RENDER_FEATURE_EXPORTS)) {
824
+ let value = symbols[name];
825
+ typeof value == "function" && (bound[name] = value);
826
+ }
827
+ return bound;
828
+ }
829
+ function featureAvailable(exports, caps, name) {
830
+ return exports[name] !== void 0 && (caps & RENDER_FEATURE_EXPORTS[name]) !== 0;
831
+ }
832
+ function graphicsCapabilities(render, caps) {
833
+ return {
834
+ backend: ENGINE_GRAPHICS_NAME,
835
+ dimensions: "3d",
836
+ rendering: (caps & 1) !== 0,
837
+ webgpu: false,
838
+ compute: false,
839
+ shaderLanguages: ["wgsl"],
840
+ instancing: (caps & 4) !== 0,
841
+ skinning: (caps & 8) !== 0,
842
+ morphTargets: (caps & 16) !== 0,
843
+ renderTargets: (caps & 32) !== 0,
844
+ postProcessing: (caps & 64) !== 0,
845
+ models: (caps & 128) !== 0,
846
+ particles: featuresAvailable(render, caps, 1024),
847
+ orderIndependentTransparency: (caps & 2048) !== 0,
848
+ imageBasedLighting: (caps & 4096) !== 0,
849
+ cascadedShadows: (caps & 16384) !== 0,
850
+ renderState: (caps & 32768) !== 0,
851
+ rawRender: featuresAvailable(render, caps, 131072),
852
+ decals: (caps & 65536) !== 0,
853
+ lod: (caps & 262144) !== 0,
854
+ fatLines: (caps & 524288) !== 0,
855
+ text: featuresAvailable(render, caps, 1048576),
856
+ picking: featuresAvailable(render, caps, 2097152),
857
+ pointShadows: (caps & CAP_POINT_SHADOWS) !== 0,
858
+ sky: (caps & 4096) !== 0,
859
+ customProjection: (caps & CAP_CUSTOM_PROJECTION) !== 0,
860
+ gpuTiming: (caps & 8388608) !== 0,
861
+ globalIllumination: (caps & 33554432) !== 0,
862
+ rayTracing: (caps & 67108864) !== 0
863
+ };
864
+ }
865
+ function featuresAvailable(exports, caps, cap) {
866
+ return (caps & cap) === 0 ? false : Object.keys(RENDER_FEATURE_EXPORTS).filter((name) => RENDER_FEATURE_EXPORTS[name] === cap).every((name) => exports[name] !== void 0);
867
+ }
868
+ function concat(a, b) {
869
+ let out = new Uint8Array(a.byteLength + b.byteLength);
870
+ return out.set(a, 0), out.set(b, a.byteLength), out;
871
+ }
872
+ function postShader(effect) {
873
+ let params = [], values = [], accessors = "";
874
+ for (let [name, uniform] of Object.entries(effect.uniforms ?? {})) {
875
+ let lanes = POST_UNIFORM_LANES[uniform.type];
876
+ if (lanes === void 0) throw new GameError("invalid_argument", `post shader uniform ${name} must be f32, vec2, vec3 or vec4`);
877
+ if (params.length + lanes > (4))
878
+ throw new GameError("invalid_argument", `post shader uniforms hold ${(4)} floats`);
879
+ let first = params.length, reads = [];
880
+ for (let lane = 0; lane < lanes; lane++) {
881
+ params.push(lanes === 1 ? name : `${name}.${LANE_NAMES[lane]}`);
882
+ let value = uniform.value;
883
+ values.push(typeof value == "number" ? value : value instanceof Float32Array ? value[lane] ?? 0 : 0), reads.push(`pass_info.params[${first + lane}]`);
884
+ }
885
+ let type = lanes === 1 ? "f32" : `vec${lanes}f`, body = lanes === 1 ? reads[0] : `${type}(${reads.join(", ")})`;
886
+ accessors += `fn ${name}() -> ${type} { return ${body}; }
887
+ `;
888
+ }
889
+ return { source: UTF8.encode(accessors + effect.shader.wgsl.fragment), params, values };
890
+ }
891
+ var EngineGraphics = class {
892
+ constructor(runtime, render = bindRenderExports(runtime.symbols), attacher = null, options = {}) {
893
+ this.attacher = attacher;
894
+ this.nativeSurface = null;
895
+ this.stopResize = null;
896
+ this.raw = null;
897
+ this.refresh = Float64Array.of((-1), (100));
898
+ this.observed = 0;
899
+ this.budgetMicros = 0;
900
+ this.pending = 0;
901
+ this.scratch = 0;
902
+ this.scratchBytes = 0;
903
+ this.attributes = /* @__PURE__ */ new Map();
904
+ this.textures = /* @__PURE__ */ new Map();
905
+ this.targetDepths = /* @__PURE__ */ new Map();
906
+ this.targetFormats = /* @__PURE__ */ new Map();
907
+ this.targetAttachments = /* @__PURE__ */ new Map();
908
+ this.targetReads = [];
909
+ this.uniforms = /* @__PURE__ */ new Map();
910
+ this.chains = /* @__PURE__ */ new Map();
911
+ this.models = /* @__PURE__ */ new Map();
912
+ this.roots = /* @__PURE__ */ new Map();
913
+ this.clipPort = null;
914
+ this.nodeViews = /* @__PURE__ */ new Map();
915
+ this.targetTextures = /* @__PURE__ */ new Map();
916
+ this.matrixScratch = null;
917
+ this.poseReaders = [];
918
+ this.fontFamilies = /* @__PURE__ */ new Map();
919
+ this.textNodes = /* @__PURE__ */ new Map();
920
+ this.defaultFont = null;
921
+ this.textPointer = 0;
922
+ this.textBytes = 0;
923
+ this.pickPointer = 0;
924
+ this.disposed = false;
925
+ this.feedSupport = null;
926
+ this.poseSupport = null;
927
+ this.mediaSupport = null;
928
+ this.mediaLive = new Array(17).fill(false);
929
+ this.mediaViews = new Array(17).fill(null);
930
+ this.mediumWords = new Float32Array(14);
931
+ this.passScratch = new Uint32Array(10);
932
+ this.batchViews = /* @__PURE__ */ new Map();
933
+ this.runtime = runtime, this.abi = render;
934
+ let budget = runtime.symbols.engine_render_set_frame_budget;
935
+ this.frameBudget = typeof budget == "function" ? budget : null;
936
+ let force = runtime.symbols.engine_render_force_tier;
937
+ this.forceTierCall = typeof force == "function" ? force : null;
938
+ let quality = runtime.symbols.engine_render_quality_tier;
939
+ if (this.qualityTierCall = typeof quality == "function" ? quality : null, this.handle = createWithDescriptor(runtime, options, (desc2) => render.engine_render_create(desc2 === 0 ? (0) : desc2)), this.handle === (0)) throw engineSessionFailure(runtime.symbols) ?? new GameError("capacity_exceeded", "engine renderer could not be created");
940
+ let buffer = this.buffer, desc = render.engine_render_desc(this.handle);
941
+ this.desc = new Uint32Array(buffer, desc, 64), this.descFloats = new Float32Array(buffer, desc, 64);
942
+ let registers = render.engine_render_registers(this.handle);
943
+ this.registers = new Uint32Array(buffer, registers, 34), this.registerFloats = new Float32Array(buffer, registers, 34);
944
+ let commands = render.engine_render_commands(this.handle);
945
+ this.commandWords = new Uint32Array(buffer, commands, 1024 * 8), this.commandFloats = new Float32Array(buffer, commands, 1024 * 8), this.sync = this.u32(5, 0, 0), this.params = this.f32(3, 0, 0);
946
+ let caps = render.engine_render_capabilities(this.handle), surfaces = engineVectorSurfaceExports(runtime.symbols);
947
+ this.vectorSurfaces = surfaces === null ? null : new EngineVectorSurfaces(surfaces, {
948
+ handle: this.handle,
949
+ buffer: () => this.buffer,
950
+ stage: (bytes) => this.stage(bytes),
951
+ flush: () => this.flush()
952
+ }), this.capabilities = { ...graphicsCapabilities(render, caps), vectorSurfaces: this.vectorSurfaces?.cap ?? 0 }, this.caps = caps, this.features = new EngineFeatures({
953
+ caps: () => this.caps,
954
+ command: (op, target) => this.command(op, target),
955
+ words: this.commandWords,
956
+ floats: this.commandFloats,
957
+ flush: () => this.flush(),
958
+ buffer: (owner, id, slot) => this.f32(owner, id, slot),
959
+ registers: this.registers
960
+ });
961
+ }
962
+ get gpu() {
963
+ return this.raw === null && (this.raw = createEngineGpu(this.rawHost())), this.raw;
964
+ }
965
+ rawCapabilities() {
966
+ let caps = this.caps, rawCompute = featuresAvailable(this.abi, caps, 8192), rawRender = featuresAvailable(this.abi, caps, 131072);
967
+ return caps & -139265 | (rawCompute ? 8192 : 0) | (rawRender ? 131072 : 0);
968
+ }
969
+ get clips() {
970
+ if (featureAvailable(this.abi, this.caps, "engine_render_animation"))
971
+ return this.clipPort ?? (this.clipPort = new EngineClips(this.clipHost())), this.clipPort;
972
+ }
973
+ clipHost() {
974
+ let views = { words: [], floats: [] }, fresh = (cached) => cached !== void 0 && cached.buffer === this.buffer;
975
+ return {
976
+ command: (op, target) => this.command(op, target),
977
+ commandWords: this.commandWords,
978
+ commandFloats: this.commandFloats,
979
+ animation: (op, target, words) => {
980
+ this.flush();
981
+ let pointer = words.length === 0 ? 0 : this.stage(new Uint8Array(words.buffer, words.byteOffset, words.byteLength)), result = this.check(this.feature("engine_render_animation")(this.handle, op, target, pointer, words.length), "animation");
982
+ return pointer !== 0 && words.set(new Uint32Array(this.buffer, pointer, words.length)), result;
983
+ },
984
+ words: (slot) => {
985
+ let cached = views.words[slot];
986
+ if (fresh(cached)) return cached;
987
+ let view = this.u32(14, 0, slot);
988
+ return views.words[slot] = view, view;
989
+ },
990
+ floats: (slot) => {
991
+ let cached = views.floats[slot];
992
+ if (fresh(cached)) return cached;
993
+ let view = this.f32(14, 0, slot);
994
+ return views.floats[slot] = view, view;
995
+ },
996
+ model: (root) => {
997
+ let model = this.roots.get(root), info = model === void 0 ? void 0 : this.models.get(model);
998
+ if (info === void 0) throw new GameError("invalid_argument", `node ${root} is not a model instance`);
999
+ return info;
1000
+ },
1001
+ refreshModel: (root) => this.refreshModel(root),
1002
+ findNode: (root, name) => this.findNode(root, name),
1003
+ createPoseReader: (nodes) => this.createPoseReader(nodes),
1004
+ readPoses: (reader, out, offset) => this.readPoses(reader, out, offset),
1005
+ destroyPoseReader: (reader) => this.destroyPoseReader(reader),
1006
+ uniformSlot: (material, name) => {
1007
+ let slot = this.uniform(material, name);
1008
+ if (slot === null) throw new GameError("invalid_argument", `material ${material} has no shader uniform ${name}`);
1009
+ return slot;
1010
+ },
1011
+ postParam: (chain, effect, name) => {
1012
+ let param = this.chains.get(chain)?.params[effect]?.indexOf(name) ?? -1;
1013
+ if (param < 0) throw new GameError("invalid_argument", `post chain ${chain} effect ${effect} has no parameter ${name}`);
1014
+ return param;
1015
+ }
1016
+ };
1017
+ }
1018
+ rawHost() {
1019
+ let graphics = this;
1020
+ return {
1021
+ get capabilities() {
1022
+ return graphics.rawCapabilities();
1023
+ },
1024
+ clearDesc: () => this.clearDesc(),
1025
+ command: (op, target) => this.command(op, target),
1026
+ commandWords: this.commandWords,
1027
+ stage: (bytes) => this.stage(bytes),
1028
+ call: (name, ...args) => this.feature(name)(this.handle, ...args),
1029
+ bytes: (owner, id, slot) => {
1030
+ let [pointer, length] = this.view(owner, id, slot);
1031
+ return new Uint8Array(this.buffer, pointer, length);
1032
+ },
1033
+ flush: () => this.flush(),
1034
+ view: (pointer, length) => new Uint8Array(this.buffer, pointer, length)
1035
+ };
1036
+ }
1037
+ get buffer() {
1038
+ return this.runtime.memory.buffer;
1039
+ }
1040
+ feature(name) {
1041
+ let found = this.abi[name];
1042
+ if (found === void 0 || !featureAvailable(this.abi, this.caps, name))
1043
+ throw new GameError("unsupported_feature", `this engine build does not provide ${name}; update the app to use this feature`);
1044
+ return found;
1045
+ }
1046
+ check(code, what) {
1047
+ if (code < 0) throw failure2(code, what);
1048
+ return code;
1049
+ }
1050
+ owns(owner) {
1051
+ let required = BUFFER_OWNER_CAPABILITIES[owner];
1052
+ return required === void 0 || (this.caps & required) !== 0;
1053
+ }
1054
+ view(owner, id, slot) {
1055
+ if (!this.owns(owner)) throw new GameError("unsupported_feature", `this engine build has no buffer owner ${owner}`);
1056
+ let pointer = this.abi.engine_render_buffer(this.handle, owner, id, slot);
1057
+ if (pointer === 0) throw new GameError("unknown_resource", `engine buffer ${owner}:${id}:${slot} does not exist`);
1058
+ return [pointer, this.registers[31]];
1059
+ }
1060
+ f32(owner, id, slot) {
1061
+ let [pointer, length] = this.view(owner, id, slot);
1062
+ return new Float32Array(this.buffer, pointer, length);
1063
+ }
1064
+ u32(owner, id, slot) {
1065
+ let [pointer, length] = this.view(owner, id, slot);
1066
+ return new Uint32Array(this.buffer, pointer, length);
1067
+ }
1068
+ clearDesc() {
1069
+ return this.desc.fill(0), this.desc;
1070
+ }
1071
+ stage(bytes) {
1072
+ if (bytes.byteLength > this.scratchBytes && (this.scratch !== 0 && this.runtime.exports.engine_free(this.scratch, this.scratchBytes, COLUMN_ALIGN), this.scratchBytes = Math.max(bytes.byteLength, COLUMN_ALIGN), this.scratch = this.runtime.exports.engine_alloc(this.scratchBytes, COLUMN_ALIGN), this.scratch === 0))
1073
+ throw new GameError("capacity_exceeded", "engine memory cannot stage asset bytes");
1074
+ return new Uint8Array(this.buffer, this.scratch, bytes.byteLength).set(bytes), this.scratch;
1075
+ }
1076
+ command(op, target) {
1077
+ this.pending === 1024 && this.flush();
1078
+ let o = this.pending * 8;
1079
+ return this.commandWords[o + 0] = op, this.commandWords[o + 1] = target, this.pending++, o + 2;
1080
+ }
1081
+ flush() {
1082
+ if (this.pending === 0) return;
1083
+ let count = this.pending;
1084
+ this.pending = 0, this.check(this.abi.engine_render_flush(this.handle, count), "graphics command");
1085
+ }
1086
+ get renderHandle() {
1087
+ return this.handle;
1088
+ }
1089
+ passTimings(out) {
1090
+ if (!this.owns(13)) return false;
1091
+ let pointer = this.abi.engine_render_buffer(this.handle, 13, 0, 0);
1092
+ return pointer === 0 ? false : (out.set(new Uint32Array(this.buffer, pointer, Math.min(10, out.length))), true);
1093
+ }
1094
+ get native() {
1095
+ return this.nativeSurface;
1096
+ }
1097
+ async attach(surface) {
1098
+ if (surface !== null || this.attacher === null || this.nativeSurface !== null) return;
1099
+ let native = await this.attacher(this.handle, {});
1100
+ this.nativeSurface = native, this.caps = this.abi.engine_render_capabilities(this.handle), this.capabilities = { ...graphicsCapabilities(this.abi, this.caps), vectorSurfaces: this.vectorSurfaces?.cap ?? 0 }, this.resize(native.width, native.height, native.pixel_ratio), this.stopResize = native.on_resize((width, height, pixelRatio) => this.resize(width, height, pixelRatio));
1101
+ }
1102
+ resize(width, height, pixelRatio) {
1103
+ let a = this.command(30, 0);
1104
+ this.commandWords[a] = Math.max(1, Math.round(width * pixelRatio)), this.commandWords[a + 1] = Math.max(1, Math.round(height * pixelRatio)), this.commandFloats[a + 2] = pixelRatio, this.features.resize(width, height);
1105
+ }
1106
+ createGeometry(desc) {
1107
+ let names = Object.keys(desc.attributes);
1108
+ if (names.length > 8) throw new GameError("invalid_argument", `geometry has more than ${8} attributes`);
1109
+ let position = desc.attributes.position;
1110
+ if (!position) throw new GameError("invalid_argument", "geometry needs a position attribute");
1111
+ let vertices = position.data.length / position.itemSize, morphs = desc.morphTargets ?? [], d = this.clearDesc();
1112
+ d[0] = names.length, d[1] = vertices, d[2] = desc.index?.length ?? 0, d[3] = desc.index instanceof Uint32Array ? 1 : 0, d[4] = morphs.length, d[5] = morphs.length > 0 && morphs.every((m) => m.normal !== void 0) ? 1 : 0, d[6] = desc.morphRelative === false ? 0 : 1, names.forEach((name, i) => {
1113
+ let attribute = desc.attributes[name], at = 8 + i * 4;
1114
+ d[at + 0] = SEMANTICS[name] ?? 8 + i, d[at + 1] = scalarOf(attribute.data), d[at + 2] = attribute.itemSize, d[at + 3] = (attribute.normalized ? 1 : 0) | (attribute.dynamic ? 2 : 0);
1115
+ });
1116
+ let id = this.check(this.abi.engine_render_create_geometry(this.handle), "create geometry"), mirrors = /* @__PURE__ */ new Map();
1117
+ if (names.forEach((name, i) => {
1118
+ let source = desc.attributes[name].data, [pointer] = this.view(0, id, i), Constructor = source.constructor, target = new Constructor(this.buffer, pointer, source.length);
1119
+ target.set(source), mirrors.set(name, { source, target, slot: i });
1120
+ }), this.attributes.set(id, mirrors), desc.index) {
1121
+ let [pointer] = this.view(0, id, 65535);
1122
+ (desc.index instanceof Uint32Array ? new Uint32Array(this.buffer, pointer, desc.index.length) : new Uint16Array(this.buffer, pointer, desc.index.length)).set(desc.index);
1123
+ }
1124
+ if (morphs.length > 0) {
1125
+ let positions = this.f32(0, id, 65534), stride = vertices * 3;
1126
+ if (morphs.forEach((m, t) => positions.set(m.position, t * stride)), d[5] === 1) {
1127
+ let normals = this.f32(0, id, 65533);
1128
+ morphs.forEach((m, t) => {
1129
+ m.normal && normals.set(m.normal, t * stride);
1130
+ });
1131
+ }
1132
+ }
1133
+ return this.check(this.abi.engine_render_commit_geometry(this.handle, id), "commit geometry"), id;
1134
+ }
1135
+ geometryAttribute(geometry, name) {
1136
+ let mirror = this.attributes.get(geometry)?.get(name);
1137
+ if (!mirror) throw new GameError("unknown_resource", `geometry ${geometry} has no attribute ${name}`);
1138
+ return mirror.source;
1139
+ }
1140
+ markGeometryDirty(geometry, name, start, count) {
1141
+ let mirrors = this.attributes.get(geometry), mirror = mirrors?.get(name);
1142
+ if (!mirrors || !mirror) throw new GameError("unknown_resource", `geometry ${geometry} has no attribute ${name}`);
1143
+ let end = count < 0 ? mirror.source.length : Math.min(mirror.source.length, start + count);
1144
+ for (let i = start; i < end; i++) mirror.target[i] = mirror.source[i];
1145
+ this.commandWords[this.command(16, geometry)] = mirror.slot;
1146
+ }
1147
+ setDrawRange(geometry, start, count) {
1148
+ let a = this.command(17, geometry);
1149
+ this.commandWords[a] = start, this.commandWords[a + 1] = count;
1150
+ }
1151
+ destroyGeometry(geometry) {
1152
+ this.command(18, geometry), this.attributes.delete(geometry);
1153
+ }
1154
+ createTexture(desc) {
1155
+ if (desc.source.kind === "video") {
1156
+ let d2 = this.clearDesc();
1157
+ return d2[0] = desc.source.width, d2[1] = desc.source.height, d2[8] = TEXTURE_KIND_EXTERNAL, this.check(this.abi.engine_render_create_texture(this.handle), "create video texture");
1158
+ }
1159
+ if (desc.source.kind !== "pixels")
1160
+ throw new GameError("unsupported_feature", "the Cimplify renderer takes pixel or encoded textures; decode images with loadTexture");
1161
+ let { width, height, data } = desc.source, format = desc.source.format ?? (data instanceof Float32Array ? "rgba32f" : data instanceof Uint16Array ? "rgba16f" : "rgba8"), [formatWord, texelBytes] = TEXEL_FORMATS[format], layered = desc.kind === "2d-array" || desc.kind === "3d", depth = desc.kind === "cube" ? 6 : layered ? desc.source.depth ?? 1 : 1;
1162
+ if (desc.kind === "cube" && (width !== height || data.byteLength !== width * height * 6 * texelBytes))
1163
+ throw new GameError("invalid_argument", "cube textures take six square faces packed +X, -X, +Y, -Y, +Z, -Z");
1164
+ if (data.byteLength !== width * height * depth * texelBytes)
1165
+ throw new GameError("invalid_argument", `a ${format} texture of ${width}x${height}x${depth} takes ${width * height * depth * texelBytes} bytes`);
1166
+ let d = this.clearDesc();
1167
+ d[0] = width, d[1] = height, d[2] = formatWord, d[8] = desc.kind === "cube" ? 1 : desc.kind === "equirect" ? 2 : desc.kind === "2d-array" ? TEXTURE_KIND_2D_ARRAY : desc.kind === "3d" ? TEXTURE_KIND_3D : 0, d[9] = depth, d[3] = desc.colorSpace === "linear" ? 1 : 0, d[4] = desc.wrap === "clamp" ? 1 : desc.wrap === "mirror" ? 2 : 0, d[5] = desc.filter === "nearest" ? 1 : 0, d[6] = desc.mipmaps === false ? 0 : 1, d[7] = desc.flipY ? 1 : 0;
1168
+ let id = this.check(this.abi.engine_render_create_texture(this.handle), "create texture");
1169
+ return this.textures.set(id, { data, width, height, depth, texelBytes }), this.copyTexture(id, data), this.requestEncode(id, desc.encode), id;
1170
+ }
1171
+ requestEncode(id, encode) {
1172
+ if (encode === void 0 || encode === "none" || !featureAvailable(this.abi, this.caps, "engine_render_encode_texture")) return;
1173
+ let encodeTexture = this.abi.engine_render_encode_texture;
1174
+ if (!encodeTexture) return;
1175
+ let mode = encode === "astc" ? TEXTURE_ENCODE_ASTC_4X4 : encode === "bc7" ? TEXTURE_ENCODE_BC7 : TEXTURE_ENCODE_AUTO;
1176
+ encodeTexture(this.handle, id, mode);
1177
+ }
1178
+ copyTexture(id, data) {
1179
+ let [pointer] = this.view(1, id, 0);
1180
+ new Uint8Array(this.buffer, pointer, data.byteLength).set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
1181
+ }
1182
+ copyRegion(id, mirror, region) {
1183
+ let [pointer] = this.view(1, id, 0), source = new Uint8Array(mirror.data.buffer, mirror.data.byteOffset, mirror.data.byteLength), target = new Uint8Array(this.buffer, pointer, mirror.data.byteLength), row = mirror.width * mirror.texelBytes, span = region.width * mirror.texelBytes, z0 = region.z ?? 0;
1184
+ for (let z = z0; z < z0 + (region.depth ?? 1); z++)
1185
+ for (let y = region.y; y < region.y + region.height; y++) {
1186
+ let at = (z * mirror.height + y) * row + region.x * mirror.texelBytes;
1187
+ target.set(source.subarray(at, at + span), at);
1188
+ }
1189
+ }
1190
+ async loadTexture(source) {
1191
+ let bytes = await this.bytes(source, "texture"), pointer = this.stage(bytes);
1192
+ return this.check(this.abi.engine_render_decode_texture(this.handle, pointer, bytes.byteLength, (1)), "decode texture");
1193
+ }
1194
+ async upgradeTexture(texture, source) {
1195
+ let bytes = await this.bytes(source, "texture"), reload = this.reloadExport("engine_render_reload_texture");
1196
+ if (reload !== null) {
1197
+ this.flush();
1198
+ let code = reload(this.handle, texture, this.stage(bytes), bytes.byteLength, (1));
1199
+ if (code >= 0) return { texture, inPlace: true };
1200
+ if (code !== ERROR_INVALID_ARGUMENT) throw failure2(code, "reload texture");
1201
+ }
1202
+ let pointer = this.stage(bytes);
1203
+ return { texture: this.check(this.abi.engine_render_decode_texture(this.handle, pointer, bytes.byteLength, (1)), "decode texture"), inPlace: false };
1204
+ }
1205
+ reloadExport(name) {
1206
+ return featureAvailable(this.abi, this.caps, name) ? this.abi[name] ?? null : null;
1207
+ }
1208
+ markTextureDirty(texture, region) {
1209
+ let mirror = this.textures.get(texture);
1210
+ if (region === void 0) {
1211
+ mirror && this.copyTexture(texture, mirror.data), this.command(19, texture);
1212
+ return;
1213
+ }
1214
+ mirror && this.copyRegion(texture, mirror, region);
1215
+ let a = this.command(OP_MARK_TEXTURE_REGION, texture), w = this.commandWords;
1216
+ w[a] = region.x, w[a + 1] = region.y, w[a + 2] = region.z ?? 0, w[a + 3] = region.width, w[a + 4] = region.height, w[a + 5] = region.depth ?? 1;
1217
+ }
1218
+ destroyTexture(texture) {
1219
+ this.command(20, texture), this.textures.delete(texture);
1220
+ }
1221
+ createMaterial(desc) {
1222
+ refuseUndrawnPhysicalFields(desc);
1223
+ let d = this.clearDesc(), f = this.descFloats;
1224
+ d[0] = MATERIAL_KINDS[desc.kind];
1225
+ let color = "color" in desc && desc.color !== void 0 ? desc.color : 16777215;
1226
+ this.writeHex(f, 1, color), f[4] = desc.opacity ?? 1, f[11] = desc.alphaTest ?? 0, f[25] = (1.5), f[6] = (1), f[21] = (1);
1227
+ let flags = 0;
1228
+ desc.transparent && (flags |= 1), desc.depthTest !== false && (flags |= 2), (desc.depthWrite ?? !desc.transparent) && (flags |= 4), desc.vertexColors && (flags |= 8), desc.wireframe && (flags |= 16), d[13] = desc.side === "back" ? 1 : desc.side === "double" ? 2 : 0, d[14] = desc.blending === "additive" ? 1 : desc.blending === "multiply" ? 2 : desc.blending === "none" ? 3 : desc.blending === "custom" ? 4 : 0;
1229
+ let write = (word, value) => {
1230
+ d[word] = value;
1231
+ };
1232
+ writeMaterialExtension(desc, write);
1233
+ let extras = extraTextures(desc);
1234
+ for (let i = 0; i < 8; i++) d[51 + i] = extras[i] ?? 0;
1235
+ writeMaterialFeatures(desc, d, f), flags |= materialFeatureFlags(desc), flags |= writeMaterialTint(desc, d);
1236
+ let fragment = null, uniforms = null;
1237
+ switch (desc.kind) {
1238
+ case "standard":
1239
+ case "physical": {
1240
+ flags |= 64, desc.flatShading && (flags |= 32), f[5] = desc.metalness ?? 0, f[6] = desc.roughness ?? (1), this.writeHex(f, 7, desc.emissive ?? 0), f[10] = desc.emissiveIntensity ?? 1, [desc.map, desc.normalMap, desc.roughnessMap, desc.metalnessMap, desc.emissiveMap, desc.aoMap].forEach((texture, i) => {
1241
+ d[15 + i] = texture ?? 0;
1242
+ }), desc.kind === "physical" && (f[22] = desc.clearcoat ?? 0, f[23] = desc.clearcoatRoughness ?? 0, f[24] = desc.transmission ?? 0, f[25] = desc.ior ?? (1.5), f[26] = desc.sheen ?? 0);
1243
+ break;
1244
+ }
1245
+ case "skin":
1246
+ case "eye":
1247
+ case "hair": {
1248
+ flags |= 64, desc.flatShading && (flags |= 32), f[6] = desc.roughness ?? (1), this.writeHex(f, 7, desc.emissive ?? 0), f[10] = desc.emissiveIntensity ?? 1, [desc.map, desc.normalMap, desc.roughnessMap, void 0, desc.emissiveMap, desc.aoMap].forEach((texture, i) => {
1249
+ d[15 + i] = texture ?? 0;
1250
+ }), writeCharacterWords(desc, write);
1251
+ break;
1252
+ }
1253
+ case "unlit":
1254
+ case "sprite":
1255
+ d[15] = desc.map ?? 0, desc.kind === "sprite" && desc.sizeAttenuation !== false && (flags |= 128);
1256
+ break;
1257
+ case "points":
1258
+ d[15] = desc.map ?? 0, f[21] = desc.size ?? (1), desc.sizeAttenuation !== false && (flags |= 128);
1259
+ break;
1260
+ case "lines":
1261
+ break;
1262
+ case "shader": {
1263
+ desc.lights && (flags |= 64), fragment = UTF8.encode(desc.shader.wgsl.fragment), uniforms = /* @__PURE__ */ new Map();
1264
+ let offset = 0;
1265
+ for (let [name, uniform] of Object.entries(desc.uniforms ?? {})) {
1266
+ let words = UNIFORM_WORDS[uniform.type];
1267
+ uniforms.set(name, { offset, words }), offset += words;
1268
+ }
1269
+ d[27] = offset;
1270
+ break;
1271
+ }
1272
+ }
1273
+ d[12] = flags;
1274
+ let transforms = desc.textureTransforms ? new Float32Array(MATERIAL_SLOTS.length * 8) : null, transformed = transforms !== null && writeTextureTransforms(desc, transforms, write), vertex = desc.kind === "shader" && desc.shader.wgsl.vertex ? UTF8.encode(desc.shader.wgsl.vertex) : null, staged = fragment && vertex ? concat(fragment, vertex) : fragment, pointer = staged ? this.stage(staged) : 0, fragmentBytes = fragment?.byteLength ?? 0, id = this.check(
1275
+ this.abi.engine_render_create_material(
1276
+ this.handle,
1277
+ pointer,
1278
+ fragmentBytes,
1279
+ vertex ? pointer + fragmentBytes : 0,
1280
+ vertex?.byteLength ?? 0
1281
+ ),
1282
+ "create material"
1283
+ ), clipped = (desc.clippingPlanes?.length ?? 0) > 0 && writePlanes(desc, this.f32(7, id, 0));
1284
+ if (transforms && transformed && this.f32(8, id, 0).set(transforms), (clipped || transformed) && this.command(13, id), uniforms && desc.kind === "shader") {
1285
+ this.uniforms.set(id, uniforms);
1286
+ for (let [name, uniform] of Object.entries(desc.uniforms ?? {}))
1287
+ typeof uniform.value == "number" ? this.setMaterialScalar(id, name, uniform.value) : uniform.value instanceof Float32Array && this.setMaterialVector(id, name, uniform.value);
1288
+ }
1289
+ return this.features.material(id, desc), id;
1290
+ }
1291
+ writeHex(target, at, hex) {
1292
+ target[at] = linear((hex >> 16 & (255)) / (255)), target[at + 1] = linear((hex >> 8 & (255)) / (255)), target[at + 2] = linear((hex & (255)) / (255));
1293
+ }
1294
+ setMaterialColor(material, r, g, b) {
1295
+ let at = material * 20 + 0;
1296
+ this.params[at] = r, this.params[at + 1] = g, this.params[at + 2] = b, this.command(13, material);
1297
+ }
1298
+ setMaterialOpacity(material, opacity) {
1299
+ this.params[material * 20 + 3] = opacity, this.command(13, material);
1300
+ }
1301
+ setMaterialTexture(material, slot, texture) {
1302
+ let a = this.command(14, material);
1303
+ this.commandWords[a] = materialSlotIndex(slot), this.commandWords[a + 1] = texture ?? 0;
1304
+ }
1305
+ uniform(material, name) {
1306
+ let slots = this.uniforms.get(material);
1307
+ if (!slots) return null;
1308
+ let slot = slots.get(name);
1309
+ if (!slot) throw new GameError("invalid_argument", `material ${material} has no uniform ${name}`);
1310
+ return slot;
1311
+ }
1312
+ setMaterialScalar(material, uniform, value) {
1313
+ let slot = this.uniform(material, uniform);
1314
+ if (slot)
1315
+ this.f32(2, material, 0)[slot.offset] = value;
1316
+ else {
1317
+ let param = SCALAR_PARAMS[uniform];
1318
+ if (param === void 0) throw new GameError("invalid_argument", `material ${material} has no scalar ${uniform}`);
1319
+ this.params[material * 20 + param] = value;
1320
+ }
1321
+ this.command(13, material);
1322
+ }
1323
+ setMaterialVector(material, uniform, value) {
1324
+ let slot = this.uniform(material, uniform);
1325
+ if (!slot) throw new GameError("invalid_argument", "vector uniforms belong to shader materials");
1326
+ if (value.length > slot.words) throw new GameError("invalid_argument", `uniform ${uniform} holds ${slot.words} values`);
1327
+ this.f32(2, material, 0).set(value, slot.offset), this.command(13, material);
1328
+ }
1329
+ setMaterialUniformTexture(material, uniform, texture) {
1330
+ let slot = this.uniform(material, uniform);
1331
+ if (!slot) throw new GameError("invalid_argument", "texture uniforms belong to shader materials");
1332
+ this.u32(2, material, 0)[slot.offset] = texture, this.command(13, material);
1333
+ }
1334
+ setMaterialState(material, state) {
1335
+ writeMaterialState(state, (word, value) => {
1336
+ let a = this.command(OP_SET_MATERIAL_WORD, material);
1337
+ this.commandWords[a] = word, this.commandWords[a + 1] = value;
1338
+ }), (state.clippingPlanes?.length ?? 0) > 0 && writePlanes(state, this.f32(7, material, 0)) && this.command(13, material);
1339
+ }
1340
+ destroyMaterial(material) {
1341
+ this.command(15, material), this.uniforms.delete(material), this.features.forgetMaterial(material);
1342
+ }
1343
+ createEmitter(desc) {
1344
+ if (!this.capabilities.particles) throw new GameError("unsupported_feature", "this engine build has no particles");
1345
+ this.flush(), writeEmitterDesc(this.clearDesc(), this.descFloats, desc);
1346
+ let id = this.check(this.feature("engine_render_create_emitter")(this.handle), "create emitter");
1347
+ return desc.sizeCurve && sampleCurve(desc.sizeCurve, this.f32(9, id, 0)), desc.colorCurve && sampleCurve(desc.colorCurve, this.f32(9, id, 1)), (desc.sizeCurve || desc.colorCurve) && this.command(OP_MARK_EMITTER, id), id;
1348
+ }
1349
+ emit(emitter, count) {
1350
+ this.commandWords[this.command(OP_EMIT, emitter)] = count;
1351
+ }
1352
+ setEmitterRate(emitter, rate) {
1353
+ this.commandFloats[this.command(OP_SET_EMITTER_RATE, emitter)] = rate;
1354
+ }
1355
+ clearEmitter(emitter) {
1356
+ this.command(OP_CLEAR_EMITTER, emitter);
1357
+ }
1358
+ destroyEmitter(emitter) {
1359
+ this.command(OP_DESTROY_EMITTER, emitter);
1360
+ }
1361
+ setRenderOrder(node, order) {
1362
+ this.commandWords[this.command(OP_SET_RENDER_ORDER, node)] = order | 0;
1363
+ }
1364
+ setShadow(light, shadow) {
1365
+ let room = 6, a = 0, used = room;
1366
+ for (let key of Object.keys(shadow)) {
1367
+ let value = shadow[key];
1368
+ value !== void 0 && (used === room && (a = this.command(OP_SET_SHADOW, light), used = 0), this.commandWords[a + used] = SHADOW_WORDS[key], this.commandWords[a + used + 1] = shadowWord(key, value), used += 2);
1369
+ }
1370
+ used < room && (this.commandWords[a + used] = 0);
1371
+ }
1372
+ writeShadow(d, shadow) {
1373
+ if (shadow)
1374
+ for (let key of Object.keys(shadow)) {
1375
+ let value = shadow[key];
1376
+ value !== void 0 && (d[SHADOW_WORDS[key]] = shadowWord(key, value));
1377
+ }
1378
+ }
1379
+ createNode(desc) {
1380
+ let d = this.clearDesc(), f = this.descFloats;
1381
+ switch (d[22] = desc.renderOrder ?? 0, desc.kind) {
1382
+ case "mesh":
1383
+ d[0] = 0, d[1] = desc.geometry, d[2] = Array.isArray(desc.material) ? desc.material[0] ?? 0 : desc.material, d[3] = this.shadowFlags(desc.castShadow, desc.receiveShadow, desc.giExclude);
1384
+ break;
1385
+ case "instanced":
1386
+ d[0] = 1, d[1] = desc.geometry, d[2] = desc.material, d[4] = desc.capacity, d[3] = this.shadowFlags(desc.castShadow, desc.receiveShadow, desc.giExclude) | (desc.colors ? 4 : 0) | (desc.batchSlots ? 64 : 0), d[18] = desc.batchSlots ?? 0;
1387
+ break;
1388
+ case "skinned": {
1389
+ d[0] = 2, d[1] = desc.geometry, d[2] = desc.material, d[3] = this.shadowFlags(desc.castShadow, desc.receiveShadow, desc.giExclude);
1390
+ let { parents, bindPose, inverseBindMatrices } = desc.skeleton;
1391
+ if (bindPose.length !== parents.length * (10)) throw new GameError("invalid_argument", "bind pose needs ten floats per bone");
1392
+ let parentBytes = Math.ceil(parents.byteLength / COLUMN_ALIGN) * COLUMN_ALIGN, poseBytes = Math.ceil(bindPose.byteLength / COLUMN_ALIGN) * COLUMN_ALIGN, total = new Uint8Array(parentBytes + poseBytes + (inverseBindMatrices?.byteLength ?? 0));
1393
+ total.set(new Uint8Array(parents.buffer, parents.byteOffset, parents.byteLength), 0), total.set(new Uint8Array(bindPose.buffer, bindPose.byteOffset, bindPose.byteLength), parentBytes), inverseBindMatrices && total.set(new Uint8Array(inverseBindMatrices.buffer, inverseBindMatrices.byteOffset, inverseBindMatrices.byteLength), parentBytes + poseBytes);
1394
+ let base = this.stage(total);
1395
+ d[18] = parents.length, d[19] = base, d[20] = base + parentBytes, d[21] = inverseBindMatrices ? base + parentBytes + poseBytes : 0;
1396
+ break;
1397
+ }
1398
+ case "points":
1399
+ d[0] = 3, d[1] = desc.geometry, d[2] = desc.material;
1400
+ break;
1401
+ case "lines":
1402
+ d[0] = 4, d[1] = desc.geometry, d[2] = desc.material, d[3] = desc.segments ? 8 : 0;
1403
+ break;
1404
+ case "sprite":
1405
+ d[0] = 5, d[2] = desc.material;
1406
+ break;
1407
+ case "camera":
1408
+ d[0] = 6, d[14] = desc.projection === "orthographic" ? 1 : 0, f[15] = desc.projection === "orthographic" ? desc.height : desc.projection === "perspective" ? desc.fov ?? 60 : 60, f[16] = desc.near ?? 0.1, f[17] = desc.far ?? 1e3;
1409
+ break;
1410
+ case "decal":
1411
+ break;
1412
+ case "light": {
1413
+ d[0] = 7, d[5] = LIGHT_KINDS[desc.light], d[6] = desc.color ?? 16777215, d[12] = desc.groundColor ?? (4473924), d[3] = desc.castShadow ? 1 : 0, d[13] = desc.shadowMapSize ?? 0, f[7] = desc.intensity ?? 1, f[8] = desc.distance ?? 0, f[9] = desc.decay ?? (2), f[10] = desc.angle ?? DEFAULT_SPOT_ANGLE, f[11] = desc.penumbra ?? 0, this.writeShadow(d, desc.shadow);
1414
+ break;
1415
+ }
1416
+ case "particles":
1417
+ d[0] = 9, d[31] = desc.emitter;
1418
+ break;
1419
+ case "group":
1420
+ d[0] = 8;
1421
+ break;
1422
+ case "shape2d":
1423
+ throw new GameError("unsupported_feature", "shape2d nodes need the 2D renderer");
1424
+ case "text2d":
1425
+ case "text3d": {
1426
+ let mode = desc.kind === "text2d" ? 2 : desc.billboard ? 1 : 0, font = desc.kind === "text3d" ? desc.font : this.resolveFont(desc.font, desc.fontFamily);
1427
+ this.writeText(d, f, font, desc, mode);
1428
+ let node2 = this.check(this.abi.engine_render_create_node(this.handle), `create ${desc.kind} node`);
1429
+ return this.textNodes.set(node2, { font, mode }), desc.text && this.setNodeText(node2, desc.text), node2;
1430
+ }
1431
+ }
1432
+ writeNodeFeatures(desc, d, f, desc.kind === "sprite" ? this.features.spriteRotation(desc.material) : 0);
1433
+ let node = this.check(this.abi.engine_render_create_node(this.handle), `create ${desc.kind} node`);
1434
+ return this.features.node(node, desc), node;
1435
+ }
1436
+ setLod(node, near, far, hysteresis) {
1437
+ this.features.setLod(node, near, far, hysteresis);
1438
+ }
1439
+ setSprite(node, rotation, centerX, centerY) {
1440
+ this.features.setSprite(node, rotation, centerX, centerY);
1441
+ }
1442
+ setProbeCoefficients(light, sh) {
1443
+ this.features.setProbeCoefficients(light, sh);
1444
+ }
1445
+ setProjectionMatrix(camera, matrix, near, far) {
1446
+ this.features.setProjectionMatrix(camera, matrix, near, far);
1447
+ }
1448
+ setViewOffset(camera, offset) {
1449
+ this.features.setViewOffset(camera, offset);
1450
+ }
1451
+ batchBuffers(node) {
1452
+ let cached = this.batchViews.get(node);
1453
+ if (cached) return cached;
1454
+ this.flush();
1455
+ let slots = this.abi.engine_render_buffer(this.handle, 4, node, 5);
1456
+ if (slots === 0) return null;
1457
+ let slotCount = this.registers[31], ranges = this.abi.engine_render_buffer(this.handle, 4, node, 6);
1458
+ if (ranges === 0) return null;
1459
+ let views = {
1460
+ slots: new Uint32Array(this.buffer, slots, slotCount),
1461
+ ranges: new Uint32Array(this.buffer, ranges, this.registers[31])
1462
+ };
1463
+ return this.batchViews.set(node, views), views;
1464
+ }
1465
+ markBatch(node) {
1466
+ this.command(62, node);
1467
+ }
1468
+ gpuStats(out) {
1469
+ this.flush(), this.check(this.abi.engine_render_stats(this.handle), "stats"), this.features.readGpuStats(out);
1470
+ let timed = this.passTimings(this.passScratch);
1471
+ for (let i = 0; i < out.passNs.length; i++) out.passNs[i] = timed ? this.passScratch[i] ?? 0 : 0;
1472
+ return timed || out.gpuLastNs > 0;
1473
+ }
1474
+ resolveFont(font, family) {
1475
+ let found = font ?? (family !== void 0 ? this.fontFamilies.get(family) : void 0) ?? this.defaultFont;
1476
+ if (found == null) throw new GameError("asset_load_failed", "load a font with loadFont before creating text");
1477
+ return found;
1478
+ }
1479
+ writeText(d, f, font, style, mode) {
1480
+ d[0] = 11, d[4] = style.capacity ?? (128), d[6] = style.color ?? (16777215), d[37] = font, d[46] = mode, d[42] = TEXT_ALIGNS[style.align ?? "start"], d[43] = TEXT_DIRECTIONS[style.direction ?? "auto"], d[48] = style.outlineColor ?? 0, f[38] = style.size ?? (mode === 2 ? (16) : (1)), f[39] = style.lineHeight ?? 0, f[40] = style.letterSpacing ?? 0, f[41] = style.maxWidth ?? 0, f[44] = style.anchor?.[0] ?? 0, f[45] = style.anchor?.[1] ?? 0, f[47] = style.outlineWidth ?? 0, f[49] = style.opacity ?? 1;
1481
+ }
1482
+ async loadFont(source, family) {
1483
+ let [atlas, table] = await Promise.all([this.bytes(source.atlas, "font atlas"), this.bytes(source.table, "font table")]), texture = this.check(
1484
+ this.abi.engine_render_decode_texture(this.handle, this.stage(atlas), atlas.byteLength, (0)),
1485
+ "decode font atlas"
1486
+ ), material = this.createMaterial({ kind: "unlit", transparent: true, depthWrite: false });
1487
+ this.setMaterialTexture(material, "map", texture);
1488
+ let font = this.check(
1489
+ this.feature("engine_render_load_font")(this.handle, this.stage(table), table.byteLength, material),
1490
+ "load font"
1491
+ );
1492
+ return source.face !== void 0 && await this.loadFontFace(font, source.face), family !== void 0 && this.fontFamilies.set(family, font), this.defaultFont ?? (this.defaultFont = font), registerFontTable(font, new FontTable(table.slice().buffer)), font;
1493
+ }
1494
+ async loadFontFace(font, source) {
1495
+ let attach = this.abi.engine_render_font_face;
1496
+ if (attach === void 0) return;
1497
+ let face = await this.bytes(source, "font face");
1498
+ this.check(attach(this.handle, font, this.stage(face), face.byteLength), "load font face");
1499
+ }
1500
+ setTextStyle(node, style) {
1501
+ let text = this.textNodes.get(node);
1502
+ if (text === void 0) throw new GameError("unknown_resource", "setTextStyle needs a text node");
1503
+ this.writeText(this.clearDesc(), this.descFloats, text.font, style, text.mode), this.check(this.feature("engine_render_set_text_style")(this.handle, node), "set text style");
1504
+ }
1505
+ textBounds(node, out) {
1506
+ let pointer = this.pickScratch();
1507
+ this.check(this.feature("engine_render_text_bounds")(this.handle, node, pointer), "text bounds"), out.set(new Float32Array(this.buffer, pointer, 4));
1508
+ }
1509
+ batchHandle() {
1510
+ return this.handle;
1511
+ }
1512
+ forceQualityTier(tier) {
1513
+ return this.forceTierCall === null ? false : (this.check(this.forceTierCall(this.handle, tier === null ? (-1) : tier), "force quality tier"), true);
1514
+ }
1515
+ qualityTier() {
1516
+ return this.qualityTierCall === null ? (0) : this.check(this.qualityTierCall(this.handle), "quality tier");
1517
+ }
1518
+ governorPressure() {
1519
+ this.check(this.abi.engine_render_stats(this.handle), "stats");
1520
+ let word = this.registers[STAT_THERMAL_TIER];
1521
+ return Math.max(word & (255), word >>> (28) & (15));
1522
+ }
1523
+ raycast(origin, direction, far, layers, out) {
1524
+ let pointer = this.pickScratch(), ray = new Float32Array(this.buffer, pointer, 7);
1525
+ ray[0] = origin[0], ray[1] = origin[1], ray[2] = origin[2], ray[3] = direction[0], ray[4] = direction[1], ray[5] = direction[2], ray[6] = far;
1526
+ let result = pointer + 7 * WORD_BYTES;
1527
+ if (this.check(this.feature("engine_render_raycast")(this.handle, pointer, layers >>> 0, result), "raycast") !== (1)) return false;
1528
+ let words = new Uint32Array(this.buffer, result, 11), floats = new Float32Array(this.buffer, result, 11);
1529
+ return out.node = words[0], out.instance = words[1], out.triangle = words[2], out.distance = floats[3], out.point.set(floats.subarray(4, 7)), out.barycentric.set(floats.subarray(7, 9)), out.uv.set(floats.subarray(9, 11)), true;
1530
+ }
1531
+ pickScratch() {
1532
+ if (this.pickPointer === 0 && (this.pickPointer = this.runtime.exports.engine_alloc(18 * WORD_BYTES, COLUMN_ALIGN), this.pickPointer === 0))
1533
+ throw new GameError("capacity_exceeded", "engine memory cannot hold the pick scratch");
1534
+ return this.pickPointer;
1535
+ }
1536
+ shadowFlags(cast, receive, giExclude) {
1537
+ return (cast ? 1 : 0) | (receive ? 2 : 0) | (giExclude ? 32 : 0);
1538
+ }
1539
+ destroyNode(node) {
1540
+ this.command(1, node), this.roots.delete(node), this.nodeViews.delete(node), this.textNodes.delete(node), this.batchViews.delete(node), this.features.forgetNode(node);
1541
+ }
1542
+ setNodeVisible(node, visible) {
1543
+ this.commandWords[this.command(2, node)] = visible ? 1 : 0;
1544
+ }
1545
+ setNodeLayers(node, mask) {
1546
+ this.commandWords[this.command(3, node)] = mask >>> 0;
1547
+ }
1548
+ setNodeMaterial(node, material) {
1549
+ this.commandWords[this.command(4, node)] = material;
1550
+ }
1551
+ setNodeText(node, text) {
1552
+ let needed = Math.max(text.length * (3), COLUMN_ALIGN);
1553
+ if (needed > this.textBytes && (this.textPointer !== 0 && this.runtime.exports.engine_free(this.textPointer, this.textBytes, COLUMN_ALIGN), this.textBytes = needed, this.textPointer = this.runtime.exports.engine_alloc(needed, COLUMN_ALIGN), this.textPointer === 0))
1554
+ throw new GameError("capacity_exceeded", "engine memory cannot stage text");
1555
+ let written = UTF8.encodeInto(text, new Uint8Array(this.buffer, this.textPointer, this.textBytes)).written;
1556
+ this.check(this.feature("engine_render_set_text")(this.handle, node, this.textPointer, written), "set text");
1557
+ }
1558
+ writeNodeMatrices(nodes, matrices, rows, count) {
1559
+ if (matrices.buffer !== this.buffer) throw new GameError("invalid_argument", "the Cimplify renderer reads render matrices from engine memory");
1560
+ let sync = this.sync;
1561
+ for (let i = 0; i < count; i++)
1562
+ sync[2 * i] = nodes[i], sync[2 * i + 1] = rows[i];
1563
+ this.flush(), this.check(this.abi.engine_render_sync(this.handle, count, matrices.byteOffset, matrices.length / 16), "sync matrices");
1564
+ }
1565
+ readNodeMatrix(node, out, offset) {
1566
+ this.flush();
1567
+ let scratch = this.nodeMatrixScratch();
1568
+ this.check(this.abi.engine_render_node_matrix(this.handle, node, scratch.byteOffset), "read node matrix");
1569
+ for (let i = 0; i < 16; i++) out[offset + i] = scratch[i];
1570
+ }
1571
+ createPoseReader(nodes) {
1572
+ let count = nodes.length, bytes = count * WORD_BYTES * (1 + NODE_POSE_FLOATS), pointer = count === 0 ? 0 : this.runtime.exports.engine_alloc(bytes, COLUMN_ALIGN);
1573
+ if (count > 0 && pointer === 0) throw new GameError("capacity_exceeded", "engine memory cannot hold a bone set");
1574
+ count > 0 && new Uint32Array(this.buffer, pointer, count).set(nodes);
1575
+ let reader = { pointer, bytes, count, out: pointer + count * WORD_BYTES, view: null }, free = this.poseReaders.indexOf(null, 1);
1576
+ return free > 0 ? (this.poseReaders[free] = reader, free) : (this.poseReaders.length === 0 && this.poseReaders.push(null), this.poseReaders.push(reader), this.poseReaders.length - 1);
1577
+ }
1578
+ poseReader(reader) {
1579
+ let found = this.poseReaders[reader];
1580
+ if (!found) throw new GameError("unknown_resource", `bone set ${reader} does not exist`);
1581
+ return found;
1582
+ }
1583
+ readPoses(id, out, offset) {
1584
+ let reader = this.poseReader(id);
1585
+ if (reader.count === 0) return;
1586
+ this.flush(), this.check(this.feature("engine_render_node_poses")(this.handle, reader.pointer, reader.count, reader.out), "read bone poses");
1587
+ let view = reader.view;
1588
+ (view === null || view.buffer !== this.buffer) && (view = new Float32Array(this.buffer, reader.out, reader.count * NODE_POSE_FLOATS), reader.view = view);
1589
+ for (let i = 0; i < view.length; i++) out[offset + i] = view[i];
1590
+ }
1591
+ destroyPoseReader(id) {
1592
+ let reader = this.poseReader(id);
1593
+ reader.pointer !== 0 && this.runtime.exports.engine_free(reader.pointer, reader.bytes, COLUMN_ALIGN), this.poseReaders[id] = null;
1594
+ }
1595
+ nodeMatrixScratch() {
1596
+ if (!this.matrixScratch) {
1597
+ let pointer = this.runtime.exports.engine_alloc(16 * WORD_BYTES, COLUMN_ALIGN);
1598
+ if (pointer === 0) throw new GameError("capacity_exceeded", "engine memory cannot hold a matrix");
1599
+ this.matrixScratch = new Float32Array(this.buffer, pointer, 16);
1600
+ }
1601
+ return this.matrixScratch;
1602
+ }
1603
+ nodeBuffer(node, slot) {
1604
+ let key = node * (4) + slot, cached = this.nodeViews.get(key);
1605
+ if (cached) return cached;
1606
+ let view = this.f32(4, node, slot);
1607
+ return this.nodeViews.set(key, view), view;
1608
+ }
1609
+ instanceMatrices(node) {
1610
+ return this.nodeBuffer(node, 0);
1611
+ }
1612
+ instanceColors(node) {
1613
+ try {
1614
+ return this.nodeBuffer(node, 1);
1615
+ } catch {
1616
+ return null;
1617
+ }
1618
+ }
1619
+ setInstanceCount(node, count) {
1620
+ this.commandWords[this.command(5, node)] = count;
1621
+ }
1622
+ markInstancesDirty(node) {
1623
+ this.command(6, node);
1624
+ }
1625
+ setInstanceFeed(node, table, columns, hostReads, pose) {
1626
+ if (this.feedSupport === null && (this.feedSupport = engineAdvertises(this.runtime, RENDER_KERNEL_INSTANCES_FEATURE)), !this.feedSupport || columns.length !== 4 || pose !== void 0 && (pose.length !== 2 || !this.posesSupported())) return false;
1627
+ let at = this.command(64, node);
1628
+ this.commandWords[at] = table;
1629
+ for (let k = 0; k < 4; k++) this.commandWords[at + 1 + k] = columns[k];
1630
+ if (this.commandWords[at + 1 + 4] = hostReads ? 1 : 0, pose !== void 0) {
1631
+ let words = this.command(66, node);
1632
+ for (let k = 0; k < 2; k++) this.commandWords[words + k] = pose[k];
1633
+ }
1634
+ return true;
1635
+ }
1636
+ setInstancePalette(node, model, skin, firstClip, clips, frames) {
1637
+ if (!this.posesSupported()) return false;
1638
+ let at = this.command(67, node);
1639
+ return this.commandWords[at] = model, this.commandWords[at + 1] = skin, this.commandWords[at + 2] = firstClip, this.commandWords[at + 3] = clips, this.commandWords[at + 4] = frames, true;
1640
+ }
1641
+ posesSupported() {
1642
+ return this.poseSupport === null && (this.poseSupport = engineAdvertises(this.runtime, RENDER_FEED_POSE_FEATURE)), this.poseSupport;
1643
+ }
1644
+ requireMedia() {
1645
+ if (this.mediaSupport === null && (this.mediaSupport = engineAdvertises(this.runtime, MEDIA_VOLUME_FEATURE)), !this.mediaSupport) throw new GameError("unsupported_feature", `this engine build has no media volumes (feature ${MEDIA_VOLUME_FEATURE}); update the app to use them`);
1646
+ }
1647
+ liveMedium(medium) {
1648
+ let id = medium;
1649
+ if (!(Number.isInteger(id) && id >= 1 && id <= 16 && this.mediaLive[id])) throw new GameError("unknown_resource", `media volume ${id} does not exist`);
1650
+ return id;
1651
+ }
1652
+ sendMedium(op, id, desc) {
1653
+ writeMediumDesc(this.mediumWords, desc), this.flush(), this.f32(OWNER_STAGING, 0, 0).set(this.mediumWords), this.command(op, id), this.flush(), this.mediaViews[id] = null;
1654
+ }
1655
+ createMedium(desc) {
1656
+ this.requireMedia();
1657
+ let id = this.mediaLive.indexOf(false, 1);
1658
+ if (id < 0) throw new GameError("capacity_exceeded", `a scene holds at most ${16} media volumes`);
1659
+ return this.sendMedium(68, id, desc), this.mediaLive[id] = true, id;
1660
+ }
1661
+ setMedium(medium, desc) {
1662
+ this.sendMedium(69, this.liveMedium(medium), desc);
1663
+ }
1664
+ mediumTexels(medium) {
1665
+ let id = this.liveMedium(medium), held = this.mediaViews[id];
1666
+ if (held !== null && held.buffer === this.buffer) return held;
1667
+ let view = this.u32(16, id, 0);
1668
+ return this.mediaViews[id] = view, view;
1669
+ }
1670
+ markMedium(medium) {
1671
+ this.command(71, this.liveMedium(medium));
1672
+ }
1673
+ destroyMedium(medium) {
1674
+ let id = this.liveMedium(medium);
1675
+ this.command(70, id), this.flush(), this.mediaLive[id] = false, this.mediaViews[id] = null;
1676
+ }
1677
+ clearInstanceFeed(node) {
1678
+ this.feedSupport === true && this.command(65, node);
1679
+ }
1680
+ morphWeights(node) {
1681
+ return this.nodeBuffer(node, 2);
1682
+ }
1683
+ markMorphWeightsDirty(node) {
1684
+ this.command(7, node);
1685
+ }
1686
+ skeletonPose(node) {
1687
+ return this.nodeBuffer(node, 3);
1688
+ }
1689
+ markSkeletonDirty(node) {
1690
+ this.command(8, node);
1691
+ }
1692
+ setCameraPerspective(node, fovDegrees, near, far) {
1693
+ let a = this.command(9, node);
1694
+ this.commandFloats[a] = fovDegrees, this.commandFloats[a + 1] = near, this.commandFloats[a + 2] = far, this.features.perspective(node, fovDegrees, near, far);
1695
+ }
1696
+ setCameraPerspectiveFrom(node, values, offset) {
1697
+ let a = this.command(9, node), f = this.commandFloats;
1698
+ f[a] = values[offset], f[a + 1] = values[offset + 1], f[a + 2] = values[offset + 2], this.features.perspectiveFrom(node, values, offset);
1699
+ }
1700
+ setCameraOrthographic(node, height, near, far) {
1701
+ let a = this.command(10, node);
1702
+ this.commandFloats[a] = height, this.commandFloats[a + 1] = near, this.commandFloats[a + 2] = far, this.features.orthographic(node, height, near, far);
1703
+ }
1704
+ setActiveCamera(node) {
1705
+ this.command(11, node);
1706
+ }
1707
+ setLight(node, color, intensity) {
1708
+ let a = this.command(12, node);
1709
+ this.commandWords[a] = color, this.commandFloats[a + 1] = intensity;
1710
+ }
1711
+ setEnvironment(desc) {
1712
+ this.flush();
1713
+ let d = this.clearDesc(), f = this.descFloats, background = desc.background;
1714
+ d[2] = 0, background && "color" in background ? (d[0] = 1, d[1] = background.color) : background && "texture" in background ? (d[0] = 2, d[2] = background.texture) : background ? d[0] = 3 : d[0] = 1, d[3] = desc.environment ?? 0, f[15] = desc.environmentIntensity ?? 1, f[16] = desc.environmentRotation ?? 0, f[17] = desc.backgroundBlurriness ?? 0, f[18] = desc.backgroundIntensity ?? 1;
1715
+ let fog = desc.fog;
1716
+ fog && (d[4] = 1, d[5] = fog.color, d[11] = FOG_MODES.indexOf(fog.mode ?? "linear"), fog.mode === "exp2" || fog.mode === "height" ? f[12] = fog.density : (f[6] = fog.near, f[7] = fog.far), fog.mode === "height" && (f[13] = fog.height, f[14] = fog.falloff)), d[8] = Math.max(0, TONE_MAPPINGS.indexOf(desc.toneMapping ?? "aces")), d[ENV_TONE_CURVE] = desc.toneCurve ?? 0, f[9] = desc.exposure ?? 1, d[10] = desc.shadows === false ? 0 : 1;
1717
+ let gi = desc.gi;
1718
+ if (gi && (d[ENV_GI] = Math.max(0, GI_MODES.indexOf(gi.mode ?? "field")), f[ENV_GI_INTENSITY] = gi.intensity ?? 1, f[ENV_GI_SPACING] = gi.spacing ?? 1, f[ENV_GI_SUN_ANGLE] = gi.sunAngle ?? 0.53), writeSky(desc, d, f), this.check(this.abi.engine_render_set_environment(this.handle), "set environment"), desc.volumetrics)
1719
+ for (let [at, chunk] of volumetricChunks(volumetricWords(desc.volumetrics))) {
1720
+ let a = this.command(OP_SET_VOLUMETRICS, 0);
1721
+ this.commandWords[a] = at, chunk.forEach((value, k) => {
1722
+ this.commandFloats[a + 1 + k] = value;
1723
+ });
1724
+ }
1725
+ }
1726
+ createRenderTarget(desc) {
1727
+ let d = this.clearDesc();
1728
+ d[0] = desc.width, d[1] = desc.height, d[2] = desc.format === "rgba16f" ? 1 : desc.format === "rgba32f" ? 2 : 0, d[3] = desc.depth === false ? 0 : 1, d[4] = desc.samples ?? 1, d[TARGET_KIND] = desc.kind === "cube" ? TARGET_KIND_CUBE : desc.kind === "2d-array" ? TARGET_KIND_ARRAY : TARGET_KIND_2D, d[TARGET_LAYERS] = desc.layers ?? 1, d[TARGET_SAMPLED_DEPTH] = desc.sampleDepth ? 1 : 0, d[TARGET_COLORS] = desc.colors ?? 1;
1729
+ let id = this.check(this.abi.engine_render_create_target(this.handle), "create render target");
1730
+ this.targetTextures.set(id, this.registers[30]);
1731
+ let depth = d[TARGET_TEXTURES + TARGET_MAX_COLORS - 1];
1732
+ desc.sampleDepth && depth !== 0 && this.targetDepths.set(id, depth), this.targetFormats.set(id, desc.format ?? "rgba8");
1733
+ let extras = [];
1734
+ for (let k = 1; k < (desc.colors ?? 1); k++) extras.push(d[TARGET_TEXTURES + k - 1]);
1735
+ return this.targetAttachments.set(id, extras), id;
1736
+ }
1737
+ renderTargetAttachment(target, attachment) {
1738
+ if (attachment === 0) return this.renderTargetTexture(target);
1739
+ let texture = this.targetAttachments.get(target)?.[attachment - 1];
1740
+ if (texture === void 0 || texture === 0)
1741
+ throw new GameError("invalid_argument", `render target ${target} has no colour attachment ${attachment}`);
1742
+ return texture;
1743
+ }
1744
+ renderTargetTexture(target) {
1745
+ let texture = this.targetTextures.get(target);
1746
+ if (texture === void 0) throw new GameError("unknown_resource", `render target ${target} does not exist`);
1747
+ return texture;
1748
+ }
1749
+ renderTargetDepthTexture(target) {
1750
+ let texture = this.targetDepths.get(target);
1751
+ if (texture === void 0) throw new GameError("unsupported_feature", `render target ${target} was not created with sampleDepth`);
1752
+ return texture;
1753
+ }
1754
+ resizeRenderTarget(target, width, height) {
1755
+ let a = this.command(26, target);
1756
+ this.commandWords[a] = width, this.commandWords[a + 1] = height;
1757
+ }
1758
+ destroyRenderTarget(target) {
1759
+ this.command(27, target), this.targetTextures.delete(target), this.targetDepths.delete(target), this.targetFormats.delete(target), this.targetAttachments.delete(target);
1760
+ }
1761
+ createPostChain(desc) {
1762
+ if (desc.effects.length > MAX_CHAIN_EFFECTS) throw new GameError("invalid_argument", `post chains hold ${MAX_CHAIN_EFFECTS} effects`);
1763
+ let shaders = desc.effects.map((effect) => effect.kind === "shader" ? postShader(effect) : null), params = desc.effects.map((effect, e) => {
1764
+ let shader = shaders[e];
1765
+ if (shader) return shader.values;
1766
+ let record = effect;
1767
+ return EFFECT_PARAMETERS[effect.kind].map((name) => Number(record[name] ?? 0));
1768
+ }), inline = Math.min(desc.effects.length, 12), d = this.clearDesc(), f = this.descFloats;
1769
+ d[0] = inline;
1770
+ for (let e = 0; e < inline; e++) {
1771
+ let at = 1 + e * 5;
1772
+ d[at + 0] = EFFECT_KINDS[desc.effects[e].kind], params[e].forEach((value, p) => {
1773
+ f[at + 1 + p] = value;
1774
+ });
1775
+ }
1776
+ let setShader = shaders.some((shader) => shader !== null) ? this.feature("engine_render_set_chain_shader") : null, id = this.check(this.abi.engine_render_create_chain(this.handle), "create post chain");
1777
+ for (let e = inline; e < desc.effects.length; e++) {
1778
+ let a = this.command(OP_SET_EFFECT, id);
1779
+ this.commandWords[a] = e, this.commandWords[a + 1] = EFFECT_KINDS[desc.effects[e].kind], params[e].forEach((value, p) => {
1780
+ this.commandFloats[a + 2 + p] = value;
1781
+ });
1782
+ }
1783
+ return inline < desc.effects.length && this.flush(), shaders.forEach((shader, e) => {
1784
+ if (!shader || !setShader) return;
1785
+ let pointer = this.stage(shader.source);
1786
+ this.check(setShader(this.handle, id, e, pointer, shader.source.byteLength), "set post shader");
1787
+ }), desc.effects.forEach((effect, e) => {
1788
+ if (!(effect.kind !== "shader" || effect.textures === void 0)) {
1789
+ if (effect.textures.length > POST_EFFECT_TEXTURES)
1790
+ throw new GameError("invalid_argument", `post shaders take ${POST_EFFECT_TEXTURES} textures`);
1791
+ effect.textures.forEach((texture, slot) => {
1792
+ let a = this.command(OP_SET_EFFECT_TEXTURE, id);
1793
+ this.commandWords[a] = e, this.commandWords[a + 1] = slot, this.commandWords[a + 2] = texture;
1794
+ });
1795
+ }
1796
+ }), this.chains.set(id, {
1797
+ kinds: desc.effects.map((e) => e.kind),
1798
+ params: desc.effects.map((effect, e) => shaders[e]?.params ?? EFFECT_PARAMETERS[effect.kind])
1799
+ }), id;
1800
+ }
1801
+ setPostScalar(chain, effect, uniform, value) {
1802
+ let mirror = this.chains.get(chain), kind = mirror?.kinds[effect];
1803
+ if (mirror === void 0 || kind === void 0) throw new GameError("unknown_resource", `post chain ${chain} has no effect ${effect}`);
1804
+ let param = mirror.params[effect].indexOf(uniform);
1805
+ if (param < 0) throw new GameError("invalid_argument", `${kind} has no parameter ${uniform}`);
1806
+ let a = this.command(24, chain);
1807
+ this.commandWords[a] = effect, this.commandWords[a + 1] = param, this.commandFloats[a + 2] = value;
1808
+ }
1809
+ setPostChain(chain) {
1810
+ this.command(23, chain ?? 0);
1811
+ }
1812
+ setWeather(state) {
1813
+ let w = weatherWords(state), a = this.command(OP_SET_WEATHER, w.snow ? 1 : 0), f = this.commandFloats;
1814
+ f[a] = w.cloudCover, f[a + 1] = w.haze, f[a + 2] = w.precipitation, f[a + 3] = w.wetness, f[a + 4] = w.windX, f[a + 5] = w.windZ;
1815
+ }
1816
+ setTimeOfDay(hours, latitude, dayOfYear) {
1817
+ let a = this.command(OP_SET_TIME_OF_DAY, 0), f = this.commandFloats;
1818
+ f[a] = hours, f[a + 1] = latitude ?? UNSET, f[a + 2] = dayOfYear ?? UNSET;
1819
+ }
1820
+ destroyPostChain(chain) {
1821
+ this.command(25, chain), this.chains.delete(chain);
1822
+ }
1823
+ createRenderPass(desc) {
1824
+ this.flush();
1825
+ let d = this.clearDesc(), f = this.descFloats;
1826
+ return d[0] = desc.camera, d[1] = desc.target ?? 0, d[2] = (desc.layers ?? 4294967295) >>> 0, d[3] = desc.clearColor ?? 0, f[4] = desc.clearAlpha ?? 1, d[5] = (desc.order ?? 0) >>> 0, d[PASS_SLICE] = desc.slice ?? 0, d[PASS_FLAGS] = (desc.cubeFace ? PASS_FLAG_CUBE_FACE : 0) | (desc.reflect ? PASS_FLAG_REFLECT : 0) | (desc.once ? PASS_FLAG_ONCE : 0), desc.reflect?.forEach((v, i) => {
1827
+ f[PASS_PLANE + i] = v;
1828
+ }), desc.viewport && (d[6] = 1, desc.viewport.forEach((v, i) => {
1829
+ f[7 + i] = v;
1830
+ })), this.check(this.abi.engine_render_create_pass(this.handle), "create render pass");
1831
+ }
1832
+ setRenderPassEnabled(pass, enabled) {
1833
+ this.commandWords[this.command(21, pass)] = enabled ? 1 : 0;
1834
+ }
1835
+ destroyRenderPass(pass) {
1836
+ this.command(22, pass);
1837
+ }
1838
+ async bytes(source, what) {
1839
+ if ("bytes" in source) return new Uint8Array(source.bytes);
1840
+ if ("text" in source) return UTF8.encode(source.text);
1841
+ let response = await fetch(source.url);
1842
+ if (!response.ok) throw new GameError("asset_load_failed", `${what} ${source.url} failed with ${response.status}`);
1843
+ return new Uint8Array(await response.arrayBuffer());
1844
+ }
1845
+ installShaders(bytes) {
1846
+ let pointer = this.stage(bytes);
1847
+ return this.check(
1848
+ this.abi.engine_render_install_shaders(this.handle, pointer, bytes.byteLength),
1849
+ "install shaders"
1850
+ );
1851
+ }
1852
+ async loadModel(source) {
1853
+ let bytes = await this.bytes(source, "model"), pointer = this.stage(bytes), id = this.check(this.abi.engine_render_load_model(this.handle, pointer, bytes.byteLength), "load model");
1854
+ return this.readModel(id, null);
1855
+ }
1856
+ async upgradeModel(model, source) {
1857
+ let previous = this.models.get(model);
1858
+ if (previous === void 0) throw new GameError("unknown_resource", `model ${model} is not loaded`);
1859
+ let bytes = await this.bytes(source, "model"), reload = this.reloadExport("engine_render_reload_model");
1860
+ if (reload !== null) {
1861
+ this.flush();
1862
+ let code = reload(this.handle, model, this.stage(bytes), bytes.byteLength);
1863
+ if (code >= 0) return { model: this.readModel(model, previous), inPlace: true };
1864
+ if (code !== ERROR_INVALID_ARGUMENT) throw failure2(code, "reload model");
1865
+ }
1866
+ let id = this.check(this.abi.engine_render_load_model(this.handle, this.stage(bytes), bytes.byteLength), "load model");
1867
+ return { model: this.readModel(id, null), inPlace: false };
1868
+ }
1869
+ readModel(id, previous) {
1870
+ let nodes = this.registers[12], clips = nodes + this.registers[13], [names, length] = this.view(6, id, 0), all = NAMES.decode(new Uint8Array(this.buffer, names, length).slice()).split(String.fromCharCode((0))), clipNames = all.slice(nodes, clips);
1871
+ if (previous !== null) {
1872
+ let info2 = { ...previous, nodeNames: all.slice(0, nodes), clipNames };
1873
+ return this.models.set(id, info2), info2;
1874
+ }
1875
+ let named = this.owns(12), materialNames = named ? all.slice(clips, all.length - 1) : [], materials = named ? this.modelMaterials(id, materialNames.length) : [], info = { id, nodeNames: all.slice(0, nodes), clipNames, materialNames, materials };
1876
+ return this.models.set(id, info), info;
1877
+ }
1878
+ refreshModel(root) {
1879
+ let model = this.roots.get(root), previous = model === void 0 ? void 0 : this.models.get(model);
1880
+ if (model === void 0 || previous === void 0) throw new GameError("invalid_argument", `node ${root} is not a model instance`);
1881
+ return this.readModel(model, previous);
1882
+ }
1883
+ async loadClips(root, source, options) {
1884
+ let rate = bakeRate(options), load = this.feature("engine_render_load_clips");
1885
+ if (!this.roots.has(root)) throw new GameError("invalid_argument", `node ${root} is not a model instance`);
1886
+ let bytes = await this.bytes(source, "clips");
1887
+ this.flush();
1888
+ let pointer = this.stage(bytes), first = this.check(load(this.handle, root, pointer, bytes.byteLength, rate), "load clips");
1889
+ return this.refreshModel(root).clipNames.slice(first);
1890
+ }
1891
+ setTint(node, tint) {
1892
+ let at = this.command(63, node);
1893
+ writeTintWords(tint, this.commandWords, at);
1894
+ }
1895
+ modelMaterials(model, count) {
1896
+ let [ids] = this.view(12, model, 0);
1897
+ return Array.from(new Uint32Array(this.buffer, ids, count), (material) => material);
1898
+ }
1899
+ instantiateModel(model) {
1900
+ if (!this.models.get(model)) throw new GameError("unknown_resource", `model ${model} is not loaded`);
1901
+ let root = this.check(this.abi.engine_render_instantiate(this.handle, model), "instantiate model");
1902
+ return this.roots.set(root, model), root;
1903
+ }
1904
+ findNode(root, name) {
1905
+ let bytes = UTF8.encode(name), node = this.check(this.abi.engine_render_find_node(this.handle, root, this.stage(bytes), bytes.byteLength), "find node");
1906
+ return node === (0) ? null : node;
1907
+ }
1908
+ playClip(root, clip, loop, fadeSeconds, speed) {
1909
+ let index = this.clipIndex(root, clip);
1910
+ if (index < 0) throw new GameError("unknown_resource", `node ${root} has no clip ${clip}`);
1911
+ return this.playClipIndex(root, index, loop, fadeSeconds, speed);
1912
+ }
1913
+ clipIndex(root, clip) {
1914
+ let model = this.roots.get(root);
1915
+ return model === void 0 ? -1 : this.models.get(model)?.clipNames.indexOf(clip) ?? -1;
1916
+ }
1917
+ playClipIndex(root, clip, loop, fadeSeconds, speed) {
1918
+ return this.flush(), this.check(this.abi.engine_render_play_clip(this.handle, root, clip, loop ? 1 : 0, fadeSeconds, speed), "play clip");
1919
+ }
1920
+ setClipWeight(action, weight) {
1921
+ this.commandFloats[this.command(28, action)] = weight;
1922
+ }
1923
+ stopClip(action, fadeSeconds) {
1924
+ this.commandFloats[this.command(29, action)] = fadeSeconds;
1925
+ }
1926
+ advanceAnimations(time) {
1927
+ this.flush(), this.registerFloats[16] = time.values[FRAME_SECONDS_SLOT], this.check(this.abi.engine_render_animate(this.handle), "advance animations");
1928
+ }
1929
+ render(time) {
1930
+ this.frameBudget !== null && this.followRefresh(time.values), this.flush();
1931
+ let native = this.nativeSurface;
1932
+ native !== null && native.before_render !== void 0 && native.before_render(), this.vectorSurfaces?.frame(time.values[FRAME_SECONDS_SLOT]), this.check(this.abi.engine_render_frame(this.handle), "render frame"), this.targetReads.length > 0 && this.pollTargetReads();
1933
+ }
1934
+ followRefresh(clock) {
1935
+ let refresh = this.refresh, interval = clock[FRAME_NOW_MS_SLOT] - refresh[(0)];
1936
+ if (refresh[(0)] = clock[FRAME_NOW_MS_SLOT], interval >= (1) && interval < (100) && (interval < refresh[(1)] && (refresh[(1)] = interval), this.observed++), this.observed < (64) || this.frameBudget === null) return;
1937
+ let micros = Math.round(refresh[(1)] * (1e3));
1938
+ refresh[(1)] = (100), this.observed = 0, !(Math.abs(micros - this.budgetMicros) * (50) <= this.budgetMicros) && (this.budgetMicros = micros, this.frameBudget(this.handle, micros));
1939
+ }
1940
+ pushVideoFrame(texture, frame, width, height) {
1941
+ let gpu = this.runtime.gpu;
1942
+ if (gpu === null || this.abi.engine_render_texture_object === void 0) return false;
1943
+ this.flush();
1944
+ let object = this.abi.engine_render_texture_object(this.handle, texture);
1945
+ return object <= 0 ? false : gpu.copyExternalImage(object, frame, width, height);
1946
+ }
1947
+ readRenderTarget(target, rect, slice = 0) {
1948
+ let read = this.feature("engine_render_read_target");
1949
+ if (this.abi.engine_render_raw_poll === void 0)
1950
+ throw new GameError("unsupported_feature", "this engine build cannot poll readbacks");
1951
+ this.flush();
1952
+ let [x, y, width, height] = rect, request = this.check(read(this.handle, target, slice, x, y, width, height), "read render target"), bytes = width * height * (this.targetFormats.get(target) === "rgba8" ? 4 : 8);
1953
+ return new Promise((resolve, reject) => {
1954
+ this.targetReads.push({ request, bytes, resolve, reject });
1955
+ });
1956
+ }
1957
+ pollTargetReads() {
1958
+ let poll = this.abi.engine_render_raw_poll;
1959
+ if (poll === void 0) return;
1960
+ let waiting = [];
1961
+ for (let read of this.targetReads) {
1962
+ let pointer = poll(this.handle, read.request);
1963
+ if (pointer === 0) {
1964
+ waiting.push(read);
1965
+ continue;
1966
+ }
1967
+ if (pointer < 0) {
1968
+ read.reject(failure2(pointer, "read render target"));
1969
+ continue;
1970
+ }
1971
+ read.resolve(new Uint8Array(this.buffer, pointer, read.bytes).slice());
1972
+ }
1973
+ this.targetReads = waiting;
1974
+ }
1975
+ stats(out) {
1976
+ this.flush(), this.check(this.abi.engine_render_stats(this.handle), "stats");
1977
+ let r = this.registers;
1978
+ out.nodes = r[0], out.geometries = r[1], out.materials = r[2], out.textures = r[3], out.renderTargets = r[4], out.postChains = r[5], out.renderPasses = r[6], out.frames = r[7];
1979
+ }
1980
+ dispose() {
1981
+ this.disposed || (this.disposed = true, this.stopResize?.(), this.nativeSurface?.release(), this.nativeSurface = null, this.abi.engine_render_destroy(this.handle), this.scratch !== 0 && this.runtime.exports.engine_free(this.scratch, this.scratchBytes, COLUMN_ALIGN), this.matrixScratch && this.runtime.exports.engine_free(this.matrixScratch.byteOffset, 16 * WORD_BYTES, COLUMN_ALIGN), this.textPointer !== 0 && this.runtime.exports.engine_free(this.textPointer, this.textBytes, COLUMN_ALIGN), this.pickPointer !== 0 && this.runtime.exports.engine_free(this.pickPointer, 18 * WORD_BYTES, COLUMN_ALIGN), this.textPointer = 0, this.pickPointer = 0, this.scratch = 0, this.matrixScratch = null);
1982
+ }
1983
+ };
1984
+
1985
+ // src/game/backends/engine/ai.ts
1986
+ var NO_WORLD = 0;
1987
+ function engineAiExports(symbols) {
1988
+ for (let name of ENGINE_AI_EXPORT_NAMES) if (typeof symbols[name] != "function") return null;
1989
+ return symbols;
1990
+ }
1991
+ var EngineAiPort = class {
1992
+ constructor(runtime, exports, physicsWorld) {
1993
+ this.name = "cimplify-engine-ai";
1994
+ this.runtime = runtime, this.exports = exports, this.physicsWorld = physicsWorld;
1995
+ let stepWorld = runtime.symbols[ENGINE_AI_WORLD_STEP];
1996
+ this.stepWorld = typeof stepWorld == "function" ? stepWorld : null;
1997
+ }
1998
+ buffer() {
1999
+ return this.runtime.memory.buffer;
2000
+ }
2001
+ alloc(bytes, align) {
2002
+ return this.runtime.exports.engine_alloc(bytes, align);
2003
+ }
2004
+ free(pointer, bytes, align) {
2005
+ this.runtime.exports.engine_free(pointer, bytes, align);
2006
+ }
2007
+ step(ai) {
2008
+ let world = this.physicsWorld();
2009
+ return this.stepWorld !== null && world !== (0) ? this.stepWorld(ai, world) : this.exports.engine_ai_step(ai);
2010
+ }
2011
+ };
2012
+ function engineAi(runtime, physicsWorld = () => (0)) {
2013
+ let exports = engineAiExports(runtime.symbols);
2014
+ return exports ? new EngineAiPort(runtime, exports, physicsWorld) : null;
2015
+ }
2016
+
2017
+ // src/game/backends/engine/nav.ts
2018
+ var ENGINE_NAV_EXPORT_NAMES = [
2019
+ "engine_nav_create",
2020
+ "engine_nav_destroy",
2021
+ "engine_nav_registers",
2022
+ "engine_nav_costs",
2023
+ "engine_nav_include",
2024
+ "engine_nav_add_tile",
2025
+ "engine_nav_remove_tile",
2026
+ "engine_nav_nearest",
2027
+ "engine_nav_find_path",
2028
+ "engine_nav_agents",
2029
+ "engine_nav_agent_add",
2030
+ "engine_nav_agent_remove",
2031
+ "engine_nav_agent_target",
2032
+ "engine_nav_agent_stop",
2033
+ "engine_nav_step",
2034
+ "engine_nav_roads",
2035
+ "engine_nav_vehicles",
2036
+ "engine_nav_vehicle_add",
2037
+ "engine_nav_vehicle_remove",
2038
+ "engine_nav_vehicle_external",
2039
+ "engine_nav_signal",
2040
+ "engine_nav_add_link",
2041
+ "engine_nav_remove_link"
2042
+ ], NO_POINTER = 0, EMPTY = new Float32Array(0), ERROR_MESSAGES = ["", "capacity exceeded", "dead entity", "unknown resource", "invalid argument", "unsupported"], DRIVER_WORDS = 6;
2043
+ function engineNavExports(symbols) {
2044
+ for (let name of ENGINE_NAV_EXPORT_NAMES) if (typeof symbols[name] != "function") return null;
2045
+ return symbols;
2046
+ }
2047
+ var EngineNav = class {
2048
+ constructor(runtime, exports) {
2049
+ this.name = "cimplify-engine-nav";
2050
+ this.handle = (0);
2051
+ this.words = new Uint32Array(0);
2052
+ this.floats = new Float32Array(0);
2053
+ this.costs = new Float32Array(0);
2054
+ this.agentView = EMPTY;
2055
+ this.vehicleView = EMPTY;
2056
+ this.maxAgents = 0;
2057
+ this.maxVehicles = 0;
2058
+ this.scratch = (0);
2059
+ this.scratchBytes = 0;
2060
+ this.complete = false;
2061
+ this.runtime = runtime, this.exports = exports;
2062
+ }
2063
+ get pathComplete() {
2064
+ return this.complete;
2065
+ }
2066
+ batchHandle() {
2067
+ return this.handle;
2068
+ }
2069
+ check(code, what) {
2070
+ if (code < 0) {
2071
+ let kind = -code === 1 ? "capacity_exceeded" : -code === 3 ? "unknown_resource" : -code === 5 ? "unsupported_feature" : "invalid_argument";
2072
+ throw new GameError(kind, `${what}: ${ERROR_MESSAGES[-code] ?? "failed"}`);
2073
+ }
2074
+ return code;
2075
+ }
2076
+ require() {
2077
+ if (this.handle === (0)) throw new GameError("not_initialized", "navigation is not initialised");
2078
+ return this.handle;
2079
+ }
2080
+ alloc(bytes) {
2081
+ if (bytes <= this.scratchBytes) return this.scratch;
2082
+ if (this.scratch !== (0) && this.runtime.exports.engine_free(this.scratch, this.scratchBytes, WORD_BYTES), this.scratch = this.runtime.exports.engine_alloc(bytes, WORD_BYTES), this.scratch === (0)) throw new GameError("capacity_exceeded", "engine memory is full");
2083
+ return this.scratchBytes = bytes, this.scratch;
2084
+ }
2085
+ init(desc) {
2086
+ let pointer = this.alloc(16 * WORD_BYTES), buffer = this.runtime.memory.buffer, words = new Uint32Array(buffer, pointer, 16), floats = new Float32Array(buffer, pointer, 16);
2087
+ words.fill(0);
2088
+ let origin = desc.origin ?? [0, 0], extents = desc.extents ?? DEFAULT_EXTENTS;
2089
+ floats[0] = origin[0], floats[1] = origin[1], floats[2] = desc.tileWorld, words[3] = desc.maxTiles ?? 256, words[4] = desc.queryNodes ?? 2048, this.maxAgents = desc.maxAgents ?? 512, words[5] = this.maxAgents, floats[6] = desc.neighbourDistance ?? 4, floats[7] = desc.timeHorizon ?? 2, words[8] = desc.pathBudget ?? 16, words[9] = desc.maxPathPolys ?? 256;
2090
+ for (let k = 0; k < 3; k++) floats[10 + k] = extents[k];
2091
+ if (this.handle = this.exports.engine_nav_create(pointer), this.handle === (0)) throw new GameError("invalid_argument", "navigation could not be created");
2092
+ let registers = this.exports.engine_nav_registers(this.handle);
2093
+ this.words = new Uint32Array(buffer, registers, 32), this.floats = new Float32Array(buffer, registers, 32);
2094
+ for (let k = 0; k < 3; k++) this.floats[6 + k] = extents[k];
2095
+ this.costs = new Float32Array(buffer, this.exports.engine_nav_costs(this.handle), 64), this.agentView = new Float32Array(buffer, this.exports.engine_nav_agents(this.handle), this.maxAgents * 8);
2096
+ }
2097
+ addTile(bytes) {
2098
+ let handle = this.require(), pointer = this.alloc(bytes.byteLength);
2099
+ return new Uint8Array(this.runtime.memory.buffer, pointer, bytes.byteLength).set(bytes), this.check(this.exports.engine_nav_add_tile(handle, pointer, bytes.byteLength), "add tile");
2100
+ }
2101
+ removeTile(x, z) {
2102
+ this.check(this.exports.engine_nav_remove_tile(this.require(), x, z), "remove tile");
2103
+ }
2104
+ addLink(start, end, radius, bidirectional, area, user) {
2105
+ let handle = this.require(), f = this.floats;
2106
+ for (let k = 0; k < 3; k++)
2107
+ f[0 + k] = start[k], f[3 + k] = end[k];
2108
+ return f[29] = radius, this.words[30] = (bidirectional ? 1 : 0) | area << 8, this.words[31] = user >>> 0, this.check(this.exports.engine_nav_add_link(handle), "add link");
2109
+ }
2110
+ removeLink(link) {
2111
+ this.check(this.exports.engine_nav_remove_link(this.require(), link), "remove link");
2112
+ }
2113
+ setAreaCost(area, cost) {
2114
+ this.require(), this.costs[area] = cost;
2115
+ }
2116
+ setIncludeMask(low, high) {
2117
+ let handle = this.require();
2118
+ this.words[27] = low, this.words[28] = high, this.check(this.exports.engine_nav_include(handle), "include mask");
2119
+ }
2120
+ nearest(x, y, z, out) {
2121
+ let handle = this.require(), f = this.floats;
2122
+ return f[0] = x, f[1] = y, f[2] = z, this.check(this.exports.engine_nav_nearest(handle), "nearest") === 0 ? false : (out[0] = f[10], out[1] = f[11], out[2] = f[12], true);
2123
+ }
2124
+ findPath(sx, sy, sz, ex, ey, ez, out) {
2125
+ let handle = this.require(), f = this.floats;
2126
+ f[0] = sx, f[1] = sy, f[2] = sz, f[3] = ex, f[4] = ey, f[5] = ez;
2127
+ let maxPoints = Math.max(Math.floor(out.length / 3), 1), pointer = this.alloc(maxPoints * 3 * WORD_BYTES), code = this.exports.engine_nav_find_path(handle, pointer, maxPoints);
2128
+ return code < 0 ? (this.complete = false, 0) : (out.set(new Float32Array(this.runtime.memory.buffer, pointer, code * 3)), this.complete = this.words[13] === 1, code);
2129
+ }
2130
+ addAgent(x, y, z, radius, speed, accel) {
2131
+ let handle = this.require(), f = this.floats;
2132
+ return f[0] = x, f[1] = y, f[2] = z, f[15] = radius, f[16] = speed, f[17] = accel, this.check(this.exports.engine_nav_agent_add(handle), "add agent");
2133
+ }
2134
+ removeAgent(agent) {
2135
+ this.check(this.exports.engine_nav_agent_remove(this.require(), agent), "remove agent");
2136
+ }
2137
+ setAgentTarget(agent, x, y, z) {
2138
+ let handle = this.require(), f = this.floats;
2139
+ f[3] = x, f[4] = y, f[5] = z, this.check(this.exports.engine_nav_agent_target(handle, agent), "agent target");
2140
+ }
2141
+ stopAgent(agent) {
2142
+ this.check(this.exports.engine_nav_agent_stop(this.require(), agent), "stop agent");
2143
+ }
2144
+ agents() {
2145
+ return this.agentView;
2146
+ }
2147
+ loadRoads(words) {
2148
+ let handle = this.require(), pointer = this.alloc(words.byteLength);
2149
+ new Uint32Array(this.runtime.memory.buffer, pointer, words.length).set(words), this.check(this.exports.engine_nav_roads(handle, pointer, words.length), "load roads"), this.maxVehicles = words[5];
2150
+ let padded = Math.ceil(this.maxVehicles / 4) * 4;
2151
+ this.vehicleView = new Float32Array(this.runtime.memory.buffer, this.exports.engine_nav_vehicles(handle), padded * 8);
2152
+ }
2153
+ addVehicle(lane, position, speed, driver) {
2154
+ let handle = this.require(), f = this.floats;
2155
+ f[18] = position, f[19] = speed;
2156
+ for (let k = 0; k < (6); k++) f[20 + k] = driver[k];
2157
+ return this.check(this.exports.engine_nav_vehicle_add(handle, lane), "add vehicle");
2158
+ }
2159
+ removeVehicle(vehicle) {
2160
+ this.check(this.exports.engine_nav_vehicle_remove(this.require(), vehicle), "remove vehicle");
2161
+ }
2162
+ setExternalVehicle(vehicle, lane, position, speed) {
2163
+ let handle = this.require();
2164
+ this.floats[18] = position, this.floats[19] = speed, this.check(this.exports.engine_nav_vehicle_external(handle, vehicle, lane), "external vehicle");
2165
+ }
2166
+ vehicles() {
2167
+ return this.vehicleView;
2168
+ }
2169
+ signal(lane) {
2170
+ return this.check(this.exports.engine_nav_signal(this.require(), lane), "signal");
2171
+ }
2172
+ step(dt) {
2173
+ let handle = this.require();
2174
+ this.floats[14] = dt, this.check(this.exports.engine_nav_step(handle), "nav step");
2175
+ }
2176
+ dispose() {
2177
+ this.handle !== (0) && this.exports.engine_nav_destroy(this.handle), this.scratch !== (0) && this.runtime.exports.engine_free(this.scratch, this.scratchBytes, WORD_BYTES), this.handle = (0), this.scratch = (0), this.scratchBytes = 0;
2178
+ }
2179
+ };
2180
+
2181
+ // src/game/backends/engine/craft.ts
2182
+ var ENGINE_CRAFT_NAME = "engine-craft", CRAFT_EXPORTS = [
2183
+ "engine_craft_create",
2184
+ "engine_craft_destroy",
2185
+ "engine_craft_registers",
2186
+ "engine_craft_controls",
2187
+ "engine_craft_telemetry",
2188
+ "engine_craft_set_water",
2189
+ "engine_craft_set_flow",
2190
+ "engine_craft_sea",
2191
+ "engine_craft_custom",
2192
+ "engine_craft_spin_up",
2193
+ "engine_craft_remove",
2194
+ "engine_craft_step",
2195
+ "engine_water_sample",
2196
+ "engine_alloc",
2197
+ "engine_free"
2198
+ ], MILLIMETRES = 1e3, OCEAN_SIZE = 113, OCEAN_PATCH = 114, OCEAN_WIND = 115, OCEAN_AMPLITUDE = 117, OCEAN_CHOPPINESS = 118, OCEAN_SMALL_WAVE = 119, OCEAN_SEED = 120, OCEAN_EVERY = 121, POINT_X = 122, POINT_Z = 123, POINT_AMOUNT = 124, DEFAULT_OCEAN_SIZE = 64, DEFAULT_OCEAN_PATCH = 64, DEFAULT_OCEAN_AMPLITUDE = 2e-4, DEFAULT_OCEAN_CHOPPINESS = 1.2, DEFAULT_OCEAN_SMALL_WAVE = 0.05, NO_RENDER = 0, DEFAULT_RIPPLE_SIZE = 128, DEFAULT_RIPPLE_CELL = 0.25, DEFAULT_RIPPLE_SPEED = 1.5, NO_RIPPLES = 0, NO_PUDDLES = 0, DEFAULT_PUDDLE_DEPTH = 0.5, REGISTER_WORDS2 = 128, WATER_LEVEL = 0, WATER_DEPTH = 1, WATER_GRAVITY = 2, WATER_DENSITY = 3, WATER_CURRENT = 4, WATER_WIND = 6, WATER_GUST = 8, WATER_GUST_PERIOD = 9, WATER_ITERATIONS = 10, WATER_WAVE_COUNT = 11, WATER_WAVES = 12, WAVE_WORDS = 6, DEFAULT_GRAVITY = 9.81, DEFAULT_DENSITY = 1025, DEFAULT_ITERATIONS = 2, NO_HANDLE2 = 0, FLOAT_BYTES = 4, SAMPLE_CAPACITY = 1024, CASCADE_DESC_FLOATS = 21, CASCADE_SEED_LOW = 19, CASCADE_SEED_HIGH = 20, SEED_HIGH = 2 ** 32, DEFAULT_PHYSICS_SIZE = 64, DEFAULT_CASCADES = {
2199
+ size: 256,
2200
+ count: 4,
2201
+ patches: [256, 64, 16, 4],
2202
+ windSpeed: 10,
2203
+ windDirection: 0,
2204
+ fetch: 1e5,
2205
+ peakEnhancement: 3.3,
2206
+ swell: 0,
2207
+ depth: Number.POSITIVE_INFINITY,
2208
+ shortWaves: 0.01,
2209
+ scale: 1,
2210
+ choppiness: 1,
2211
+ gravity: 9.81,
2212
+ seed: 1
2213
+ }, DEFAULT_FOAM = { threshold: 0.7, gain: 4, decaySeconds: 2.5 };
2214
+ function packCascades(desc) {
2215
+ let out = new Float32Array((21)), bits = new Uint32Array(out.buffer);
2216
+ if (desc === null) return out;
2217
+ let d = { ...DEFAULT_CASCADES, ...desc }, foam = { ...DEFAULT_FOAM, ...desc.foam };
2218
+ out.set([d.size, d.count, ...d.patches, d.windSpeed, d.windDirection, d.fetch, d.peakEnhancement, d.swell, d.depth, d.shortWaves, d.scale, d.choppiness, foam.threshold, foam.gain, foam.decaySeconds, d.gravity]);
2219
+ let seed = Math.max(0, Math.floor(d.seed));
2220
+ return bits[(19)] = seed % SEED_HIGH, bits[(20)] = Math.floor(seed / SEED_HIGH), out;
2221
+ }
2222
+ function hasCraft(symbols) {
2223
+ return CRAFT_EXPORTS.every((name) => typeof symbols[name] == "function");
2224
+ }
2225
+ function engineCraft(session) {
2226
+ return hasCraft(session.symbols) ? new EngineCraft(session, session.symbols) : null;
2227
+ }
2228
+ var EngineCraft = class {
2229
+ constructor(session, symbols, capacity = 64) {
2230
+ this.name = ENGINE_CRAFT_NAME;
2231
+ this.handle = (0);
2232
+ this.words = new Uint32Array(0);
2233
+ this.floats = new Float32Array(0);
2234
+ this.controlTable = new Float32Array(0);
2235
+ this.telemetryTable = new Float32Array(0);
2236
+ this.points = 0;
2237
+ this.samples = 0;
2238
+ this.render = () => (0);
2239
+ this.pointView = new Float32Array(0);
2240
+ this.sampleView = new Float32Array(0);
2241
+ if (!hasCraft(symbols)) throw new GameError("unsupported_feature", "this engine build has no craft simulation");
2242
+ this.session = session, this.exports = symbols, this.capacity = capacity;
2243
+ }
2244
+ configureWater(desc) {
2245
+ this.open();
2246
+ let w = this.words, f = this.floats, waves = desc.waves ?? [];
2247
+ if (waves.length > MAX_WAVES) throw new GameError("invalid_argument", "too many waves");
2248
+ f[(0)] = desc.level ?? 0, f[(1)] = desc.depth ?? Number.POSITIVE_INFINITY, f[(2)] = desc.gravity ?? (9.81), f[(3)] = desc.density ?? (1025), f[(4)] = desc.current?.[0] ?? 0, f[(4) + 1] = desc.current?.[1] ?? 0, f[(6)] = desc.wind?.[0] ?? 0, f[(6) + 1] = desc.wind?.[1] ?? 0, f[(8)] = desc.gust ?? 0, f[(9)] = desc.gustPeriod ?? 0, w[(10)] = desc.iterations ?? (2), w[(11)] = waves.length, waves.forEach((wave, i) => {
2249
+ let o = (12) + i * (6);
2250
+ f[o] = wave.direction[0], f[o + 1] = wave.direction[1], f[o + 2] = wave.wavelength, f[o + 3] = wave.amplitude, f[o + 4] = wave.steepness, f[o + 5] = wave.phase;
2251
+ }), this.session.check(this.exports.engine_craft_set_water(this.handle), "configure water");
2252
+ }
2253
+ sea(state, windRadians, seed) {
2254
+ this.open(), this.session.check(this.exports.engine_craft_sea(this.handle, SEA_STATES.indexOf(state), windRadians, seed >>> 0), "sea state");
2255
+ }
2256
+ setFlow(flow) {
2257
+ this.open();
2258
+ let f = this.floats;
2259
+ f[(0)] = flow.level, f[(4)] = flow.current[0], f[(4) + 1] = flow.current[1], f[(6)] = flow.wind[0], f[(6) + 1] = flow.wind[1], f[(8)] = flow.gust, f[(9)] = flow.gustPeriod, this.session.check(this.exports.engine_craft_set_flow(this.handle), "water flow");
2260
+ }
2261
+ createCraft(_entity, body, collider, words, running) {
2262
+ this.open();
2263
+ let bytes = words.length * (4), pointer = this.exports.engine_alloc(bytes, (4));
2264
+ if (pointer === 0) throw new GameError("capacity_exceeded", "craft description could not be staged");
2265
+ try {
2266
+ new Float32Array(this.session.buffer, pointer, words.length).set(words);
2267
+ let id = this.session.check(
2268
+ this.exports.engine_craft_custom(this.handle, body, collider >>> 0, pointer, words.length),
2269
+ "create craft"
2270
+ );
2271
+ return running && this.session.check(this.exports.engine_craft_spin_up(this.handle, id), "spin up craft"), id;
2272
+ } finally {
2273
+ this.exports.engine_free(pointer, bytes, (4));
2274
+ }
2275
+ }
2276
+ removeCraft(craft) {
2277
+ this.open(), this.session.check(this.exports.engine_craft_remove(this.handle, craft), "remove craft");
2278
+ }
2279
+ controls() {
2280
+ return this.open(), this.controlTable;
2281
+ }
2282
+ telemetry() {
2283
+ return this.open(), this.telemetryTable;
2284
+ }
2285
+ setOcean(desc) {
2286
+ let ocean = this.exports.engine_craft_ocean;
2287
+ if (!ocean) throw new GameError("unsupported_feature", "this engine build has no ocean simulation");
2288
+ this.open();
2289
+ let w = this.words, f = this.floats;
2290
+ w[(113)] = desc ? desc.size ?? (64) : 0, f[(114)] = desc?.patch ?? (64), f[(115)] = desc?.wind?.[0] ?? f[(6)], f[(115) + 1] = desc?.wind?.[1] ?? f[(6) + 1], f[(117)] = desc?.amplitude ?? (2e-4), f[(118)] = desc?.choppiness ?? (1.2), f[(119)] = desc?.smallWave ?? (0.05), w[(120)] = (desc?.seed ?? 1) >>> 0, w[(121)] = Math.max(1, desc?.updateEvery ?? 1), this.session.check(ocean(this.handle), "configure ocean");
2291
+ }
2292
+ setRipples(desc) {
2293
+ let ripples = this.exports.engine_craft_ripples;
2294
+ if (!ripples) throw new GameError("unsupported_feature", "this engine build has no ripples");
2295
+ this.open();
2296
+ let size = desc ? desc.size ?? (128) : (0), cell = desc?.cell ?? (0.25), speed = desc?.speed ?? (1.5);
2297
+ this.session.check(ripples(this.handle, size, cell, speed), "configure ripples");
2298
+ }
2299
+ setCascades(desc) {
2300
+ let cascades = this.exports.engine_craft_cascades;
2301
+ if (!cascades) throw new GameError("unsupported_feature", "this engine build has no FFT ocean");
2302
+ let render = this.render();
2303
+ if (render === (0)) throw new GameError("invalid_argument", "the FFT ocean needs a render world to draw it");
2304
+ this.open();
2305
+ let words = packCascades(desc), pointer = this.exports.engine_alloc(words.byteLength, (4));
2306
+ if (pointer === 0) throw new GameError("capacity_exceeded", "engine memory cannot hold the ocean desc");
2307
+ try {
2308
+ new Float32Array(this.session.buffer, pointer, (21)).set(words);
2309
+ let size = desc?.physicsSize ?? (64);
2310
+ this.session.check(cascades(this.handle, render, pointer, size), "FFT ocean");
2311
+ } finally {
2312
+ this.exports.engine_free(pointer, words.byteLength, (4));
2313
+ }
2314
+ }
2315
+ setPuddles(desc) {
2316
+ let puddles = this.exports.engine_craft_puddles;
2317
+ if (!puddles) throw new GameError("unsupported_feature", "this engine build has no puddles");
2318
+ this.open();
2319
+ let width = desc ? desc.width : (0);
2320
+ this.session.check(
2321
+ puddles(this.handle, desc?.origin[0] ?? 0, desc?.origin[1] ?? 0, desc?.cell ?? 0, width, desc?.height ?? 0, desc?.maxDepth ?? (0.5)),
2322
+ "configure puddles"
2323
+ );
2324
+ }
2325
+ setPuddleBed(heights) {
2326
+ let bed = this.exports.engine_craft_puddles_bed;
2327
+ if (!bed || this.handle === (0)) return;
2328
+ let bytes = Math.max(heights.byteLength, (4)), pointer = this.exports.engine_alloc(bytes, (4));
2329
+ if (pointer === 0) throw new GameError("capacity_exceeded", "engine memory cannot hold the puddle bed");
2330
+ try {
2331
+ new Float32Array(this.session.buffer, pointer, heights.length).set(heights), this.session.check(bed(this.handle, pointer, heights.length), "puddle bed");
2332
+ } finally {
2333
+ this.exports.engine_free(pointer, bytes, (4));
2334
+ }
2335
+ }
2336
+ pourPuddles(x, z, volume) {
2337
+ let pour = this.exports.engine_craft_puddles_pour;
2338
+ pour && this.handle !== (0) && (this.point(x, z, volume), this.session.check(pour(this.handle), "pour"));
2339
+ }
2340
+ /** Per-frame water calls pass integers only: the point goes through the registers. */
2341
+ point(x, z, amount) {
2342
+ let f = this.floats;
2343
+ f[(122)] = x, f[(123)] = z, f[(124)] = amount;
2344
+ }
2345
+ puddleWeather(rain, evaporation) {
2346
+ let weather = this.exports.engine_craft_puddles_weather;
2347
+ weather && this.handle !== (0) && this.session.check(weather(this.handle, rain, evaporation), "puddle weather");
2348
+ }
2349
+ followRipples(x, z) {
2350
+ let follow = this.exports.engine_craft_ripples_follow;
2351
+ follow && this.handle !== (0) && (this.point(x, z, 0), this.session.check(follow(this.handle), "follow ripples"));
2352
+ }
2353
+ pushRipples(x, z, amount) {
2354
+ let push = this.exports.engine_craft_ripples_push;
2355
+ push && this.handle !== (0) && (this.point(x, z, amount), this.session.check(push(this.handle), "push ripples"));
2356
+ }
2357
+ bindRender(source) {
2358
+ this.render = source;
2359
+ }
2360
+ step() {
2361
+ if (this.handle === (0) || this.session.world === 0) return;
2362
+ this.session.check(this.exports.engine_craft_step(this.handle, this.session.world), "craft step");
2363
+ let handoff = this.exports.engine_craft_render_water, render = this.render();
2364
+ handoff && render !== (0) && this.session.check(handoff(this.handle, render), "render water");
2365
+ }
2366
+ sampleWater(points, count, out) {
2367
+ this.open();
2368
+ let buffer = this.session.buffer;
2369
+ this.pointView.buffer !== buffer && (this.pointView = new Float32Array(buffer, this.points, (1024) * 2), this.sampleView = new Float32Array(buffer, this.samples, (1024) * WATER_SAMPLE_WORDS));
2370
+ for (let start = 0; start < count; start += (1024)) {
2371
+ let n = Math.min((1024), count - start);
2372
+ for (let i = 0; i < n * 2; i++) this.pointView[i] = points[start * 2 + i];
2373
+ this.session.check(this.exports.engine_water_sample(this.handle, this.points, n, this.samples), "water sample");
2374
+ let base = start * WATER_SAMPLE_WORDS;
2375
+ for (let i = 0; i < n * WATER_SAMPLE_WORDS; i++) out[base + i] = this.sampleView[i];
2376
+ }
2377
+ }
2378
+ floatsIn(values) {
2379
+ let pointer = this.exports.engine_alloc(Math.max(values.byteLength, (4)), (4));
2380
+ if (pointer === 0) throw new GameError("capacity_exceeded", "engine memory cannot hold the crumple data");
2381
+ return new Float32Array(this.session.buffer, pointer, values.length).set(values), pointer;
2382
+ }
2383
+ crumpleExport(name) {
2384
+ let found = this.exports[name];
2385
+ if (!found) throw new GameError("unsupported_feature", `this engine build has no vehicle crumple (feature ${SOFT_BODY_FEATURE})`);
2386
+ return found;
2387
+ }
2388
+ crumple(craft, vertices, desc) {
2389
+ let create = this.crumpleExport("engine_craft_crumple");
2390
+ this.open();
2391
+ let points = this.floatsIn(vertices), words = desc === null ? 0 : this.floatsIn(desc);
2392
+ try {
2393
+ this.session.check(create(this.handle, craft, words, points, vertices.length / 3), "crumple cage");
2394
+ } finally {
2395
+ this.exports.engine_free(points, Math.max(vertices.byteLength, (4)), (4)), desc !== null && this.exports.engine_free(words, Math.max(desc.byteLength, (4)), (4));
2396
+ }
2397
+ }
2398
+ impact(craft, point, severity) {
2399
+ let impact = this.crumpleExport("engine_craft_impact");
2400
+ this.open();
2401
+ let words = this.floatsIn(new Float32Array([...point, ...severity]));
2402
+ try {
2403
+ return this.session.check(impact(this.handle, craft, words), "impact") === 1;
2404
+ } finally {
2405
+ this.exports.engine_free(words, CRUMPLE_IMPACT_FLOATS * (4), (4));
2406
+ }
2407
+ }
2408
+ damage(craft) {
2409
+ if (this.handle === (0)) return 0;
2410
+ let mm = this.crumpleExport("engine_craft_damage")(this.handle, craft);
2411
+ return mm >= 0 ? mm / (1e3) : 0;
2412
+ }
2413
+ presentCrumple(craft, geometry) {
2414
+ let render = this.render();
2415
+ if (this.handle === (0) || render === (0)) return 0;
2416
+ let written = this.crumpleExport("engine_craft_crumple_present")(this.handle, craft, render, geometry);
2417
+ return written >= 0 ? written : 0;
2418
+ }
2419
+ dispose() {
2420
+ this.handle !== (0) && (this.exports.engine_craft_destroy(this.handle), this.exports.engine_free(this.points, (1024) * 2 * (4), (4)), this.exports.engine_free(this.samples, (1024) * WATER_SAMPLE_WORDS * (4), (4)), this.handle = (0));
2421
+ }
2422
+ open() {
2423
+ if (this.handle !== (0)) return;
2424
+ let handle = this.exports.engine_craft_create(this.capacity);
2425
+ if (handle === (0)) throw new GameError("capacity_exceeded", "craft world could not be created");
2426
+ this.handle = handle;
2427
+ let buffer = this.session.buffer, registers = this.exports.engine_craft_registers(handle);
2428
+ if (this.words = new Uint32Array(buffer, registers, (128)), this.floats = new Float32Array(buffer, registers, (128)), this.controlTable = new Float32Array(buffer, this.exports.engine_craft_controls(handle), this.capacity * 16), this.telemetryTable = new Float32Array(buffer, this.exports.engine_craft_telemetry(handle), this.capacity * 16), this.points = this.exports.engine_alloc((1024) * 2 * (4), (4)), this.samples = this.exports.engine_alloc((1024) * WATER_SAMPLE_WORDS * (4), (4)), this.points === 0 || this.samples === 0) throw new GameError("capacity_exceeded", "water sample buffers could not be allocated");
2429
+ }
2430
+ };
2431
+
2432
+ // src/game/backends/engine/vehicles.ts
2433
+ var ENGINE_VEHICLE_EXPORT_NAMES = [
2434
+ "engine_vehicle_reserve",
2435
+ "engine_vehicle_create",
2436
+ "engine_vehicle_destroy",
2437
+ "engine_vehicle_capacity",
2438
+ "engine_vehicle_inputs",
2439
+ "engine_vehicle_states"
2440
+ ], NO_POINTER2 = 0, EMPTY2 = new Float32Array(0);
2441
+ function engineVehicleExports(symbols) {
2442
+ for (let name of ENGINE_VEHICLE_EXPORT_NAMES) if (typeof symbols[name] != "function") return null;
2443
+ return symbols;
2444
+ }
2445
+ var EngineVehicles = class {
2446
+ constructor(session, exports) {
2447
+ this.desc = (0);
2448
+ this.inputs = EMPTY2;
2449
+ this.states = EMPTY2;
2450
+ this.session = session, this.exports = exports;
2451
+ }
2452
+ createVehicle(body, desc) {
2453
+ let s = this.session;
2454
+ s.flush();
2455
+ let world = s.require();
2456
+ if (this.desc === (0) && (this.desc = s.exports.engine_alloc(VEHICLE_DESC_WORDS * WORD_BYTES, WORD_BYTES), this.desc === (0)))
2457
+ throw new GameError("capacity_exceeded", "engine memory cannot hold a vehicle descriptor");
2458
+ new Float32Array(s.buffer, this.desc, VEHICLE_DESC_WORDS).set(desc.subarray(0, VEHICLE_DESC_WORDS));
2459
+ let id = s.check(this.exports.engine_vehicle_create(world, body, this.desc, VEHICLE_DESC_WORDS), "create vehicle");
2460
+ return this.bindViews(world), id;
2461
+ }
2462
+ destroyVehicle(vehicle) {
2463
+ let s = this.session;
2464
+ s.flush(), s.check(this.exports.engine_vehicle_destroy(s.require(), vehicle), "destroy vehicle");
2465
+ }
2466
+ vehicleInputs() {
2467
+ return this.inputs;
2468
+ }
2469
+ vehicleStates() {
2470
+ return this.states;
2471
+ }
2472
+ bindViews(world) {
2473
+ let capacity = this.exports.engine_vehicle_capacity(world), inputs = this.exports.engine_vehicle_inputs(world), states = this.exports.engine_vehicle_states(world);
2474
+ if (inputs === (0) || states === (0)) throw new GameError("not_initialized", "engine vehicles are not reserved");
2475
+ let buffer = this.session.buffer;
2476
+ (this.inputs.byteOffset !== inputs || this.inputs.buffer !== buffer) && (this.inputs = new Float32Array(buffer, inputs, capacity * INPUT_STRIDE), this.states = new Float32Array(buffer, states, capacity * STATE_STRIDE));
2477
+ }
2478
+ };
2479
+
2480
+ // src/game/backends/engine/physics.ts
2481
+ var ENGINE_PHYSICS_NAME = "cimplify-engine", COLLISION_GROUP_BITS = 65535, DEGREES_TO_RADIANS = Math.PI / 180, DEFAULT_CONTROLLER_OFFSET = 0.01, ORIGIN = [0, 0, 0], IDENTITY_ROTATION = [0, 0, 0, 1], ALL_AXES = [true, true, true], NO_AXES = [false, false, false], PLANAR_TRANSLATIONS = [true, true, false], PLANAR_ROTATIONS = [false, false, true], NO_POINTER3 = 0, NO_VALUE = Number.NaN;
2482
+ function axisBits(axes, shift) {
2483
+ return ((axes[0] ? 1 : 0) | (axes[1] ? 2 : 0) | (axes[2] ? 4 : 0)) << shift;
2484
+ }
2485
+ function shapeCode(shape) {
2486
+ switch (shape.kind) {
2487
+ case "ball":
2488
+ return SHAPE_BALL;
2489
+ case "cuboid":
2490
+ return SHAPE_CUBOID;
2491
+ case "capsule":
2492
+ return SHAPE_CAPSULE;
2493
+ case "cylinder":
2494
+ return SHAPE_CYLINDER;
2495
+ case "cone":
2496
+ return SHAPE_CONE;
2497
+ case "trimesh":
2498
+ return SHAPE_TRIMESH;
2499
+ case "convex_hull":
2500
+ return SHAPE_CONVEX_HULL;
2501
+ case "heightfield":
2502
+ return SHAPE_HEIGHTFIELD;
2503
+ case "round_cuboid":
2504
+ return SHAPE_ROUND_CUBOID;
2505
+ case "round_cylinder":
2506
+ return SHAPE_ROUND_CYLINDER;
2507
+ case "round_cone":
2508
+ return SHAPE_ROUND_CONE;
2509
+ case "round_convex_hull":
2510
+ return SHAPE_ROUND_CONVEX_HULL;
2511
+ case "compound":
2512
+ return SHAPE_COMPOUND;
2513
+ }
2514
+ }
2515
+ function writePrimitive(shape, floats, params, border) {
2516
+ switch (shape.kind) {
2517
+ case "ball":
2518
+ floats[params] = shape.radius;
2519
+ break;
2520
+ case "cuboid":
2521
+ case "round_cuboid":
2522
+ floats[params] = shape.halfExtents[0], floats[params + 1] = shape.halfExtents[1], floats[params + 2] = shape.halfExtents[2];
2523
+ break;
2524
+ case "capsule":
2525
+ case "cylinder":
2526
+ case "cone":
2527
+ case "round_cylinder":
2528
+ case "round_cone":
2529
+ floats[params] = shape.halfHeight, floats[params + 1] = shape.radius;
2530
+ break;
2531
+ }
2532
+ (shape.kind === "round_cuboid" || shape.kind === "round_cylinder" || shape.kind === "round_cone") && (floats[border] = shape.border);
2533
+ }
2534
+ function compoundFloats(parts) {
2535
+ let out = new Float32Array(parts.length * PART_FLOATS);
2536
+ for (let i = 0; i < parts.length; i++) {
2537
+ let part = parts[i], at = i * PART_FLOATS;
2538
+ out[at + PART_SHAPE] = shapeCode(part.shape), writePrimitive(part.shape, out, at + PART_PARAMS, at + PART_BORDER);
2539
+ let offset = part.offset ?? ORIGIN, rotation = part.rotation ?? IDENTITY_ROTATION;
2540
+ for (let k = 0; k < 3; k++) out[at + PART_OFFSET + k] = offset[k];
2541
+ for (let k = 0; k < 4; k++) out[at + PART_ROTATION + k] = rotation[k];
2542
+ }
2543
+ return out;
2544
+ }
2545
+ var LOCKED_AXES = ["locked", "locked", "locked"], LIMIT_PAIR = 2, SIX_DOF_AXES = 6, QUATERNION = 4;
2546
+ function encodeSixDof(desc, words, floats) {
2547
+ let frameA = desc.frameA ?? IDENTITY_ROTATION, frameB = desc.frameB ?? IDENTITY_ROTATION;
2548
+ for (let k = 0; k < (4); k++)
2549
+ floats[JOINT_FRAME_A + k] = frameA[k], floats[JOINT_FRAME_B + k] = frameB[k];
2550
+ let axes = [...desc.linear ?? LOCKED_AXES, ...desc.angular ?? LOCKED_AXES];
2551
+ if (axes.length !== (6)) throw new GameError("invalid_argument", "a six_dof joint has three linear and three angular axes");
2552
+ let motions = 0;
2553
+ for (let axis = 0; axis < (6); axis++) {
2554
+ let motion = axes[axis], code = MOTION_LOCKED;
2555
+ motion === "free" ? code = MOTION_FREE : motion !== "locked" && (code = MOTION_LIMITED, floats[JOINT_AXIS_LIMITS + axis * (2)] = motion[0], floats[JOINT_AXIS_LIMITS + axis * (2) + 1] = motion[1]), motions |= code << axis * MOTION_BITS;
2556
+ }
2557
+ words[JOINT_MOTIONS] = motions >>> 0, floats[JOINT_SWING_CONE] = desc.swingCone ?? NO_VALUE;
2558
+ }
2559
+ var EnginePhysics = class {
2560
+ constructor(session) {
2561
+ this.name = ENGINE_PHYSICS_NAME;
2562
+ this.session = session;
2563
+ let exports = engineVehicleExports(session.symbols);
2564
+ this.vehicles = exports ? new EngineVehicles(session, exports) : null, this.craft = engineCraft(session), this.jointPort = engineJoints(session);
2565
+ }
2566
+ bindTransforms(columns) {
2567
+ this.session.bind(columns);
2568
+ }
2569
+ init(desc) {
2570
+ return this.session.open(desc), Promise.resolve();
2571
+ }
2572
+ get rollback() {
2573
+ return this.session.snapshots;
2574
+ }
2575
+ setGravity(gravity) {
2576
+ this.vectorCommand(OP_SET_GRAVITY, 0, gravity);
2577
+ }
2578
+ createBody(entity, desc) {
2579
+ let s = this.session;
2580
+ s.flush();
2581
+ let words = s.descWords, floats = s.descFloats;
2582
+ words[BODY_KIND] = desc.kind === "dynamic" ? BODY_KIND_DYNAMIC : desc.kind === "kinematic" ? BODY_KIND_KINEMATIC : BODY_KIND_FIXED, floats[BODY_LINEAR_DAMPING] = desc.linearDamping ?? 0, floats[BODY_ANGULAR_DAMPING] = desc.angularDamping ?? 0, floats[BODY_GRAVITY_SCALE] = desc.gravityScale ?? 1;
2583
+ let translations = desc.planar ? PLANAR_TRANSLATIONS : desc.lockTranslations ? NO_AXES : desc.enabledTranslations ?? ALL_AXES, rotations = desc.planar ? PLANAR_ROTATIONS : desc.lockRotations ? NO_AXES : desc.enabledRotations ?? ALL_AXES;
2584
+ return words[BODY_FLAGS] = (desc.ccd ? BODY_FLAG_CCD : 0) | (desc.canSleep === false ? 0 : BODY_FLAG_CAN_SLEEP) | axisBits(translations, BODY_TRANSLATION_SHIFT) | axisBits(rotations, BODY_ROTATION_SHIFT), words[BODY_DOMINANCE] = desc.dominance ?? 0, s.check(s.exports.engine_body_create(s.require(), entity), "create body");
2585
+ }
2586
+ destroyBody(body) {
2587
+ let s = this.session;
2588
+ s.flush(), s.check(s.exports.engine_body_destroy(s.require(), body), "destroy body");
2589
+ }
2590
+ createCollider(body, desc) {
2591
+ let s = this.session;
2592
+ s.flush();
2593
+ let words = s.descWords, floats = s.descFloats;
2594
+ words.fill(0);
2595
+ let shape = desc.shape;
2596
+ words[COLLIDER_SHAPE] = shapeCode(shape);
2597
+ let staged = [];
2598
+ switch (shape.kind) {
2599
+ case "ball":
2600
+ case "cuboid":
2601
+ case "capsule":
2602
+ case "cylinder":
2603
+ case "cone":
2604
+ case "round_cuboid":
2605
+ case "round_cylinder":
2606
+ case "round_cone":
2607
+ writePrimitive(shape, floats, COLLIDER_PARAMS, COLLIDER_BORDER);
2608
+ break;
2609
+ case "round_convex_hull":
2610
+ this.stage(staged, shape.points, COLLIDER_DATA_A, COLLIDER_DATA_A_LEN), floats[COLLIDER_BORDER] = shape.border;
2611
+ break;
2612
+ case "compound":
2613
+ this.stage(staged, compoundFloats(shape.parts), COLLIDER_DATA_A, COLLIDER_DATA_A_LEN);
2614
+ break;
2615
+ case "trimesh":
2616
+ this.stage(staged, shape.vertices, COLLIDER_DATA_A, COLLIDER_DATA_A_LEN), this.stage(staged, shape.indices, COLLIDER_DATA_B, COLLIDER_DATA_B_LEN);
2617
+ break;
2618
+ case "convex_hull":
2619
+ this.stage(staged, shape.points, COLLIDER_DATA_A, COLLIDER_DATA_A_LEN);
2620
+ break;
2621
+ case "heightfield":
2622
+ this.stage(staged, shape.heights, COLLIDER_DATA_A, COLLIDER_DATA_A_LEN), words[COLLIDER_ROWS] = shape.rows, words[COLLIDER_COLUMNS] = shape.columns, floats[COLLIDER_PARAMS] = shape.scale[0], floats[COLLIDER_PARAMS + 1] = shape.scale[1], floats[COLLIDER_PARAMS + 2] = shape.scale[2];
2623
+ break;
2624
+ }
2625
+ let offset = desc.offset ?? ORIGIN, rotation = desc.rotation ?? IDENTITY_ROTATION;
2626
+ for (let k = 0; k < 3; k++) floats[COLLIDER_OFFSET + k] = offset[k];
2627
+ for (let k = 0; k < 4; k++) floats[COLLIDER_ROTATION + k] = rotation[k];
2628
+ floats[COLLIDER_DENSITY] = desc.density ?? NO_VALUE, floats[COLLIDER_MASS] = desc.mass ?? NO_VALUE, floats[COLLIDER_FRICTION] = desc.friction ?? NO_VALUE, floats[COLLIDER_RESTITUTION] = desc.restitution ?? NO_VALUE;
2629
+ let grouped = desc.membership !== void 0 || desc.filter !== void 0;
2630
+ words[COLLIDER_FLAGS] = (desc.sensor ? COLLIDER_FLAG_SENSOR : 0) | (desc.events ? COLLIDER_FLAG_EVENTS : 0) | (grouped ? COLLIDER_FLAG_GROUPS : 0), words[COLLIDER_MEMBERSHIP] = desc.membership ?? COLLISION_GROUP_ALL, words[COLLIDER_FILTER] = desc.filter ?? COLLISION_GROUP_ALL;
2631
+ try {
2632
+ return s.check(s.exports.engine_collider_create(s.require(), body), "create collider");
2633
+ } finally {
2634
+ for (let block of staged) s.exports.engine_free(block.pointer, block.bytes, WORD_BYTES);
2635
+ }
2636
+ }
2637
+ destroyCollider(collider) {
2638
+ let s = this.session;
2639
+ s.flush(), s.check(s.exports.engine_collider_destroy(s.require(), collider), "destroy collider");
2640
+ }
2641
+ setColliderEnabled(collider, enabled) {
2642
+ let s = this.session;
2643
+ s.flush(), s.check(s.exports.engine_collider_enable(s.require(), collider, enabled ? 1 : 0), "enable collider");
2644
+ }
2645
+ createJoint(bodyA, bodyB, desc) {
2646
+ let s = this.session;
2647
+ s.flush();
2648
+ let words = s.descWords, floats = s.descFloats;
2649
+ words.fill(0);
2650
+ for (let k = 0; k < 3; k++)
2651
+ floats[JOINT_ANCHOR_A + k] = desc.anchorA[k], floats[JOINT_ANCHOR_B + k] = desc.anchorB[k];
2652
+ switch (desc.kind) {
2653
+ case "fixed":
2654
+ words[JOINT_KIND] = JOINT_FIXED;
2655
+ break;
2656
+ case "spherical":
2657
+ words[JOINT_KIND] = JOINT_SPHERICAL;
2658
+ break;
2659
+ case "revolute":
2660
+ case "prismatic":
2661
+ words[JOINT_KIND] = desc.kind === "revolute" ? JOINT_REVOLUTE : JOINT_PRISMATIC;
2662
+ for (let k = 0; k < 3; k++) floats[JOINT_AXIS + k] = desc.axis[k];
2663
+ desc.limits && (words[JOINT_HAS_LIMITS] = 1, floats[JOINT_LIMITS] = desc.limits[0], floats[JOINT_LIMITS + 1] = desc.limits[1]);
2664
+ break;
2665
+ case "rope":
2666
+ words[JOINT_KIND] = JOINT_ROPE, floats[JOINT_LENGTH] = desc.length;
2667
+ break;
2668
+ case "spring":
2669
+ words[JOINT_KIND] = JOINT_SPRING, floats[JOINT_LENGTH] = desc.restLength, floats[JOINT_STIFFNESS] = desc.stiffness, floats[JOINT_DAMPING] = desc.damping;
2670
+ break;
2671
+ case "cone":
2672
+ words[JOINT_KIND] = JOINT_CONE;
2673
+ for (let k = 0; k < 3; k++) floats[JOINT_AXIS + k] = desc.axis[k];
2674
+ floats[JOINT_SWING] = desc.swing, floats[JOINT_LIMITS] = desc.twist[0], floats[JOINT_LIMITS + 1] = desc.twist[1];
2675
+ break;
2676
+ case "six_dof":
2677
+ words[JOINT_KIND] = JOINT_SIX_DOF, encodeSixDof(desc, words, floats);
2678
+ break;
2679
+ }
2680
+ return s.check(s.exports.engine_joint_create(s.require(), bodyA, bodyB), "create joint");
2681
+ }
2682
+ setJointMotor(joint, targetVelocity, maxForce) {
2683
+ let s = this.session;
2684
+ s.flush();
2685
+ let world = s.require();
2686
+ s.registerFloats[REGISTER_MOTOR_VELOCITY] = targetVelocity, s.registerFloats[REGISTER_MOTOR_MAX_FORCE] = maxForce, s.check(s.exports.engine_joint_motor(world, joint), "joint motor");
2687
+ }
2688
+ destroyJoint(joint) {
2689
+ let s = this.session;
2690
+ s.flush(), s.check(s.exports.engine_joint_destroy(s.require(), joint), "destroy joint");
2691
+ }
2692
+ step() {
2693
+ this.session.step();
2694
+ }
2695
+ setBodyPose(body, positions, po, rotations, ro) {
2696
+ let s = this.session, o = s.command(OP_SET_BODY_POSE, body), f = s.commandPayload;
2697
+ f[o] = positions[po], f[o + 1] = positions[po + 1], f[o + 2] = positions[po + 2], f[o + 3] = rotations[ro], f[o + 4] = rotations[ro + 1], f[o + 5] = rotations[ro + 2], f[o + 6] = rotations[ro + 3];
2698
+ }
2699
+ linearVelocity(body, out) {
2700
+ let s = this.session;
2701
+ s.flush(), s.check(s.exports.engine_body_linear_velocity(s.require(), body), "linear velocity"), this.readVector(out);
2702
+ }
2703
+ angularVelocity(body, out) {
2704
+ let s = this.session;
2705
+ s.flush(), s.check(s.exports.engine_body_angular_velocity(s.require(), body), "angular velocity"), this.readVector(out);
2706
+ }
2707
+ setLinearVelocity(body, velocity) {
2708
+ this.vectorCommand(OP_SET_LINEAR_VELOCITY, body, velocity);
2709
+ }
2710
+ setAngularVelocity(body, velocity) {
2711
+ this.vectorCommand(OP_SET_ANGULAR_VELOCITY, body, velocity);
2712
+ }
2713
+ applyImpulse(body, impulse) {
2714
+ this.vectorCommand(OP_APPLY_IMPULSE, body, impulse);
2715
+ }
2716
+ applyTorqueImpulse(body, impulse) {
2717
+ this.vectorCommand(OP_APPLY_TORQUE_IMPULSE, body, impulse);
2718
+ }
2719
+ addForce(body, force) {
2720
+ this.vectorCommand(OP_ADD_FORCE, body, force);
2721
+ }
2722
+ applyImpulseAtPoint(body, impulse, point) {
2723
+ this.pointCommand(OP_APPLY_IMPULSE_AT_POINT, body, impulse, point);
2724
+ }
2725
+ addForceAtPoint(body, force, point) {
2726
+ this.pointCommand(OP_ADD_FORCE_AT_POINT, body, force, point);
2727
+ }
2728
+ addTorque(body, torque) {
2729
+ this.vectorCommand(OP_ADD_TORQUE, body, torque);
2730
+ }
2731
+ extra(name) {
2732
+ let fn = this.session.symbols[name];
2733
+ if (typeof fn != "function") throw new GameError("unsupported_feature", `${name} is not in this engine build`);
2734
+ return fn;
2735
+ }
2736
+ velocityAtPoint(body, point, out) {
2737
+ let s = this.session;
2738
+ s.flush();
2739
+ let floats = s.registerFloats;
2740
+ floats[VECTOR_OUT] = point.x, floats[VECTOR_OUT + 1] = point.y, floats[VECTOR_OUT + 2] = point.z, s.check(this.extra("engine_body_velocity_at_point")(s.require(), body), "velocity at point"), this.readVector(out);
2741
+ }
2742
+ setJointMotorPosition(joint, target, stiffness, damping) {
2743
+ let s = this.session;
2744
+ s.flush();
2745
+ let floats = s.registerFloats;
2746
+ floats[MOTOR_TARGET] = target, floats[MOTOR_STIFFNESS] = stiffness, floats[MOTOR_DAMPING] = damping, s.check(this.extra("engine_joint_motor_position")(s.require(), joint), "joint motor position");
2747
+ }
2748
+ castShape(query, out) {
2749
+ let s = this.session;
2750
+ s.flush();
2751
+ let words = s.registerWords, floats = s.registerFloats;
2752
+ words[CAST_SHAPE] = castShapeCode(query.kind), floats[CAST_PARAMS] = query.params.x, floats[CAST_PARAMS + 1] = query.params.y, floats[CAST_PARAMS + 2] = query.params.z;
2753
+ for (let k = 0; k < 4; k++) floats[CAST_ROTATION + k] = query.rotation[k];
2754
+ floats[RAY_ORIGIN] = query.origin.x, floats[RAY_ORIGIN + 1] = query.origin.y, floats[RAY_ORIGIN + 2] = query.origin.z, floats[RAY_DIRECTION] = query.direction.x, floats[RAY_DIRECTION + 1] = query.direction.y, floats[RAY_DIRECTION + 2] = query.direction.z, floats[RAY_MAX] = query.maxDistance, words[RAY_INCLUDE_SENSORS] = query.includeSensors ? 1 : 0, words[RAY_EXCLUDE] = query.excludeBody < 0 ? NO_EXCLUDE : query.excludeBody;
2755
+ let hit = s.check(this.extra("engine_shape_cast")(s.require()), "shape cast") === RAY_HIT;
2756
+ return out.hit = hit, hit ? (out.collider = words[HIT_COLLIDER], out.distance = floats[HIT_DISTANCE], out.pointX = floats[HIT_POINT], out.pointY = floats[HIT_POINT + 1], out.pointZ = floats[HIT_POINT + 2], out.normalX = floats[HIT_NORMAL], out.normalY = floats[HIT_NORMAL + 1], out.normalZ = floats[HIT_NORMAL + 2], true) : (out.collider = -1, false);
2757
+ }
2758
+ overlapSphere(x, y, z, radius, includeSensors, out) {
2759
+ let s = this.session;
2760
+ s.flush();
2761
+ let words = s.registerWords, floats = s.registerFloats;
2762
+ floats[RAY_ORIGIN] = x, floats[RAY_ORIGIN + 1] = y, floats[RAY_ORIGIN + 2] = z, floats[RAY_MAX] = radius, words[RAY_INCLUDE_SENSORS] = includeSensors ? 1 : 0, out.count = s.check(this.extra("engine_overlap_sphere")(s.require()), "sphere overlap"), out.collider = out.count > 0 ? words[HIT_COLLIDER] : -1;
2763
+ }
2764
+ pointCommand(op, body, v, p) {
2765
+ let s = this.session, o = s.command(op, body), f = s.commandPayload;
2766
+ f[o] = v.x, f[o + 1] = v.y, f[o + 2] = v.z, f[o + 3] = p.x, f[o + 4] = p.y, f[o + 5] = p.z;
2767
+ }
2768
+ resetForces(body) {
2769
+ this.session.command(OP_RESET_FORCES, body);
2770
+ }
2771
+ isSleeping(body) {
2772
+ let s = this.session;
2773
+ return s.flush(), s.check(s.exports.engine_body_sleeping(s.require(), body), "sleeping") === 1;
2774
+ }
2775
+ wake(body) {
2776
+ this.session.command(OP_WAKE, body);
2777
+ }
2778
+ batchHandle() {
2779
+ let s = this.session;
2780
+ return s.flush(), s.require();
2781
+ }
2782
+ raycast(ray, out) {
2783
+ let s = this.session;
2784
+ s.flush();
2785
+ let words = s.registerWords, floats = s.registerFloats;
2786
+ floats[RAY_ORIGIN] = ray.origin.x, floats[RAY_ORIGIN + 1] = ray.origin.y, floats[RAY_ORIGIN + 2] = ray.origin.z, floats[RAY_DIRECTION] = ray.direction.x, floats[RAY_DIRECTION + 1] = ray.direction.y, floats[RAY_DIRECTION + 2] = ray.direction.z, floats[RAY_MAX] = ray.maxDistance, words[RAY_SOLID] = ray.solid ? 1 : 0, words[RAY_INCLUDE_SENSORS] = ray.includeSensors ? 1 : 0, words[RAY_EXCLUDE] = ray.excludeCollider < 0 ? NO_EXCLUDE : ray.excludeCollider;
2787
+ let hit = s.check(s.exports.engine_raycast(s.require()), "raycast") === RAY_HIT;
2788
+ return out.hit = hit, hit ? (out.collider = words[HIT_COLLIDER], out.distance = floats[HIT_DISTANCE], out.pointX = floats[HIT_POINT], out.pointY = floats[HIT_POINT + 1], out.pointZ = floats[HIT_POINT + 2], out.normalX = floats[HIT_NORMAL], out.normalY = floats[HIT_NORMAL + 1], out.normalZ = floats[HIT_NORMAL + 2], true) : (out.collider = -1, false);
2789
+ }
2790
+ contactCount() {
2791
+ return this.session.contacts;
2792
+ }
2793
+ contactColliderA(index) {
2794
+ return this.session.contactA[index];
2795
+ }
2796
+ contactColliderB(index) {
2797
+ return this.session.contactB[index];
2798
+ }
2799
+ contactStarted(index) {
2800
+ return this.session.contactBegan[index] === 1;
2801
+ }
2802
+ createCharacterController(desc) {
2803
+ let s = this.session;
2804
+ s.flush();
2805
+ let words = s.descWords, floats = s.descFloats;
2806
+ if (words.fill(0), floats[CONTROLLER_OFFSET] = desc.offset ?? (0.01), floats[CONTROLLER_MAX_SLOPE_CLIMB] = desc.maxSlopeClimbDegrees === void 0 ? NO_VALUE : desc.maxSlopeClimbDegrees * DEGREES_TO_RADIANS, floats[CONTROLLER_MIN_SLOPE_SLIDE] = desc.minSlopeSlideDegrees === void 0 ? NO_VALUE : desc.minSlopeSlideDegrees * DEGREES_TO_RADIANS, floats[CONTROLLER_AUTOSTEP_HEIGHT] = desc.autostepMaxHeight ?? NO_VALUE, floats[CONTROLLER_AUTOSTEP_WIDTH] = desc.autostepMinWidth ?? NO_VALUE, floats[CONTROLLER_SNAP] = desc.snapToGround ?? NO_VALUE, words[CONTROLLER_SLIDE] = desc.slide === void 0 ? CONTROLLER_SLIDE_UNSET : desc.slide ? 1 : 0, desc.up) {
2807
+ words[CONTROLLER_HAS_UP] = 1;
2808
+ for (let k = 0; k < 3; k++) floats[CONTROLLER_UP + k] = desc.up[k];
2809
+ }
2810
+ return s.check(s.exports.engine_controller_create(s.require()), "create controller");
2811
+ }
2812
+ moveCharacter(controller, collider, desired, out) {
2813
+ let s = this.session;
2814
+ s.flush();
2815
+ let floats = s.registerFloats;
2816
+ floats[VECTOR_OUT] = desired.x, floats[VECTOR_OUT + 1] = desired.y, floats[VECTOR_OUT + 2] = desired.z, s.check(s.exports.engine_character_move(s.require(), controller, collider), "move character"), out.x = floats[VECTOR_OUT], out.y = floats[VECTOR_OUT + 1], out.z = floats[VECTOR_OUT + 2], out.grounded = s.registerWords[GROUNDED_OUT] === 1;
2817
+ }
2818
+ destroyCharacterController(controller) {
2819
+ let s = this.session;
2820
+ s.flush(), s.check(s.exports.engine_controller_destroy(s.require(), controller), "destroy controller");
2821
+ }
2822
+ dispose() {
2823
+ this.craft?.dispose(), this.session.close();
2824
+ }
2825
+ setColliderClass(collider, colliderClass) {
2826
+ let s = this.session, o = s.command(OP_SET_COLLIDER_CLASS, collider);
2827
+ s.commandPayloadWords[o] = checkColliderClass(colliderClass);
2828
+ }
2829
+ setContactRule(platform, other, rule) {
2830
+ let s = this.session, o = s.command(OP_SET_CONTACT_RULE, packContactRuleHeader(platform, other, rule));
2831
+ writeContactRulePayload(rule, s.commandPayload, o);
2832
+ }
2833
+ setCollisionGroups(collider, membership, filter) {
2834
+ let s = this.session, o = s.command(OP_SET_COLLIDER_GROUPS, collider);
2835
+ s.commandPayloadWords[o] = membership & (65535), s.commandPayloadWords[o + 1] = filter & (65535);
2836
+ }
2837
+ setSolver(iterations, pgsIterations, ccdSubsteps) {
2838
+ let s = this.session, o = s.command(OP_SET_SOLVER, 0);
2839
+ s.commandPayloadWords[o] = iterations, s.commandPayloadWords[o + 1] = pgsIterations, s.commandPayloadWords[o + 2] = ccdSubsteps;
2840
+ }
2841
+ setSoftCcd(body, distance) {
2842
+ let s = this.session, o = s.command(OP_SET_BODY_SOFT_CCD, body);
2843
+ s.commandPayload[o] = distance;
2844
+ }
2845
+ setSleepThresholds(body, linear2, angular, seconds) {
2846
+ let s = this.session, o = s.command(OP_SET_BODY_SLEEP, body), f = s.commandPayload;
2847
+ f[o] = linear2, f[o + 1] = angular, f[o + 2] = seconds;
2848
+ }
2849
+ vectorCommand(op, body, v) {
2850
+ let s = this.session, o = s.command(op, body), f = s.commandPayload;
2851
+ f[o] = v.x, f[o + 1] = v.y, f[o + 2] = v.z;
2852
+ }
2853
+ readVector(out) {
2854
+ let floats = this.session.registerFloats;
2855
+ out.x = floats[VECTOR_OUT], out.y = floats[VECTOR_OUT + 1], out.z = floats[VECTOR_OUT + 2];
2856
+ }
2857
+ stage(staged, data, pointerSlot, lengthSlot) {
2858
+ let s = this.session, bytes = data.length * WORD_BYTES, pointer = s.exports.engine_alloc(bytes, WORD_BYTES);
2859
+ if (pointer === (0)) throw new GameError("capacity_exceeded", "engine memory cannot hold collider data");
2860
+ staged.push({ pointer, bytes }), new Uint8Array(s.buffer, pointer, bytes).set(new Uint8Array(data.buffer, data.byteOffset, bytes)), s.descWords[pointerSlot] = pointer, s.descWords[lengthSlot] = data.length;
2861
+ }
2862
+ };
2863
+
2864
+ // src/game/backends/engine/session.ts
2865
+ var NO_WORLD2 = 0, EMPTY_WORDS = new Uint32Array(0), EMPTY_FLOATS = new Float32Array(0), EMPTY_BYTES = new Uint8Array(0);
2866
+ function failure3(code, what) {
2867
+ switch (code) {
2868
+ case ERROR_CAPACITY_EXCEEDED:
2869
+ return new GameError("capacity_exceeded", `${what}: capacity exceeded`);
2870
+ case ERROR_DEAD_ENTITY:
2871
+ return new GameError("dead_entity", `${what}: entity has no transform`);
2872
+ case ERROR_UNKNOWN_RESOURCE:
2873
+ return new GameError("unknown_resource", `${what}: unknown resource`);
2874
+ case ERROR_UNSUPPORTED:
2875
+ return new GameError("unsupported_feature", `${what}: unsupported`);
2876
+ case ERROR_INVALID_ARGUMENT:
2877
+ default:
2878
+ return new GameError("invalid_argument", `${what}: invalid argument`);
2879
+ }
2880
+ }
2881
+ var EngineSession = class {
2882
+ constructor(runtime, memory) {
2883
+ this.world = (0);
2884
+ this.registerWords = EMPTY_WORDS;
2885
+ this.registerFloats = EMPTY_FLOATS;
2886
+ this.descWords = EMPTY_WORDS;
2887
+ this.descFloats = EMPTY_FLOATS;
2888
+ this.contactA = EMPTY_WORDS;
2889
+ this.contactB = EMPTY_WORDS;
2890
+ this.contactBegan = EMPTY_BYTES;
2891
+ this.contacts = 0;
2892
+ this.snapshots = null;
2893
+ this.commandWords = EMPTY_WORDS;
2894
+ this.commandFloats = EMPTY_FLOATS;
2895
+ this.commandCapacity = 0;
2896
+ this.pending = 0;
2897
+ this.columns = null;
2898
+ this.runtime = runtime, this.exports = runtime.exports, this.memory = memory;
2899
+ }
2900
+ bind(columns) {
2901
+ for (let array of [columns.position, columns.rotation, columns.render, columns.parent, columns.entities, columns.sparse])
2902
+ if (!this.memory.owns(array)) throw new GameError("invalid_argument", "engine transforms must live in engine memory");
2903
+ this.columns = columns, this.world !== (0) && this.bindLayout(columns);
2904
+ }
2905
+ open(desc) {
2906
+ if (this.world !== (0)) throw new GameError("invalid_argument", "engine world is already open");
2907
+ let scratch = this.memory.allocate("u32", DESC_WORDS), floats = new Float32Array(scratch.buffer, scratch.byteOffset, DESC_WORDS), g = desc.gravity ?? [0, -9.81, 0];
2908
+ floats[WORLD_GRAVITY] = g[0], floats[WORLD_GRAVITY + 1] = g[1], floats[WORLD_GRAVITY + 2] = g[2], floats[WORLD_STEP_SECONDS] = desc.stepSeconds, scratch[WORLD_MAX_BODIES] = desc.maxBodies ?? 2048, scratch[WORLD_MAX_COLLIDERS] = desc.maxColliders ?? 4096, scratch[WORLD_MAX_JOINTS] = desc.maxJoints ?? 1024, scratch[WORLD_MAX_CONTACTS] = desc.maxContactEvents ?? 1024, scratch[WORLD_MAX_CONTROLLERS] = desc.maxCharacterControllers ?? 64, scratch[WORLD_MAX_COMMANDS] = DEFAULT_MAX_COMMANDS;
2909
+ let world = desc.rollback === void 0 ? this.exports.engine_world_create(scratch.byteOffset) : this.createRollback(scratch, desc.rollback);
2910
+ if (world === (0)) throw engineSessionFailure(this.runtime.symbols) ?? new GameError("capacity_exceeded", "engine world could not be created");
2911
+ this.world = world, this.snapshots = desc.rollback === void 0 ? null : WorldSnapshots.bind(this.runtime.symbols, this.runtime.memory, world, () => this.discard(), desc.rollback.frames ?? DEFAULT_ROLLBACK_FRAMES), noteInspectorWorld(world);
2912
+ let buffer = this.runtime.memory.buffer, registers = this.exports.engine_world_registers(world);
2913
+ this.registerWords = new Uint32Array(buffer, registers, REGISTER_WORDS), this.registerFloats = new Float32Array(buffer, registers, REGISTER_WORDS);
2914
+ let descPointer = this.exports.engine_world_desc(world);
2915
+ this.descWords = new Uint32Array(buffer, descPointer, DESC_WORDS), this.descFloats = new Float32Array(buffer, descPointer, DESC_WORDS), this.commandCapacity = DEFAULT_MAX_COMMANDS;
2916
+ let commandBuffer = hasPhysics(this.runtime.symbols) ? buffer : new ArrayBuffer(DEFAULT_MAX_COMMANDS * COMMAND_WORDS * WORD_BYTES), commands = commandBuffer === buffer ? this.exports.engine_world_commands(world) : 0;
2917
+ this.commandWords = new Uint32Array(commandBuffer, commands, DEFAULT_MAX_COMMANDS * COMMAND_WORDS), this.commandFloats = new Float32Array(commandBuffer, commands, DEFAULT_MAX_COMMANDS * COMMAND_WORDS);
2918
+ let maxContacts = scratch[WORLD_MAX_CONTACTS];
2919
+ this.contactA = new Uint32Array(buffer, this.exports.engine_contacts_a(world), maxContacts), this.contactB = new Uint32Array(buffer, this.exports.engine_contacts_b(world), maxContacts), this.contactBegan = new Uint8Array(buffer, this.exports.engine_contacts_started(world), maxContacts), this.columns && this.bindLayout(this.columns);
2920
+ }
2921
+ createRollback(desc, rollback) {
2922
+ let symbols = this.runtime.symbols;
2923
+ if (!hasRollback(symbols)) throw new GameError("unsupported_feature", "this engine has no client rollback (feature rollback_1)");
2924
+ let config = this.memory.allocate("u32", ROLLBACK_CONFIG_WORDS);
2925
+ writeRollbackConfig(config, rollback);
2926
+ let create = symbols.engine_world_rollback_create;
2927
+ return create(desc.byteOffset, config.byteOffset);
2928
+ }
2929
+ require() {
2930
+ if (this.world === (0)) throw new GameError("not_initialized", "engine physics is not initialised");
2931
+ return this.world;
2932
+ }
2933
+ check(code, what) {
2934
+ if (!(code >= 0)) throw failure3(code, what);
2935
+ return code;
2936
+ }
2937
+ command(op, body) {
2938
+ this.pending === this.commandCapacity && this.flush();
2939
+ let o = this.pending * COMMAND_WORDS;
2940
+ return this.commandWords[o + COMMAND_OP] = op, this.commandWords[o + COMMAND_BODY] = body, this.pending++, o + COMMAND_PAYLOAD;
2941
+ }
2942
+ get commandPayload() {
2943
+ return this.commandFloats;
2944
+ }
2945
+ get commandPayloadWords() {
2946
+ return this.commandWords;
2947
+ }
2948
+ get symbols() {
2949
+ return this.runtime.symbols;
2950
+ }
2951
+ get buffer() {
2952
+ return this.runtime.memory.buffer;
2953
+ }
2954
+ discard() {
2955
+ this.pending = 0;
2956
+ }
2957
+ flush() {
2958
+ if (this.pending === 0) return;
2959
+ let count = this.pending;
2960
+ this.pending = 0, this.check(this.exports.engine_apply_commands(this.require(), count), "command");
2961
+ }
2962
+ step() {
2963
+ requireEngineMemoryHeld(this.runtime.memory);
2964
+ let count = this.pending;
2965
+ this.pending = 0, this.check(this.exports.engine_step(this.require(), count), "step"), this.contacts = this.exports.engine_contact_count(this.world);
2966
+ }
2967
+ close() {
2968
+ this.world !== (0) && (noteInspectorWorld((0)), this.exports.engine_world_destroy(this.world)), this.world = (0), this.snapshots = null, this.pending = 0, this.columns = null, this.memory.release(), releaseEngineArena(this.runtime.symbols);
2969
+ }
2970
+ bindLayout(columns) {
2971
+ let words = this.descWords;
2972
+ words[LAYOUT_POSITION] = columns.position.byteOffset, words[LAYOUT_ROTATION] = columns.rotation.byteOffset, words[LAYOUT_SCALE] = columns.scale.byteOffset, words[LAYOUT_PREVIOUS_POSITION] = columns.previousPosition.byteOffset, words[LAYOUT_PREVIOUS_ROTATION] = columns.previousRotation.byteOffset, words[LAYOUT_PREVIOUS_SCALE] = columns.previousScale.byteOffset, words[LAYOUT_PARENT] = columns.parent.byteOffset, words[LAYOUT_RENDER] = columns.render.byteOffset, words[LAYOUT_ENTITIES] = columns.entities.byteOffset, words[LAYOUT_SPARSE] = columns.sparse.byteOffset, words[LAYOUT_CAPACITY] = columns.capacity, words[LAYOUT_SPARSE_LEN] = columns.sparse.byteLength / WORD_BYTES, this.check(this.exports.engine_bind_transforms(this.world), "bind transforms");
2973
+ }
2974
+ };
2975
+
2976
+ // src/game/backends/engine/transforms.ts
2977
+ var EngineTransforms = class {
2978
+ constructor(session) {
2979
+ this.session = session;
2980
+ }
2981
+ bind(columns) {
2982
+ this.session.bind(columns);
2983
+ }
2984
+ snapshot(count) {
2985
+ let s = this.session;
2986
+ s.check(s.exports.engine_snapshot(s.require(), count), "snapshot");
2987
+ }
2988
+ computeRender(count, time, version) {
2989
+ let s = this.session, world = s.require();
2990
+ s.registerFloats[REGISTER_FRAME_ALPHA] = time.values[FRAME_ALPHA_SLOT], s.registerWords[REGISTER_FRAME_VERSION_LOW] = version >>> 0, s.registerWords[REGISTER_FRAME_VERSION_HIGH] = Math.floor(version / U32_RANGE), s.check(s.exports.engine_compute_render(world, count), "compute render");
2991
+ }
2992
+ };
2993
+
2994
+ // src/game/backends/engine/signatures.ts
2995
+ var ARITY_EXPORT = "engine_export_arity", PROTOTYPE_EXPORT = "engine_export_prototype_of", NAME_ALIGN = 8, NAME_CAPACITY = 64, NULL = 0, NO_PROTOTYPE = 0;
2996
+ function nativeByName(runtime, query) {
2997
+ let scratch = runtime.exports.engine_alloc((64), (8));
2998
+ if (scratch === (0)) throw new GameError("capacity_exceeded", "engine memory cannot hold an export name");
2999
+ return (name) => {
3000
+ let bytes = new Uint8Array(runtime.memory.buffer, scratch, (64));
3001
+ for (let i = 0; i < name.length; i++) bytes[i] = name.charCodeAt(i);
3002
+ return query(scratch, name.length);
3003
+ };
3004
+ }
3005
+ function engineArity(runtime) {
3006
+ let symbols = runtime.symbols, native = symbols[ARITY_EXPORT];
3007
+ return typeof native == "function" ? nativeByName(runtime, native) : (name) => {
3008
+ let fn = symbols[name];
3009
+ return typeof fn == "function" ? fn.length : -1;
3010
+ };
3011
+ }
3012
+ function enginePrototype(runtime) {
3013
+ let native = runtime.symbols[PROTOTYPE_EXPORT];
3014
+ return typeof native == "function" ? nativeByName(runtime, native) : null;
3015
+ }
3016
+ function engineSignatureMismatches(symbols, arity, prototype = null) {
3017
+ let mismatches = [];
3018
+ for (let name in ENGINE_EXPORT_ARITY) {
3019
+ if (typeof symbols[name] != "function") continue;
3020
+ let expected = ENGINE_EXPORT_ARITY[name], actual = arity(name);
3021
+ if (actual !== expected) {
3022
+ mismatches.push(`${name} takes ${actual < 0 ? "an unknown number of" : actual} arguments, this package expects ${expected}`);
3023
+ continue;
3024
+ }
3025
+ let advertised = prototype?.(name) ?? (0);
3026
+ advertised !== (0) && advertised !== ENGINE_EXPORT_PROTOTYPES[name] && mismatches.push(`${name} has another prototype than this package expects`);
3027
+ }
3028
+ return mismatches;
3029
+ }
3030
+ function verifyEngineSignatures(runtime) {
3031
+ let mismatches = engineSignatureMismatches(runtime.symbols, engineArity(runtime), enginePrototype(runtime));
3032
+ if (mismatches.length > 0)
3033
+ throw new GameError(
3034
+ "engine_mismatch",
3035
+ `this package was built for a different engine; rebuild it or update the app (${mismatches.length} exports differ: ${mismatches.slice(0, 3).join("; ")})`
3036
+ );
3037
+ }
3038
+
3039
+ // src/game/backends/engine/native.ts
3040
+ var ENGINE_BACKEND_NAME = "cimplify-engine", ENGINE_BACKEND_VERSION = "engine_core@0.1.0+rapier3d@0.36.0+three@0.186.1";
3041
+ function engineAudio(options, runtime) {
3042
+ let native = runtime ? nativeAudio(runtime, options.assets ?? null) : null;
3043
+ if (native) return native;
3044
+ let assets = options.assets ?? null, explicit = runtime && options.audioWorklet ? workletAudio(runtime, options.audioWorklet, assets) : null;
3045
+ if (explicit) return explicit;
3046
+ if (options.audio) return options.audio;
3047
+ let context = options.audioContext ?? runtime?.audioContext?.() ?? null, chosen = options.audioWorklet === null ? null : defaultWorklet(runtime, context), worklet = runtime && chosen ? workletAudio(runtime, chosen, assets) : null;
3048
+ return worklet || (context ? new WebAudioPort(context) : new HeadlessAudio());
3049
+ }
3050
+ function defaultWorklet(runtime, context) {
3051
+ let module = runtime?.audioWorklet ?? null, worklets = context?.audioWorklet;
3052
+ return context === null || module === null || typeof worklets?.addModule != "function" ? null : { context, module };
3053
+ }
3054
+ function engineHost(runtime) {
3055
+ return {
3056
+ exports: runtime.symbols,
3057
+ memory: runtime.memory,
3058
+ allocate: (bytes) => runtime.exports.engine_alloc(bytes, COLUMN_ALIGN),
3059
+ release: (pointer, bytes) => runtime.exports.engine_free(pointer, bytes, COLUMN_ALIGN)
3060
+ };
3061
+ }
3062
+ function workletAudio(runtime, options, assets) {
3063
+ let symbols = runtime.symbols;
3064
+ if ([...ENGINE_AUDIO_EXPORT_NAMES.filter((name) => name !== "engine_audio_bound"), ...ENGINE_AUDIO_WORKLET_EXPORTS].some((name) => typeof symbols[name] != "function")) return null;
3065
+ let host = engineHost(runtime), relay = WorkletAudio.create(host, options);
3066
+ return new EngineAudioPort({ ...host, decode: runtime.decodeAudio ?? null, assets, handle: relay.handle, relay });
3067
+ }
3068
+ function nativeAudio(runtime, assets) {
3069
+ let symbols = runtime.symbols;
3070
+ if (ENGINE_AUDIO_EXPORT_NAMES.some((name) => typeof symbols[name] != "function")) return null;
3071
+ let exports = symbols;
3072
+ return exports.engine_audio_bound() === 0 ? null : new EngineAudioPort({
3073
+ exports,
3074
+ memory: runtime.memory,
3075
+ allocate: (bytes) => runtime.exports.engine_alloc(bytes, COLUMN_ALIGN),
3076
+ release: (pointer, bytes) => runtime.exports.engine_free(pointer, bytes, COLUMN_ALIGN),
3077
+ decode: runtime.decodeAudio ?? null,
3078
+ assets
3079
+ });
3080
+ }
3081
+ function assembleEngineBackend(runtime, graphics, audio) {
3082
+ verifyEngineSignatures(runtime);
3083
+ let memory = new EngineMemory(runtime), session = new EngineSession(runtime, memory), port = graphics(runtime), physics = new EnginePhysics(session);
3084
+ return port instanceof EngineGraphics && physics.craft?.bindRender?.(() => port.renderHandle), audio instanceof EngineAudioPort && audio.bindOcclusionWorld(() => session.world), useTransformEngine(bindTransformEngine(runtime.symbols, runtime.memory)), {
3085
+ name: ENGINE_BACKEND_NAME,
3086
+ version: ENGINE_BACKEND_VERSION,
3087
+ memory,
3088
+ transforms: new EngineTransforms(session),
3089
+ physics,
3090
+ graphics: port,
3091
+ audio,
3092
+ nav: engineNav(runtime),
3093
+ ai: engineAi(runtime, () => session.world),
3094
+ streaming: engineStreaming(runtime, port),
3095
+ scenery: engineScenery(runtime, port),
3096
+ terrain: engineTerrain(runtime, port, () => session.world),
3097
+ soa: bindSoaEngine(runtime.symbols, runtime.memory),
3098
+ kernels: bindKernelEngine(runtime.symbols, runtime.memory),
3099
+ chemistry: bindChemistryEngine(runtime.symbols, runtime.memory),
3100
+ fluids: engineFluids(runtime, port),
3101
+ destruction: engineDestruction(runtime, () => session.world),
3102
+ softBodies: engineSoftBodies(runtime, port, () => session.world),
3103
+ reactive: engineReactive(runtime, port),
3104
+ cloths: engineCloths(runtime, port, () => session.world),
3105
+ smoke: engineSmoke(runtime, port),
3106
+ story: engineStory(runtime)
3107
+ };
3108
+ }
3109
+ function engineStory(runtime) {
3110
+ let exports = engineStoryExports(runtime);
3111
+ return exports !== null ? new EngineStory(runtime, exports) : null;
3112
+ }
3113
+ function engineSmoke(runtime, port) {
3114
+ let exports = engineSmokeExports(runtime);
3115
+ return exports !== null && port instanceof EngineGraphics ? new EngineSmoke(runtime, exports, () => port.renderHandle) : null;
3116
+ }
3117
+ function engineCloths(runtime, port, world) {
3118
+ let exports = engineClothExports(runtime);
3119
+ if (exports === null) return null;
3120
+ let render = port instanceof EngineGraphics ? () => port.renderHandle : () => 0;
3121
+ return new EngineCloths(runtime, exports, render, world);
3122
+ }
3123
+ function engineReactive(runtime, port) {
3124
+ let exports = engineReactiveExports(runtime);
3125
+ if (exports === null) return null;
3126
+ let render = port instanceof EngineGraphics ? () => port.renderHandle : () => 0;
3127
+ return new EngineReactive(runtime, exports, render);
3128
+ }
3129
+ function engineSoftBodies(runtime, port, world) {
3130
+ let exports = engineSoftBodyExports(runtime);
3131
+ if (exports === null) return null;
3132
+ let render = port instanceof EngineGraphics ? () => port.renderHandle : () => 0;
3133
+ return new EngineSoftBodies(runtime, exports, render, world);
3134
+ }
3135
+ function engineFluids(runtime, port) {
3136
+ let exports = engineFluidExports(runtime);
3137
+ return exports !== null && port instanceof EngineGraphics ? new EngineFluids(runtime, exports, () => port.renderHandle) : null;
3138
+ }
3139
+ function engineDestruction(runtime, world) {
3140
+ let exports = engineDestructionExports(runtime);
3141
+ return exports !== null ? new EngineDestruction(runtime, exports, world) : null;
3142
+ }
3143
+ function engineTerrain(runtime, port, world) {
3144
+ let exports = engineTerrainExports(runtime);
3145
+ return exports !== null && port instanceof EngineGraphics ? new EngineTerrain(runtime, exports, () => port.renderHandle, world) : null;
3146
+ }
3147
+ function engineStreaming(runtime, port) {
3148
+ let exports = engineStreamExports(runtime);
3149
+ return exports !== null && port instanceof EngineGraphics ? new EngineWorldStreaming(runtime, exports, () => port.renderHandle) : null;
3150
+ }
3151
+ function engineScenery(runtime, port) {
3152
+ let exports = engineSplatExports(runtime);
3153
+ return exports !== null && port instanceof EngineGraphics ? new EngineScenery(runtime, exports, () => port.renderHandle) : null;
3154
+ }
3155
+ function engineNav(runtime) {
3156
+ let exports = engineNavExports(runtime.symbols);
3157
+ return exports ? new EngineNav(runtime, exports) : null;
3158
+ }
3159
+ function createNativeEngineBackend(runtime, options = {}) {
3160
+ let attach = options.attach ?? null;
3161
+ return assembleEngineBackend(runtime, (r) => new EngineGraphics(r, void 0, attach, options.graphics), engineAudio(options, runtime));
3162
+ }
3163
+
3164
+ export { ENGINE_BACKEND_NAME, ENGINE_BACKEND_VERSION, EngineGraphics, assembleEngineBackend, createNativeEngineBackend, engineAudio };