@holoscript/core 7.0.0 → 8.0.1

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 (350) hide show
  1. package/README.md +4 -4
  2. package/bin/holoscript.cjs +3 -0
  3. package/dist/GLTFPipeline-N6B6PJ6G.cjs +38 -0
  4. package/dist/GLTFPipeline-P3WMNYCN.js +17 -0
  5. package/dist/HoloScriptPlusParser-7FBIFUFC.js +693 -0
  6. package/dist/HoloScriptPlusParser-A2W7OCN2.cjs +698 -0
  7. package/dist/HoloScriptPlusParser-F2Z56FJR.js +10 -0
  8. package/dist/HoloScriptPlusParser-WKHRIH6T.cjs +27 -0
  9. package/dist/HoloScriptRuntime-CBYJX3LZ.js +10 -0
  10. package/dist/HoloScriptRuntime-VJ374RER.cjs +19 -0
  11. package/dist/USDZExporter-3FWJ25JI.cjs +1037 -0
  12. package/dist/USDZExporter-D2HQLQYK.js +1035 -0
  13. package/dist/agents/index.cjs +19 -0
  14. package/dist/agents/index.d.ts +100 -0
  15. package/dist/agents/index.js +17 -0
  16. package/dist/chunk-2BSMSUCE.js +1941 -0
  17. package/dist/chunk-2IWC4FP7.cjs +1189 -0
  18. package/dist/chunk-2M2DPHKB.js +762 -0
  19. package/dist/chunk-2X7NGX3M.js +2426 -0
  20. package/dist/chunk-2YSNA2F2.cjs +1274 -0
  21. package/dist/chunk-3FOKASKO.cjs +348 -0
  22. package/dist/chunk-3WZEJHUQ.cjs +116 -0
  23. package/dist/chunk-4C57PR42.js +468 -0
  24. package/dist/chunk-4GU5GCIY.js +1384 -0
  25. package/dist/chunk-4N4SXXWF.js +769 -0
  26. package/dist/chunk-4PDEPEQW.cjs +41 -0
  27. package/dist/chunk-4R6SBXDB.js +45 -0
  28. package/dist/chunk-4SDKXQ4C.js +811 -0
  29. package/dist/chunk-4V2E7U7Q.cjs +2015 -0
  30. package/dist/chunk-5FSKKMR7.cjs +2092 -0
  31. package/dist/chunk-5GLCTO44.js +161 -0
  32. package/dist/chunk-5H2G27PK.cjs +627 -0
  33. package/dist/chunk-5JEU52DW.js +382 -0
  34. package/dist/chunk-5NWINHR5.cjs +689 -0
  35. package/dist/chunk-5S7RKFGR.cjs +446 -0
  36. package/dist/chunk-5WUNN6ZN.cjs +428 -0
  37. package/dist/chunk-6CTRH7HT.cjs +1985 -0
  38. package/dist/chunk-6EX3I5P4.cjs +130 -0
  39. package/dist/chunk-6Q7RC2MK.cjs +1418 -0
  40. package/dist/chunk-7H33U5SM.cjs +413 -0
  41. package/dist/chunk-7M3PNU2M.cjs +672 -0
  42. package/dist/chunk-7T25IEZ2.js +449 -0
  43. package/dist/chunk-7V4JI5TB.cjs +6947 -0
  44. package/dist/chunk-A6KINLZJ.js +236 -0
  45. package/dist/chunk-ADADVMXY.js +404 -0
  46. package/dist/chunk-AIA52I7T.cjs +543 -0
  47. package/dist/chunk-ALC6K7GL.cjs +4402 -0
  48. package/dist/chunk-ANXZFVY2.js +113 -0
  49. package/dist/chunk-AOVGZ25K.cjs +56583 -0
  50. package/dist/chunk-AVJHHUC5.cjs +718 -0
  51. package/dist/chunk-BGY3SDG3.js +4396 -0
  52. package/dist/chunk-BOVPWH4H.js +3857 -0
  53. package/dist/chunk-BRQJKJGT.cjs +20 -0
  54. package/dist/chunk-C37BHB7N.cjs +636 -0
  55. package/dist/chunk-CBJY23VL.js +126 -0
  56. package/dist/chunk-CCATWPXM.js +778 -0
  57. package/dist/chunk-CIWWXYHZ.cjs +50 -0
  58. package/dist/chunk-CMT5NMMS.js +669 -0
  59. package/dist/chunk-CR4FMIWL.cjs +1049 -0
  60. package/dist/chunk-CR7XRXRN.cjs +639 -0
  61. package/dist/chunk-CSD27UNQ.js +2176 -0
  62. package/dist/chunk-D3STJ56J.js +714 -0
  63. package/dist/chunk-DAJXW4KX.js +725 -0
  64. package/dist/chunk-DHO2YRIM.js +756 -0
  65. package/dist/chunk-DTGBOSEM.cjs +319 -0
  66. package/dist/chunk-E6XXE66V.js +2252 -0
  67. package/dist/chunk-E7JP3BS3.cjs +61 -0
  68. package/dist/chunk-EKBKLK7P.js +1169 -0
  69. package/dist/chunk-EKYL4PE3.cjs +404 -0
  70. package/dist/chunk-EXKSFGSX.cjs +274 -0
  71. package/dist/chunk-EXUP2BUM.cjs +1173 -0
  72. package/dist/chunk-FDSGHPAK.js +130 -0
  73. package/dist/chunk-FEWUHQNM.cjs +144 -0
  74. package/dist/chunk-FFAOS5HQ.js +70 -0
  75. package/dist/chunk-FGGJQRLZ.js +270 -0
  76. package/dist/chunk-FHP6LXJS.js +415 -0
  77. package/dist/chunk-FJPADH77.cjs +666 -0
  78. package/dist/chunk-FL33V6U7.js +421 -0
  79. package/dist/chunk-FYSPZT4V.cjs +169 -0
  80. package/dist/chunk-GIOYPNTH.js +5575 -0
  81. package/dist/chunk-GJNCFRJU.cjs +125 -0
  82. package/dist/chunk-GMP623FG.cjs +1508 -0
  83. package/dist/chunk-GQHQOPXZ.cjs +5580 -0
  84. package/dist/chunk-GTU2Z2WW.cjs +262 -0
  85. package/dist/chunk-GYZE55MO.js +2007 -0
  86. package/dist/chunk-GZG4KA4E.js +529 -0
  87. package/dist/chunk-H652NHX5.js +600 -0
  88. package/dist/chunk-HCCQLAA4.cjs +74 -0
  89. package/dist/chunk-HKEXJUWS.cjs +4007 -0
  90. package/dist/chunk-HNDK4IQU.cjs +5737 -0
  91. package/dist/chunk-HR2OSYVQ.js +56165 -0
  92. package/dist/chunk-HYNTS5CP.js +422 -0
  93. package/dist/chunk-I6XZ5DZF.cjs +488 -0
  94. package/dist/chunk-ILRBGFVD.cjs +72 -0
  95. package/dist/chunk-IUDGEUDO.cjs +1409 -0
  96. package/dist/chunk-IUTY5WQ2.cjs +424 -0
  97. package/dist/chunk-IVY74O6C.js +247 -0
  98. package/dist/chunk-IWC5DM2M.cjs +611 -0
  99. package/dist/chunk-J32ZJZJH.js +554 -0
  100. package/dist/chunk-J52VSAQ7.js +6884 -0
  101. package/dist/chunk-J6M4FPK5.js +421 -0
  102. package/dist/chunk-J7XZV333.js +844 -0
  103. package/dist/chunk-JBNDTXXV.cjs +2433 -0
  104. package/dist/chunk-JC5YBPSF.cjs +984 -0
  105. package/dist/chunk-JD7CIZ33.js +1949 -0
  106. package/dist/chunk-JIBL5LRK.js +4287 -0
  107. package/dist/chunk-JIYN45TV.cjs +2525 -0
  108. package/dist/chunk-K574J76X.cjs +457 -0
  109. package/dist/chunk-KHDZJE5D.cjs +2196 -0
  110. package/dist/chunk-KKFZ3B6J.cjs +557 -0
  111. package/dist/chunk-KKP7JKN4.cjs +6002 -0
  112. package/dist/chunk-KPJL34Y7.cjs +186 -0
  113. package/dist/chunk-KQCN6AKJ.cjs +3042 -0
  114. package/dist/chunk-L5LKKENW.cjs +424 -0
  115. package/dist/chunk-LHAXPADA.js +882 -0
  116. package/dist/chunk-LM2VU56C.cjs +37 -0
  117. package/dist/chunk-M56JSP4A.js +400 -0
  118. package/dist/chunk-MBOOR7X4.js +18 -0
  119. package/dist/chunk-MQWAT42R.cjs +4310 -0
  120. package/dist/chunk-MXFUTKCO.js +56 -0
  121. package/dist/chunk-MYY4PMWX.cjs +264 -0
  122. package/dist/chunk-N75IH2HY.js +258 -0
  123. package/dist/chunk-NCWCUZNS.cjs +72 -0
  124. package/dist/chunk-NG77ATEW.cjs +778 -0
  125. package/dist/chunk-NW5G5FBQ.js +215 -0
  126. package/dist/chunk-OBIYPYYS.cjs +1993 -0
  127. package/dist/chunk-OH2FAIVU.js +608 -0
  128. package/dist/chunk-OIQYIIO3.cjs +473 -0
  129. package/dist/chunk-OL46QLBJ.js +61 -0
  130. package/dist/chunk-OMXII44L.js +5386 -0
  131. package/dist/chunk-OSYNRVOV.cjs +243 -0
  132. package/dist/chunk-PGANYCAG.cjs +220 -0
  133. package/dist/chunk-PHENW4MQ.js +65 -0
  134. package/dist/chunk-PY37LNDP.js +686 -0
  135. package/dist/chunk-Q56TT7IL.js +483 -0
  136. package/dist/chunk-QD32ADK6.js +1046 -0
  137. package/dist/chunk-QPOQ7VPI.js +1491 -0
  138. package/dist/chunk-QPSKHBJP.js +5963 -0
  139. package/dist/chunk-QXH7QDSZ.js +1989 -0
  140. package/dist/chunk-R24NNAEG.js +1399 -0
  141. package/dist/chunk-R75BSDH7.cjs +50 -0
  142. package/dist/chunk-RARB3MBR.js +207 -0
  143. package/dist/chunk-ROHLEP2W.cjs +847 -0
  144. package/dist/chunk-S3MDHNKB.cjs +490 -0
  145. package/dist/chunk-S6YWHCKV.cjs +410 -0
  146. package/dist/chunk-SIEXCILW.js +229 -0
  147. package/dist/chunk-SLU6UPJI.cjs +410 -0
  148. package/dist/chunk-SMIWS6DE.cjs +212 -0
  149. package/dist/chunk-T5J7ZKP3.cjs +4885 -0
  150. package/dist/chunk-TDCNJHWO.js +341 -0
  151. package/dist/chunk-TG7O4WBC.js +406 -0
  152. package/dist/chunk-THCK6ECW.js +2085 -0
  153. package/dist/chunk-TJHVSBP2.js +439 -0
  154. package/dist/chunk-TVHSPJ4N.cjs +606 -0
  155. package/dist/chunk-TWUXUCEW.cjs +781 -0
  156. package/dist/chunk-U44IKGG7.cjs +5390 -0
  157. package/dist/chunk-UFZZ7TSN.cjs +886 -0
  158. package/dist/chunk-UJXISJBN.js +487 -0
  159. package/dist/chunk-UOIGFQXC.cjs +9750 -0
  160. package/dist/chunk-URG2SJLK.js +2521 -0
  161. package/dist/chunk-UWJHCOH2.js +623 -0
  162. package/dist/chunk-V6MKC2FZ.js +979 -0
  163. package/dist/chunk-VJ3L7CHT.cjs +169 -0
  164. package/dist/chunk-VMLKSV26.js +1216 -0
  165. package/dist/chunk-VVKVQZI6.js +55 -0
  166. package/dist/chunk-W6RW64BB.cjs +1219 -0
  167. package/dist/chunk-WKX5AMOY.js +309 -0
  168. package/dist/chunk-WNNE3PO3.js +34 -0
  169. package/dist/chunk-WRKUDAZJ.js +3038 -0
  170. package/dist/chunk-WRLUBRKS.cjs +1943 -0
  171. package/dist/chunk-WRNEH5MO.js +3169 -0
  172. package/dist/chunk-WRWEX5ZF.js +658 -0
  173. package/dist/chunk-X3GJPRVK.cjs +3246 -0
  174. package/dist/chunk-X3UVCWNL.cjs +2257 -0
  175. package/dist/chunk-XB274MW5.cjs +814 -0
  176. package/dist/chunk-XHIV6326.cjs +793 -0
  177. package/dist/chunk-XIVIE43A.cjs +729 -0
  178. package/dist/chunk-XJAN7CZG.cjs +432 -0
  179. package/dist/chunk-XKTPFXGA.js +164 -0
  180. package/dist/chunk-XL6INWKT.js +121 -0
  181. package/dist/chunk-XSFNHP2E.js +632 -0
  182. package/dist/chunk-XT6JY5W5.js +9684 -0
  183. package/dist/chunk-XUILI4KB.cjs +430 -0
  184. package/dist/chunk-YF2I3MV3.js +46 -0
  185. package/dist/chunk-YIMN575O.js +4847 -0
  186. package/dist/chunk-YIVFJNYV.js +176 -0
  187. package/dist/chunk-YKGPCZEE.cjs +237 -0
  188. package/dist/chunk-YN2YWTXW.js +5731 -0
  189. package/dist/chunk-YN6V7R3L.cjs +327 -0
  190. package/dist/chunk-YQELFNJV.js +39 -0
  191. package/dist/chunk-YVD3CSO3.js +1183 -0
  192. package/dist/chunk-YVOAF4ML.js +623 -0
  193. package/dist/chunk-YWOBW2PV.cjs +759 -0
  194. package/dist/chunk-YYXH45E2.js +426 -0
  195. package/dist/chunk-ZDSYWBIE.cjs +69 -0
  196. package/dist/chunk-ZU7NIRT6.js +325 -0
  197. package/dist/chunk-ZZ7RO2UQ.js +1243 -0
  198. package/dist/cli/holoscript-runner.cjs +2255 -0
  199. package/dist/cli/holoscript-runner.js +2230 -0
  200. package/dist/codebase/index.cjs +336 -0
  201. package/dist/codebase/index.js +331 -0
  202. package/dist/compiler/agent-inference.cjs +31 -0
  203. package/dist/compiler/agent-inference.js +8 -0
  204. package/dist/compiler/android-xr.cjs +24 -0
  205. package/dist/compiler/android-xr.js +14 -0
  206. package/dist/compiler/android.cjs +24 -0
  207. package/dist/compiler/android.js +14 -0
  208. package/dist/compiler/ar.cjs +23 -0
  209. package/dist/compiler/ar.js +11 -0
  210. package/dist/compiler/babylon.cjs +21 -0
  211. package/dist/compiler/babylon.js +15 -0
  212. package/dist/compiler/business-quest.cjs +43 -0
  213. package/dist/compiler/business-quest.js +4 -0
  214. package/dist/compiler/coco.cjs +27 -0
  215. package/dist/compiler/coco.js +4 -0
  216. package/dist/compiler/context.cjs +25 -0
  217. package/dist/compiler/context.d.ts +28 -0
  218. package/dist/compiler/context.js +8 -0
  219. package/dist/compiler/domain-block-utils.cjs +609 -0
  220. package/dist/compiler/domain-block-utils.js +11 -0
  221. package/dist/compiler/dtdl.cjs +27 -0
  222. package/dist/compiler/dtdl.js +11 -0
  223. package/dist/compiler/gltf-pipeline.cjs +39 -0
  224. package/dist/compiler/gltf-pipeline.js +4 -0
  225. package/dist/compiler/godot.cjs +18 -0
  226. package/dist/compiler/godot.js +12 -0
  227. package/dist/compiler/incremental.cjs +34 -0
  228. package/dist/compiler/incremental.js +9 -0
  229. package/dist/compiler/index.cjs +5408 -0
  230. package/dist/compiler/index.d.ts +334 -21
  231. package/dist/compiler/index.js +5069 -0
  232. package/dist/compiler/ios.cjs +23 -0
  233. package/dist/compiler/ios.js +13 -0
  234. package/dist/compiler/llm-provider-capabilities.cjs +25 -0
  235. package/dist/compiler/llm-provider-capabilities.d.ts +43 -0
  236. package/dist/compiler/llm-provider-capabilities.js +8 -0
  237. package/dist/compiler/multi-layer.cjs +24 -0
  238. package/dist/compiler/multi-layer.js +15 -0
  239. package/dist/compiler/nodetoy.cjs +23 -0
  240. package/dist/compiler/nodetoy.d.ts +69 -0
  241. package/dist/compiler/nodetoy.js +4 -0
  242. package/dist/compiler/openxr.cjs +19 -0
  243. package/dist/compiler/openxr.js +13 -0
  244. package/dist/compiler/playcanvas.cjs +19 -0
  245. package/dist/compiler/playcanvas.js +13 -0
  246. package/dist/compiler/r3f.cjs +39 -0
  247. package/dist/compiler/r3f.d.ts +22 -0
  248. package/dist/compiler/r3f.js +17 -0
  249. package/dist/compiler/remotion.cjs +23 -0
  250. package/dist/compiler/remotion.js +4 -0
  251. package/dist/compiler/reproducibility.cjs +39 -0
  252. package/dist/compiler/reproducibility.js +4 -0
  253. package/dist/compiler/sdf.cjs +24 -0
  254. package/dist/compiler/sdf.js +12 -0
  255. package/dist/compiler/semantic-scene.cjs +31 -0
  256. package/dist/compiler/semantic-scene.js +4 -0
  257. package/dist/compiler/state.cjs +21 -0
  258. package/dist/compiler/state.js +11 -0
  259. package/dist/compiler/trait-composition.cjs +30 -0
  260. package/dist/compiler/trait-composition.js +9 -0
  261. package/dist/compiler/unity.cjs +19 -0
  262. package/dist/compiler/unity.js +13 -0
  263. package/dist/compiler/unreal.cjs +23 -0
  264. package/dist/compiler/unreal.js +13 -0
  265. package/dist/compiler/urdf.cjs +52 -0
  266. package/dist/compiler/urdf.js +12 -0
  267. package/dist/compiler/usd-physics.cjs +26 -0
  268. package/dist/compiler/usd-physics.js +9 -0
  269. package/dist/compiler/visionos.cjs +19 -0
  270. package/dist/compiler/visionos.js +13 -0
  271. package/dist/compiler/vrchat.cjs +22 -0
  272. package/dist/compiler/vrchat.js +12 -0
  273. package/dist/compiler/vrr.cjs +24 -0
  274. package/dist/compiler/vrr.js +12 -0
  275. package/dist/compiler/wasm.cjs +36 -0
  276. package/dist/compiler/wasm.js +12 -0
  277. package/dist/compiler/webgpu.cjs +18 -0
  278. package/dist/compiler/webgpu.js +12 -0
  279. package/dist/coordinators/index.cjs +1266 -0
  280. package/dist/coordinators/index.d.ts +72 -1
  281. package/dist/coordinators/index.js +1259 -0
  282. package/dist/debugger.cjs +24 -0
  283. package/dist/debugger.js +11 -0
  284. package/dist/dist-ACXG6IH5.cjs +3113 -0
  285. package/dist/dist-VD4L6V7Q.js +3076 -0
  286. package/dist/entries/interop.cjs +64 -0
  287. package/dist/entries/interop.js +7 -0
  288. package/dist/entries/scripting.cjs +55 -0
  289. package/dist/entries/scripting.js +10 -0
  290. package/dist/hololand/index.cjs +146 -0
  291. package/dist/hololand/index.d.ts +70 -0
  292. package/dist/hololand/index.js +5 -0
  293. package/dist/index.cjs +44660 -0
  294. package/dist/index.d.ts +978 -21
  295. package/dist/index.js +41422 -0
  296. package/dist/math/tropical-spmv.cjs +45 -0
  297. package/dist/math/tropical-spmv.js +4 -0
  298. package/dist/math/vec3.cjs +57 -0
  299. package/dist/math/vec3.js +4 -0
  300. package/dist/ml-dsa-FSKBTE3W.cjs +1265 -0
  301. package/dist/ml-dsa-Z7JDKW4L.js +1265 -0
  302. package/dist/paper-0c-spike/index.cjs +150 -0
  303. package/dist/paper-0c-spike/index.js +141 -0
  304. package/dist/parser.cjs +61 -0
  305. package/dist/parser.d.ts +11 -0
  306. package/dist/parser.js +12 -0
  307. package/dist/playwright-3AT3AKTV.cjs +98673 -0
  308. package/dist/playwright-VZPDVUEQ.js +98660 -0
  309. package/dist/reconstruction/index.cjs +153 -0
  310. package/dist/reconstruction/index.d.ts +29 -2
  311. package/dist/reconstruction/index.js +8 -0
  312. package/dist/runtime.cjs +316 -0
  313. package/dist/runtime.d.ts +61 -0
  314. package/dist/runtime.js +31 -0
  315. package/dist/self-improvement/index.cjs +563 -0
  316. package/dist/self-improvement/index.js +545 -0
  317. package/dist/src-4ROC227P.cjs +2094 -0
  318. package/dist/src-HCCCSYP7.js +2073 -0
  319. package/dist/storage/index.cjs +38 -0
  320. package/dist/storage/index.js +5 -0
  321. package/dist/testing.cjs +25 -0
  322. package/dist/testing.d.ts +70 -0
  323. package/dist/testing.js +4 -0
  324. package/dist/traitDocs/traitDocs.cjs +33 -0
  325. package/dist/traitDocs/traitDocs.js +7 -0
  326. package/dist/traits/botanical-lotus.cjs +177 -0
  327. package/dist/traits/botanical-lotus.d.ts +502 -0
  328. package/dist/traits/botanical-lotus.js +7 -0
  329. package/dist/traits/engines/index.cjs +520 -0
  330. package/dist/traits/engines/index.js +380 -0
  331. package/dist/traits/index.cjs +24548 -0
  332. package/dist/traits/index.d.ts +171 -35
  333. package/dist/traits/index.js +21638 -0
  334. package/dist/traits/simulation-solver-factory.cjs +13 -0
  335. package/dist/traits/simulation-solver-factory.d.ts +23 -0
  336. package/dist/traits/simulation-solver-factory.js +4 -0
  337. package/dist/traits/webcam-gaze.cjs +35 -0
  338. package/dist/traits/webcam-gaze.d.ts +17 -0
  339. package/dist/traits/webcam-gaze.js +4 -0
  340. package/dist/type-checker.cjs +19 -0
  341. package/dist/type-checker.js +6 -0
  342. package/dist/world/index.cjs +947 -0
  343. package/dist/world/index.d.ts +147 -0
  344. package/dist/world/index.js +939 -0
  345. package/dist/world-model/index.cjs +1446 -0
  346. package/dist/world-model/index.d.ts +119 -0
  347. package/dist/world-model/index.js +1414 -0
  348. package/dist/wot/index.cjs +29 -0
  349. package/dist/wot/index.js +4 -0
  350. package/package.json +93 -49
@@ -0,0 +1,1046 @@
1
+ import { init_PlatformConditionalCompilerMixin, filterCompositionForPlatform } from './chunk-GZG4KA4E.js';
2
+ import { init_DomainBlockCompilerMixin, compileDomainBlocks, compileWeatherBlock, compileAudioSourceBlock, compilePostProcessingBlock, compileParticleBlock, compilePhysicsBlock, compileMaterialBlock } from './chunk-BOVPWH4H.js';
3
+ import { init_CompilerBase, CompilerBase } from './chunk-QPSKHBJP.js';
4
+ import { __export, __esm } from './chunk-OL46QLBJ.js';
5
+ import { ANSCapabilityPath } from '@holoscript/core-types/ans';
6
+
7
+ // src/compiler/OpenXRCompiler.ts
8
+ var OpenXRCompiler_exports = {};
9
+ __export(OpenXRCompiler_exports, {
10
+ OpenXRCompiler: () => OpenXRCompiler
11
+ });
12
+ var OpenXRCompiler;
13
+ var init_OpenXRCompiler = __esm({
14
+ "src/compiler/OpenXRCompiler.ts"() {
15
+ init_CompilerBase();
16
+ init_PlatformConditionalCompilerMixin();
17
+ init_DomainBlockCompilerMixin();
18
+ OpenXRCompiler = class extends CompilerBase {
19
+ constructor(options = {}) {
20
+ super();
21
+ this.compilerName = "OpenXRCompiler";
22
+ this.lines = [];
23
+ this.indentLevel = 0;
24
+ this.options = {
25
+ appName: options.appName || "HoloScriptApp",
26
+ renderBackend: options.renderBackend || "vulkan",
27
+ enableHandTracking: options.enableHandTracking ?? true,
28
+ enablePassthrough: options.enablePassthrough ?? false,
29
+ indent: options.indent || " "
30
+ };
31
+ }
32
+ getRequiredCapability() {
33
+ return ANSCapabilityPath.OPENXR;
34
+ }
35
+ compile(composition, agentToken, outputPath) {
36
+ this.validateCompilerAccess(agentToken, outputPath);
37
+ composition = filterCompositionForPlatform(composition, "quest3");
38
+ this.lines = [];
39
+ this.indentLevel = 0;
40
+ this.emit("// Auto-generated by HoloScript OpenXRCompiler");
41
+ this.emit(
42
+ `// Source: composition "${this.escapeStringValue(composition.name, "TypeScript")}"`
43
+ );
44
+ this.emit("// Do not edit manually -- regenerate from .holo source");
45
+ this.emit("");
46
+ this.emitIncludes();
47
+ this.emit("");
48
+ this.emit(`namespace ${this.sanitizeName(composition.name)} {`);
49
+ this.emit("");
50
+ this.indent();
51
+ this.emit("struct LightUBO {");
52
+ this.indent();
53
+ this.emit("glm::vec4 position;");
54
+ this.emit("glm::vec4 color;");
55
+ this.emit("float intensity;");
56
+ this.emit("float range;");
57
+ this.emit("float padding[2];");
58
+ this.dedent();
59
+ this.emit("};");
60
+ this.emit("");
61
+ this.emit("XrInstance instance = XR_NULL_HANDLE;");
62
+ this.emit("XrSession session = XR_NULL_HANDLE;");
63
+ this.emit("XrSpace appSpace = XR_NULL_HANDLE;");
64
+ this.emit("XrSwapchain swapchain = XR_NULL_HANDLE;");
65
+ this.emit("XrActionSet actionSet = XR_NULL_HANDLE;");
66
+ this.emit("XrAction grabAction = XR_NULL_HANDLE;");
67
+ this.emit("XrAction triggerAction = XR_NULL_HANDLE;");
68
+ this.emit("XrAction aimPoseAction = XR_NULL_HANDLE;");
69
+ this.emit("XrAction hapticAction = XR_NULL_HANDLE;");
70
+ if (this.options.enableHandTracking) {
71
+ this.emit("XrHandTrackerEXT handTrackerLeft = XR_NULL_HANDLE;");
72
+ this.emit("XrHandTrackerEXT handTrackerRight = XR_NULL_HANDLE;");
73
+ }
74
+ this.emit("bool sessionRunning = false;");
75
+ this.emit("");
76
+ this.emitInstanceInit(composition);
77
+ this.emit("");
78
+ this.emitSessionInit();
79
+ this.emit("");
80
+ this.emitActionSets();
81
+ this.emit("");
82
+ if (this.options.enableHandTracking) {
83
+ this.emitHandTracking();
84
+ this.emit("");
85
+ }
86
+ this.emitRenderPass();
87
+ this.emit("");
88
+ this.emit("void setupScene() {");
89
+ this.indent();
90
+ if (composition.environment) {
91
+ this.emitEnvironment(composition.environment);
92
+ }
93
+ for (const light of composition.lights ?? []) {
94
+ this.emitLight(light);
95
+ }
96
+ for (const obj of composition.objects ?? []) {
97
+ this.emitObject(obj);
98
+ }
99
+ for (const group of composition.spatialGroups ?? []) {
100
+ this.emitGroup(group);
101
+ }
102
+ if (composition.camera) {
103
+ this.emitCamera(composition.camera);
104
+ }
105
+ this.dedent();
106
+ this.emit("}");
107
+ this.emit("");
108
+ this.emitRenderLoop(composition);
109
+ this.emit("");
110
+ this.emit("int main() {");
111
+ this.indent();
112
+ this.emit("initInstance();");
113
+ this.emit("initSession();");
114
+ this.emit("initActionSets();");
115
+ if (this.options.enableHandTracking) {
116
+ this.emit("initHandTracking();");
117
+ }
118
+ this.emit("setupScene();");
119
+ this.emit("renderLoop();");
120
+ this.emit("");
121
+ this.emit("// Cleanup");
122
+ if (this.options.enableHandTracking) {
123
+ this.emit("xrDestroyHandTrackerEXT(handTrackerLeft);");
124
+ this.emit("xrDestroyHandTrackerEXT(handTrackerRight);");
125
+ }
126
+ this.emit("xrDestroySwapchain(swapchain);");
127
+ this.emit("xrDestroySpace(appSpace);");
128
+ this.emit("xrDestroySession(session);");
129
+ this.emit("xrDestroyInstance(instance);");
130
+ this.emit("return 0;");
131
+ this.dedent();
132
+ this.emit("}");
133
+ const domainBlocks = composition.domainBlocks ?? [];
134
+ if (domainBlocks.length > 0) {
135
+ this.emit("");
136
+ this.emit("// === v4.2 Domain Blocks ===");
137
+ const compiled = compileDomainBlocks(
138
+ // @ts-expect-error During migration
139
+ domainBlocks,
140
+ {
141
+ material: (block) => {
142
+ const m = compileMaterialBlock(block);
143
+ return `// Material: "${this.escapeStringValue(m.name, "TypeScript")}" type=${m.type} baseColor=${m.baseColor || "none"} roughness=${m.roughness ?? "default"} metallic=${m.metallic ?? "default"}`;
144
+ },
145
+ physics: (block) => {
146
+ const p = compilePhysicsBlock(block);
147
+ return `// Physics: ${p.keyword} "${p.name || ""}" colliders=${p.colliders?.length || 0} rigidbody=${!!p.rigidbody}`;
148
+ },
149
+ vfx: (block) => {
150
+ const ps = compileParticleBlock(block);
151
+ return `// Particles: "${this.escapeStringValue(ps.name, "TypeScript")}" rate=${ps.properties.rate || "default"} modules=${ps.modules.length}`;
152
+ },
153
+ postfx: (block) => {
154
+ const pp = compilePostProcessingBlock(block);
155
+ return `// PostFX: ${pp.keyword} effects=[${pp.effects.map((e) => e.type).join(", ")}]`;
156
+ },
157
+ audio: (block) => {
158
+ const a = compileAudioSourceBlock(block);
159
+ return `// Audio: "${this.escapeStringValue(a.name, "TypeScript")}" (${a.keyword}) clip=${a.properties.clip || "none"}`;
160
+ },
161
+ weather: (block) => {
162
+ const w = compileWeatherBlock(block);
163
+ return `// Weather: ${w.keyword} layers=[${w.layers.map((l) => l.type).join(", ")}]`;
164
+ }
165
+ },
166
+ (block) => `// Domain block: ${block.domain}/${block.keyword} "${this.escapeStringValue(block.name, "TypeScript")}"`
167
+ );
168
+ for (const line of compiled) {
169
+ for (const l of line.split("\n")) this.emit(l);
170
+ }
171
+ }
172
+ this.dedent();
173
+ this.emit("");
174
+ this.emit(`} // namespace ${this.sanitizeName(composition.name)}`);
175
+ return this.lines.join("\n");
176
+ }
177
+ // ---------------------------------------------------------------------------
178
+ // Includes
179
+ // ---------------------------------------------------------------------------
180
+ emitIncludes() {
181
+ this.emit("#include <openxr/openxr.h>");
182
+ this.emit("#include <openxr/openxr_platform.h>");
183
+ if (this.options.enableHandTracking) {
184
+ this.emit("#include <openxr/openxr_extension.h>");
185
+ }
186
+ this.emit("");
187
+ if (this.options.renderBackend === "vulkan") {
188
+ this.emit("#include <vulkan/vulkan.h>");
189
+ } else {
190
+ this.emit("#include <GLES3/gl3.h>");
191
+ this.emit("#include <EGL/egl.h>");
192
+ }
193
+ this.emit("");
194
+ this.emit("#include <glm/glm.hpp>");
195
+ this.emit("#include <glm/gtc/matrix_transform.hpp>");
196
+ this.emit("#include <glm/gtc/type_ptr.hpp>");
197
+ this.emit("");
198
+ this.emit("#include <vector>");
199
+ this.emit("#include <array>");
200
+ this.emit("#include <string>");
201
+ this.emit("#include <cstring>");
202
+ this.emit("#include <cmath>");
203
+ this.emit("#include <iostream>");
204
+ }
205
+ // ---------------------------------------------------------------------------
206
+ // Instance initialization
207
+ // ---------------------------------------------------------------------------
208
+ emitInstanceInit(composition) {
209
+ this.emit("void initInstance() {");
210
+ this.indent();
211
+ this.emit("std::vector<const char*> extensions = {");
212
+ this.indent();
213
+ if (this.options.renderBackend === "vulkan") {
214
+ this.emit("XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME,");
215
+ } else {
216
+ this.emit("XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME,");
217
+ }
218
+ if (this.options.enableHandTracking) {
219
+ this.emit("XR_EXT_HAND_TRACKING_EXTENSION_NAME,");
220
+ }
221
+ if (this.options.enablePassthrough) {
222
+ this.emit("XR_FB_PASSTHROUGH_EXTENSION_NAME,");
223
+ }
224
+ const needsAnchor = this.compositionUsesAnchor(composition);
225
+ if (needsAnchor) {
226
+ this.emit("XR_MSFT_SPATIAL_ANCHOR_EXTENSION_NAME,");
227
+ }
228
+ this.dedent();
229
+ this.emit("};");
230
+ this.emit("");
231
+ this.emit("XrInstanceCreateInfo createInfo{XR_TYPE_INSTANCE_CREATE_INFO};");
232
+ this.emit(
233
+ `std::strncpy(createInfo.applicationInfo.applicationName, "${this.options.appName}", XR_MAX_APPLICATION_NAME_SIZE);`
234
+ );
235
+ this.emit("createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;");
236
+ this.emit("createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());");
237
+ this.emit("createInfo.enabledExtensionNames = extensions.data();");
238
+ this.emit("");
239
+ this.emit("XrResult result = xrCreateInstance(&createInfo, &instance);");
240
+ this.emit("if (XR_FAILED(result)) {");
241
+ this.indent();
242
+ this.emit('std::cerr << "Failed to create XR instance" << std::endl;');
243
+ this.emit("return;");
244
+ this.dedent();
245
+ this.emit("}");
246
+ this.dedent();
247
+ this.emit("}");
248
+ }
249
+ // ---------------------------------------------------------------------------
250
+ // Session initialization
251
+ // ---------------------------------------------------------------------------
252
+ emitSessionInit() {
253
+ this.emit("void initSession() {");
254
+ this.indent();
255
+ this.emit("// Get system");
256
+ this.emit("XrSystemId systemId = XR_NULL_SYSTEM_ID;");
257
+ this.emit("XrSystemGetInfo systemInfo{XR_TYPE_SYSTEM_GET_INFO};");
258
+ this.emit("systemInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;");
259
+ this.emit("xrGetSystem(instance, &systemInfo, &systemId);");
260
+ this.emit("");
261
+ if (this.options.renderBackend === "vulkan") {
262
+ this.emit("// Vulkan graphics binding");
263
+ this.emit("XrGraphicsBindingVulkanKHR graphicsBinding{XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR};");
264
+ this.emit("graphicsBinding.instance = vkInstance;");
265
+ this.emit("graphicsBinding.physicalDevice = vkPhysicalDevice;");
266
+ this.emit("graphicsBinding.device = vkDevice;");
267
+ this.emit("graphicsBinding.queueFamilyIndex = graphicsQueueFamilyIndex;");
268
+ this.emit("graphicsBinding.queueIndex = 0;");
269
+ } else {
270
+ this.emit("// OpenGL ES graphics binding");
271
+ this.emit(
272
+ "XrGraphicsBindingOpenGLESAndroidKHR graphicsBinding{XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR};"
273
+ );
274
+ this.emit("graphicsBinding.display = eglDisplay;");
275
+ this.emit("graphicsBinding.config = eglConfig;");
276
+ this.emit("graphicsBinding.context = eglContext;");
277
+ }
278
+ this.emit("");
279
+ this.emit("// Create session");
280
+ this.emit("XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO};");
281
+ this.emit("sessionCreateInfo.systemId = systemId;");
282
+ this.emit("sessionCreateInfo.next = &graphicsBinding;");
283
+ this.emit("xrCreateSession(instance, &sessionCreateInfo, &session);");
284
+ this.emit("");
285
+ this.emit("// Reference space (STAGE for room-scale)");
286
+ this.emit("XrReferenceSpaceCreateInfo refSpaceInfo{XR_TYPE_REFERENCE_SPACE_CREATE_INFO};");
287
+ this.emit("refSpaceInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;");
288
+ this.emit("refSpaceInfo.poseInReferenceSpace.orientation = {0.0f, 0.0f, 0.0f, 1.0f};");
289
+ this.emit("refSpaceInfo.poseInReferenceSpace.position = {0.0f, 0.0f, 0.0f};");
290
+ this.emit("xrCreateReferenceSpace(session, &refSpaceInfo, &appSpace);");
291
+ this.emit("");
292
+ this.emit("// Swapchain");
293
+ this.emit("XrSwapchainCreateInfo swapchainInfo{XR_TYPE_SWAPCHAIN_CREATE_INFO};");
294
+ this.emit("swapchainInfo.usageFlags = XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;");
295
+ if (this.options.renderBackend === "vulkan") {
296
+ this.emit("swapchainInfo.format = VK_FORMAT_R8G8B8A8_SRGB;");
297
+ } else {
298
+ this.emit("swapchainInfo.format = GL_SRGB8_ALPHA8;");
299
+ }
300
+ this.emit("swapchainInfo.sampleCount = 1;");
301
+ this.emit("swapchainInfo.width = 1920;");
302
+ this.emit("swapchainInfo.height = 1920;");
303
+ this.emit("swapchainInfo.faceCount = 1;");
304
+ this.emit("swapchainInfo.arraySize = 2; // stereo");
305
+ this.emit("swapchainInfo.mipCount = 1;");
306
+ this.emit("xrCreateSwapchain(session, &swapchainInfo, &swapchain);");
307
+ this.emit("");
308
+ this.emit("sessionRunning = true;");
309
+ this.dedent();
310
+ this.emit("}");
311
+ }
312
+ // ---------------------------------------------------------------------------
313
+ // Action sets (input)
314
+ // ---------------------------------------------------------------------------
315
+ emitActionSets() {
316
+ this.emit("void initActionSets() {");
317
+ this.indent();
318
+ this.emit("XrActionSetCreateInfo actionSetInfo{XR_TYPE_ACTION_SET_CREATE_INFO};");
319
+ this.emit(
320
+ 'std::strncpy(actionSetInfo.actionSetName, "gameplay", XR_MAX_ACTION_SET_NAME_SIZE);'
321
+ );
322
+ this.emit(
323
+ 'std::strncpy(actionSetInfo.localizedActionSetName, "Gameplay", XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE);'
324
+ );
325
+ this.emit("xrCreateActionSet(instance, &actionSetInfo, &actionSet);");
326
+ this.emit("");
327
+ const actions = [
328
+ { name: "grabAction", id: "grab", localized: "Grab", type: "XR_ACTION_TYPE_FLOAT_INPUT" },
329
+ {
330
+ name: "triggerAction",
331
+ id: "trigger",
332
+ localized: "Trigger",
333
+ type: "XR_ACTION_TYPE_FLOAT_INPUT"
334
+ },
335
+ {
336
+ name: "aimPoseAction",
337
+ id: "aim_pose",
338
+ localized: "Aim Pose",
339
+ type: "XR_ACTION_TYPE_POSE_INPUT"
340
+ },
341
+ {
342
+ name: "hapticAction",
343
+ id: "haptic",
344
+ localized: "Haptic",
345
+ type: "XR_ACTION_TYPE_VIBRATION_OUTPUT"
346
+ }
347
+ ];
348
+ for (const action of actions) {
349
+ this.emit("{");
350
+ this.indent();
351
+ this.emit("XrActionCreateInfo info{XR_TYPE_ACTION_CREATE_INFO};");
352
+ this.emit(`info.actionType = ${action.type};`);
353
+ this.emit(
354
+ `std::strncpy(info.actionName, "${this.escapeStringValue(action.id, "TypeScript")}", XR_MAX_ACTION_NAME_SIZE);`
355
+ );
356
+ this.emit(
357
+ `std::strncpy(info.localizedActionName, "${action.localized}", XR_MAX_LOCALIZED_ACTION_NAME_SIZE);`
358
+ );
359
+ this.emit("info.countSubactionPaths = 0;");
360
+ this.emit(
361
+ `xrCreateAction(actionSet, &info, &${this.escapeStringValue(action.name, "TypeScript")});`
362
+ );
363
+ this.dedent();
364
+ this.emit("}");
365
+ }
366
+ this.emit("");
367
+ this.emit("// Attach action set to session");
368
+ this.emit("XrSessionActionSetsAttachInfo attachInfo{XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO};");
369
+ this.emit("attachInfo.countActionSets = 1;");
370
+ this.emit("attachInfo.actionSets = &actionSet;");
371
+ this.emit("xrAttachSessionActionSets(session, &attachInfo);");
372
+ this.dedent();
373
+ this.emit("}");
374
+ }
375
+ // ---------------------------------------------------------------------------
376
+ // Environment (clear color, fog)
377
+ // ---------------------------------------------------------------------------
378
+ emitEnvironment(env) {
379
+ this.emit("// === Environment ===");
380
+ for (const prop of env.properties) {
381
+ if (prop.key === "preset" || prop.key === "skybox") {
382
+ this.emit(`// Environment preset: "${prop.value}"`);
383
+ } else if (prop.key === "background" || prop.key === "clear_color") {
384
+ const color = this.toCppColor(prop.value);
385
+ this.emit(`glm::vec4 clearColor = ${color};`);
386
+ } else if (prop.key === "fog" && typeof prop.value === "object") {
387
+ const fog = prop.value;
388
+ const fogColor = fog.color ? this.toCppColor(fog.color) : "glm::vec4(0.5f, 0.5f, 0.5f, 1.0f)";
389
+ this.emit(`glm::vec4 fogColor = ${fogColor};`);
390
+ this.emit(`float fogNear = ${fog.near ?? 10}f;`);
391
+ this.emit(`float fogFar = ${fog.far ?? 100}f;`);
392
+ } else if (prop.key === "ambient_light") {
393
+ const intensity = typeof prop.value === "number" ? prop.value : 0.5;
394
+ this.emit(`float ambientIntensity = ${intensity}f;`);
395
+ } else if (prop.key === "gravity" && Array.isArray(prop.value)) {
396
+ this.emit(`glm::vec3 gravity = ${this.toCppVec3(prop.value)};`);
397
+ }
398
+ }
399
+ this.emit("");
400
+ }
401
+ // ---------------------------------------------------------------------------
402
+ // Object emission
403
+ // ---------------------------------------------------------------------------
404
+ emitObject(obj) {
405
+ const varName = this.sanitizeName(obj.name);
406
+ this.emit(`// Object: ${this.escapeStringValue(obj.name, "TypeScript")}`);
407
+ this.emit("{");
408
+ this.indent();
409
+ const meshType = this.findObjProp(obj, "mesh") || this.findObjProp(obj, "type") || "cube";
410
+ const pos = this.findObjProp(obj, "position");
411
+ const scale = this.findObjProp(obj, "scale");
412
+ const color = this.findObjProp(obj, "color");
413
+ const material = this.findObjProp(obj, "material");
414
+ this.emit(`auto ${varName}_vertices = ${this.mapShapeToVertexData(meshType)};`);
415
+ this.emit("");
416
+ this.emit(`glm::mat4 ${varName}_model = glm::mat4(1.0f);`);
417
+ if (pos && Array.isArray(pos)) {
418
+ this.emit(`${varName}_model = glm::translate(${varName}_model, ${this.toCppVec3(pos)});`);
419
+ }
420
+ if (scale) {
421
+ if (Array.isArray(scale)) {
422
+ this.emit(`${varName}_model = glm::scale(${varName}_model, ${this.toCppVec3(scale)});`);
423
+ } else {
424
+ this.emit(`${varName}_model = glm::scale(${varName}_model, glm::vec3(${scale}f));`);
425
+ }
426
+ }
427
+ this.emit("");
428
+ if (material && typeof material === "object") {
429
+ const mat = material;
430
+ const baseColor = mat.color ? this.toCppColor(mat.color) : "glm::vec4(1.0f)";
431
+ this.emit(`glm::vec4 ${varName}_color = ${baseColor};`);
432
+ this.emit(`float ${varName}_roughness = ${mat.roughness ?? 0.5}f;`);
433
+ this.emit(`float ${varName}_metallic = ${mat.metalness ?? mat.metallic ?? 0}f;`);
434
+ } else if (color) {
435
+ this.emit(`glm::vec4 ${varName}_color = ${this.toCppColor(color)};`);
436
+ } else {
437
+ this.emit(`glm::vec4 ${varName}_color = glm::vec4(1.0f);`);
438
+ }
439
+ this.emit("");
440
+ if (this.options.renderBackend === "vulkan") {
441
+ this.emit(
442
+ `// Create Vulkan vertex buffer for ${this.escapeStringValue(obj.name, "TypeScript")}`
443
+ );
444
+ this.emit(`VkBuffer ${varName}_vbo = VK_NULL_HANDLE;`);
445
+ this.emit(`VkDeviceMemory ${varName}_vboMemory = VK_NULL_HANDLE;`);
446
+ this.emit("{");
447
+ this.indent();
448
+ this.emit("VkBufferCreateInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};");
449
+ this.emit(`bufferInfo.size = ${varName}_vertices.size() * sizeof(float);`);
450
+ this.emit("bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;");
451
+ this.emit("bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;");
452
+ this.emit(`vkCreateBuffer(vkDevice, &bufferInfo, nullptr, &${varName}_vbo);`);
453
+ this.emit("");
454
+ this.emit("VkMemoryRequirements memReqs;");
455
+ this.emit(`vkGetBufferMemoryRequirements(vkDevice, ${varName}_vbo, &memReqs);`);
456
+ this.emit("");
457
+ this.emit("VkMemoryAllocateInfo allocInfo{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};");
458
+ this.emit("allocInfo.allocationSize = memReqs.size;");
459
+ this.emit(
460
+ "allocInfo.memoryTypeIndex = findMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);"
461
+ );
462
+ this.emit(`vkAllocateMemory(vkDevice, &allocInfo, nullptr, &${varName}_vboMemory);`);
463
+ this.emit(`vkBindBufferMemory(vkDevice, ${varName}_vbo, ${varName}_vboMemory, 0);`);
464
+ this.emit("");
465
+ this.emit("// Upload vertex data");
466
+ this.emit("void* mapped = nullptr;");
467
+ this.emit(`vkMapMemory(vkDevice, ${varName}_vboMemory, 0, bufferInfo.size, 0, &mapped);`);
468
+ this.emit(`std::memcpy(mapped, ${varName}_vertices.data(), bufferInfo.size);`);
469
+ this.emit(`vkUnmapMemory(vkDevice, ${varName}_vboMemory);`);
470
+ this.dedent();
471
+ this.emit("}");
472
+ this.emit("");
473
+ this.emit(
474
+ `// Allocate descriptor set for ${this.escapeStringValue(obj.name, "TypeScript")}`
475
+ );
476
+ this.emit(`VkDescriptorSet ${varName}_desc = VK_NULL_HANDLE;`);
477
+ this.emit("{");
478
+ this.indent();
479
+ this.emit(
480
+ "VkDescriptorSetAllocateInfo descAllocInfo{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO};"
481
+ );
482
+ this.emit("descAllocInfo.descriptorPool = descriptorPool;");
483
+ this.emit("descAllocInfo.descriptorSetCount = 1;");
484
+ this.emit("descAllocInfo.pSetLayouts = &descriptorSetLayout;");
485
+ this.emit(`vkAllocateDescriptorSets(vkDevice, &descAllocInfo, &${varName}_desc);`);
486
+ this.dedent();
487
+ this.emit("}");
488
+ } else {
489
+ this.emit(`GLuint ${varName}_vao, ${varName}_vbo;`);
490
+ this.emit(`glGenVertexArrays(1, &${varName}_vao);`);
491
+ this.emit(`glGenBuffers(1, &${varName}_vbo);`);
492
+ this.emit(`glBindVertexArray(${varName}_vao);`);
493
+ this.emit(`glBindBuffer(GL_ARRAY_BUFFER, ${varName}_vbo);`);
494
+ this.emit(
495
+ `glBufferData(GL_ARRAY_BUFFER, ${varName}_vertices.size() * sizeof(float), ${varName}_vertices.data(), GL_STATIC_DRAW);`
496
+ );
497
+ this.emit("glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);");
498
+ this.emit("glEnableVertexAttribArray(0);");
499
+ this.emit(
500
+ "glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));"
501
+ );
502
+ this.emit("glEnableVertexAttribArray(1);");
503
+ }
504
+ if (obj.traits) {
505
+ for (const trait of obj.traits) {
506
+ if (trait.name === "hand_tracking") {
507
+ this.emit("");
508
+ this.emit(`// Trait: hand_tracking -- joint data driven via XR_EXT_hand_tracking`);
509
+ this.emit(`// ${varName} position will be updated from hand joint locations each frame`);
510
+ } else if (trait.name === "anchor") {
511
+ this.emit("");
512
+ this.emit(`// Trait: anchor -- XR_MSFT_spatial_anchor`);
513
+ this.emit(`XrSpatialAnchorMSFT ${varName}_anchor = XR_NULL_HANDLE;`);
514
+ this.emit(
515
+ "XrSpatialAnchorCreateInfoMSFT anchorInfo{XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT};"
516
+ );
517
+ this.emit("anchorInfo.space = appSpace;");
518
+ this.emit("anchorInfo.time = predictedDisplayTime;");
519
+ if (pos && Array.isArray(pos)) {
520
+ this.emit(
521
+ `anchorInfo.pose.position = {${pos[0] ?? 0}f, ${pos[1] ?? 0}f, ${pos[2] ?? 0}f};`
522
+ );
523
+ } else {
524
+ this.emit("anchorInfo.pose.position = {0.0f, 0.0f, 0.0f};");
525
+ }
526
+ this.emit("anchorInfo.pose.orientation = {0.0f, 0.0f, 0.0f, 1.0f};");
527
+ this.emit(`xrCreateSpatialAnchorMSFT(session, &anchorInfo, &${varName}_anchor);`);
528
+ } else if (trait.name === "grabbable") {
529
+ this.emit("");
530
+ this.emit(
531
+ `// Trait: grabbable -- detect grip action on ${this.escapeStringValue(obj.name, "TypeScript")}`
532
+ );
533
+ this.emit(`bool ${varName}_grabbed = false;`);
534
+ } else if (trait.name === "physics") {
535
+ this.emit("");
536
+ this.emit(`// Trait: physics -- simulated via CPU/GPU physics step`);
537
+ this.emit(`glm::vec3 ${varName}_velocity(0.0f);`);
538
+ this.emit(`float ${varName}_mass = ${trait.config?.mass ?? 1}f;`);
539
+ }
540
+ }
541
+ }
542
+ this.dedent();
543
+ this.emit("}");
544
+ this.emit("");
545
+ if (obj.children) {
546
+ for (const child of obj.children) {
547
+ this.emitObject(child);
548
+ }
549
+ }
550
+ }
551
+ // ---------------------------------------------------------------------------
552
+ // Spatial group
553
+ // ---------------------------------------------------------------------------
554
+ emitGroup(group) {
555
+ const varName = this.sanitizeName(group.name);
556
+ this.emit(`// Spatial Group: ${this.escapeStringValue(group.name, "TypeScript")}`);
557
+ this.emit("{");
558
+ this.indent();
559
+ this.emit(`glm::mat4 ${varName}_transform = glm::mat4(1.0f);`);
560
+ for (const prop of group.properties) {
561
+ if (prop.key === "position" && Array.isArray(prop.value)) {
562
+ this.emit(
563
+ `${varName}_transform = glm::translate(${varName}_transform, ${this.toCppVec3(prop.value)});`
564
+ );
565
+ } else if (prop.key === "rotation" && Array.isArray(prop.value)) {
566
+ const r = prop.value;
567
+ this.emit(
568
+ `${varName}_transform = glm::rotate(${varName}_transform, glm::radians(${r[0] ?? 0}f), glm::vec3(1,0,0));`
569
+ );
570
+ this.emit(
571
+ `${varName}_transform = glm::rotate(${varName}_transform, glm::radians(${r[1] ?? 0}f), glm::vec3(0,1,0));`
572
+ );
573
+ this.emit(
574
+ `${varName}_transform = glm::rotate(${varName}_transform, glm::radians(${r[2] ?? 0}f), glm::vec3(0,0,1));`
575
+ );
576
+ } else if (prop.key === "scale") {
577
+ if (Array.isArray(prop.value)) {
578
+ this.emit(
579
+ `${varName}_transform = glm::scale(${varName}_transform, ${this.toCppVec3(prop.value)});`
580
+ );
581
+ } else {
582
+ this.emit(
583
+ `${varName}_transform = glm::scale(${varName}_transform, glm::vec3(${prop.value}f));`
584
+ );
585
+ }
586
+ }
587
+ }
588
+ this.emit(`// Push ${varName}_transform onto model matrix stack`);
589
+ this.emit("");
590
+ for (const obj of group.objects) {
591
+ this.emitObject(obj);
592
+ }
593
+ if (group.groups) {
594
+ for (const sub of group.groups) {
595
+ this.emitGroup(sub);
596
+ }
597
+ }
598
+ this.emit("// Pop model matrix stack");
599
+ this.dedent();
600
+ this.emit("}");
601
+ this.emit("");
602
+ }
603
+ // ---------------------------------------------------------------------------
604
+ // Light
605
+ // ---------------------------------------------------------------------------
606
+ emitLight(light) {
607
+ const varName = this.sanitizeName(light.name);
608
+ this.emit(
609
+ `// Light: ${this.escapeStringValue(light.name, "TypeScript")} (${light.lightType})`
610
+ );
611
+ this.emit("{");
612
+ this.indent();
613
+ this.emit(`LightUBO ${varName}_ubo;`);
614
+ const colorProp = light.properties.find((p) => p.key === "color");
615
+ const intensityProp = light.properties.find((p) => p.key === "intensity");
616
+ const posProp = light.properties.find((p) => p.key === "position");
617
+ if (posProp && Array.isArray(posProp.value)) {
618
+ const p = posProp.value;
619
+ const w = light.lightType === "directional" ? 0 : 1;
620
+ this.emit(`${varName}_ubo.position = glm::vec4(${p[0]}f, ${p[1]}f, ${p[2]}f, ${w}f);`);
621
+ } else {
622
+ const w = light.lightType === "directional" ? 0 : 1;
623
+ this.emit(`${varName}_ubo.position = glm::vec4(0.0f, 5.0f, 0.0f, ${w}f);`);
624
+ }
625
+ if (colorProp) {
626
+ this.emit(`${varName}_ubo.color = ${this.toCppColor(colorProp.value)};`);
627
+ } else {
628
+ this.emit(`${varName}_ubo.color = glm::vec4(1.0f);`);
629
+ }
630
+ this.emit(`${varName}_ubo.intensity = ${intensityProp?.value ?? 1}f;`);
631
+ this.emit(`${varName}_ubo.range = ${light.lightType === "directional" ? 0 : 50}f;`);
632
+ this.emit(`// Upload ${varName}_ubo to uniform buffer`);
633
+ this.dedent();
634
+ this.emit("}");
635
+ this.emit("");
636
+ }
637
+ // ---------------------------------------------------------------------------
638
+ // Camera (XR view-driven)
639
+ // ---------------------------------------------------------------------------
640
+ emitCamera(cam) {
641
+ this.emit("// Camera: view/projection derived from xrLocateViews");
642
+ this.emit("{");
643
+ this.indent();
644
+ this.emit("XrViewLocateInfo viewLocateInfo{XR_TYPE_VIEW_LOCATE_INFO};");
645
+ this.emit("viewLocateInfo.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;");
646
+ this.emit("viewLocateInfo.displayTime = predictedDisplayTime;");
647
+ this.emit("viewLocateInfo.space = appSpace;");
648
+ this.emit("");
649
+ this.emit("XrViewState viewState{XR_TYPE_VIEW_STATE};");
650
+ this.emit("uint32_t viewCount = 2;");
651
+ this.emit("std::array<XrView, 2> views;");
652
+ this.emit("views[0].type = XR_TYPE_VIEW;");
653
+ this.emit("views[1].type = XR_TYPE_VIEW;");
654
+ this.emit(
655
+ "xrLocateViews(session, &viewLocateInfo, &viewState, viewCount, &viewCount, views.data());"
656
+ );
657
+ this.emit("");
658
+ this.emit("// Per-eye projection and view matrices");
659
+ this.emit("for (uint32_t eye = 0; eye < viewCount; eye++) {");
660
+ this.indent();
661
+ this.emit("const XrFovf& fov = views[eye].fov;");
662
+ for (const prop of cam.properties) {
663
+ if (prop.key === "near" || prop.key === "near_clip") {
664
+ this.emit(`float nearClip = ${prop.value}f;`);
665
+ } else if (prop.key === "far" || prop.key === "far_clip") {
666
+ this.emit(`float farClip = ${prop.value}f;`);
667
+ }
668
+ }
669
+ this.emit("// Build asymmetric projection from fov angles + near/far");
670
+ this.emit("// Build view matrix from views[eye].pose");
671
+ this.dedent();
672
+ this.emit("}");
673
+ this.dedent();
674
+ this.emit("}");
675
+ this.emit("");
676
+ }
677
+ // ---------------------------------------------------------------------------
678
+ // Render pass
679
+ // ---------------------------------------------------------------------------
680
+ emitRenderPass() {
681
+ if (this.options.renderBackend === "vulkan") {
682
+ this.emit(
683
+ "void beginRenderPass(VkCommandBuffer cmd, VkRenderPass renderPass, VkFramebuffer framebuffer, uint32_t width, uint32_t height) {"
684
+ );
685
+ this.indent();
686
+ this.emit("VkRenderPassBeginInfo rpInfo{VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};");
687
+ this.emit("rpInfo.renderPass = renderPass;");
688
+ this.emit("rpInfo.framebuffer = framebuffer;");
689
+ this.emit("rpInfo.renderArea.extent = {width, height};");
690
+ this.emit("VkClearValue clearValue{};");
691
+ this.emit("clearValue.color = {{0.0f, 0.0f, 0.0f, 1.0f}};");
692
+ this.emit("rpInfo.clearValueCount = 1;");
693
+ this.emit("rpInfo.pClearValues = &clearValue;");
694
+ this.emit("vkCmdBeginRenderPass(cmd, &rpInfo, VK_SUBPASS_CONTENTS_INLINE);");
695
+ this.emit("");
696
+ this.emit("// Bind pipeline and draw objects here");
697
+ this.emit("");
698
+ this.emit("vkCmdEndRenderPass(cmd);");
699
+ this.dedent();
700
+ this.emit("}");
701
+ } else {
702
+ this.emit("void beginRenderPass(uint32_t framebuffer, uint32_t width, uint32_t height) {");
703
+ this.indent();
704
+ this.emit("glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);");
705
+ this.emit("glViewport(0, 0, width, height);");
706
+ this.emit("glClearColor(0.0f, 0.0f, 0.0f, 1.0f);");
707
+ this.emit("glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);");
708
+ this.emit("glEnable(GL_DEPTH_TEST);");
709
+ this.emit("");
710
+ this.emit("// Bind shader program and draw objects here");
711
+ this.emit("");
712
+ this.dedent();
713
+ this.emit("}");
714
+ }
715
+ }
716
+ // ---------------------------------------------------------------------------
717
+ // Render loop
718
+ // ---------------------------------------------------------------------------
719
+ emitRenderLoop(composition) {
720
+ this.emit("void renderLoop() {");
721
+ this.indent();
722
+ this.emit("while (sessionRunning) {");
723
+ this.indent();
724
+ this.emit("// Poll OpenXR events");
725
+ this.emit("XrEventDataBuffer event{XR_TYPE_EVENT_DATA_BUFFER};");
726
+ this.emit("while (xrPollEvent(instance, &event) == XR_SUCCESS) {");
727
+ this.indent();
728
+ this.emit("if (event.type == XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) {");
729
+ this.indent();
730
+ this.emit("auto* stateEvent = reinterpret_cast<XrEventDataSessionStateChanged*>(&event);");
731
+ this.emit("if (stateEvent->state == XR_SESSION_STATE_STOPPING) {");
732
+ this.indent();
733
+ this.emit("sessionRunning = false;");
734
+ this.dedent();
735
+ this.emit("}");
736
+ this.dedent();
737
+ this.emit("}");
738
+ this.emit("event = {XR_TYPE_EVENT_DATA_BUFFER};");
739
+ this.dedent();
740
+ this.emit("}");
741
+ this.emit("if (!sessionRunning) break;");
742
+ this.emit("");
743
+ this.emit("// Sync actions");
744
+ this.emit("XrActiveActionSet activeActionSet{actionSet, XR_NULL_PATH};");
745
+ this.emit("XrActionsSyncInfo syncInfo{XR_TYPE_ACTIONS_SYNC_INFO};");
746
+ this.emit("syncInfo.countActiveActionSets = 1;");
747
+ this.emit("syncInfo.activeActionSets = &activeActionSet;");
748
+ this.emit("xrSyncActions(session, &syncInfo);");
749
+ this.emit("");
750
+ this.emit("// Wait frame");
751
+ this.emit("XrFrameWaitInfo waitInfo{XR_TYPE_FRAME_WAIT_INFO};");
752
+ this.emit("XrFrameState frameState{XR_TYPE_FRAME_STATE};");
753
+ this.emit("xrWaitFrame(session, &waitInfo, &frameState);");
754
+ this.emit("");
755
+ this.emit("// Begin frame");
756
+ this.emit("XrFrameBeginInfo beginInfo{XR_TYPE_FRAME_BEGIN_INFO};");
757
+ this.emit("xrBeginFrame(session, &beginInfo);");
758
+ this.emit("");
759
+ this.emit("XrTime predictedDisplayTime = frameState.predictedDisplayTime;");
760
+ this.emit("");
761
+ if (this.options.enableHandTracking) {
762
+ this.emit("// Hand tracking update");
763
+ this.emit("updateHandTracking(predictedDisplayTime);");
764
+ this.emit("");
765
+ }
766
+ this.emit("// Locate views for stereo rendering");
767
+ this.emit("XrViewLocateInfo viewLocateInfo{XR_TYPE_VIEW_LOCATE_INFO};");
768
+ this.emit("viewLocateInfo.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;");
769
+ this.emit("viewLocateInfo.displayTime = predictedDisplayTime;");
770
+ this.emit("viewLocateInfo.space = appSpace;");
771
+ this.emit("XrViewState viewState{XR_TYPE_VIEW_STATE};");
772
+ this.emit("uint32_t viewCount = 2;");
773
+ this.emit("std::array<XrView, 2> views;");
774
+ this.emit("views[0].type = XR_TYPE_VIEW;");
775
+ this.emit("views[1].type = XR_TYPE_VIEW;");
776
+ this.emit(
777
+ "xrLocateViews(session, &viewLocateInfo, &viewState, viewCount, &viewCount, views.data());"
778
+ );
779
+ this.emit("");
780
+ this.emit("// Acquire and render to swapchain image");
781
+ this.emit("XrSwapchainImageAcquireInfo acquireInfo{XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO};");
782
+ this.emit("uint32_t imageIndex;");
783
+ this.emit("xrAcquireSwapchainImage(swapchain, &acquireInfo, &imageIndex);");
784
+ this.emit("");
785
+ this.emit("XrSwapchainImageWaitInfo swapWaitInfo{XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO};");
786
+ this.emit("swapWaitInfo.timeout = XR_INFINITE_DURATION;");
787
+ this.emit("xrWaitSwapchainImage(swapchain, &swapWaitInfo);");
788
+ this.emit("");
789
+ this.emit("// === Render scene objects ===");
790
+ if (this.options.renderBackend === "vulkan") {
791
+ this.emit(
792
+ "VkCommandBufferBeginInfo cmdBeginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};"
793
+ );
794
+ this.emit("cmdBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;");
795
+ this.emit("vkBeginCommandBuffer(commandBuffer, &cmdBeginInfo);");
796
+ this.emit("");
797
+ this.emit(
798
+ "beginRenderPass(commandBuffer, renderPass, framebuffers[imageIndex], 1920, 1920);"
799
+ );
800
+ this.emit("");
801
+ const allObjects = this.collectAllObjects(composition);
802
+ for (const obj of allObjects) {
803
+ const varName = this.sanitizeName(obj.name);
804
+ this.emit(`// Draw: ${this.escapeStringValue(obj.name, "TypeScript")}`);
805
+ this.emit(
806
+ `vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);`
807
+ );
808
+ this.emit(`VkDeviceSize ${varName}_offset = 0;`);
809
+ this.emit(
810
+ `vkCmdBindVertexBuffers(commandBuffer, 0, 1, &${varName}_vbo, &${varName}_offset);`
811
+ );
812
+ this.emit(
813
+ `vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &${varName}_desc, 0, nullptr);`
814
+ );
815
+ this.emit(
816
+ `vkCmdDraw(commandBuffer, static_cast<uint32_t>(${varName}_vertices.size() / 6), 1, 0, 0);`
817
+ );
818
+ this.emit("");
819
+ }
820
+ this.emit("vkCmdEndRenderPass(commandBuffer);");
821
+ this.emit("vkEndCommandBuffer(commandBuffer);");
822
+ this.emit("");
823
+ this.emit("// Submit command buffer");
824
+ this.emit("VkSubmitInfo submitInfo{VK_STRUCTURE_TYPE_SUBMIT_INFO};");
825
+ this.emit("submitInfo.commandBufferCount = 1;");
826
+ this.emit("submitInfo.pCommandBuffers = &commandBuffer;");
827
+ this.emit("vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);");
828
+ this.emit("vkQueueWaitIdle(graphicsQueue);");
829
+ } else {
830
+ const allObjects = this.collectAllObjects(composition);
831
+ for (const obj of allObjects) {
832
+ const varName = this.sanitizeName(obj.name);
833
+ this.emit(`// Draw: ${this.escapeStringValue(obj.name, "TypeScript")}`);
834
+ this.emit(`glBindVertexArray(${varName}_vao);`);
835
+ this.emit(
836
+ `glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(${varName}_vertices.size() / 6));`
837
+ );
838
+ this.emit("");
839
+ }
840
+ }
841
+ this.emit("");
842
+ this.emit("XrSwapchainImageReleaseInfo releaseInfo{XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO};");
843
+ this.emit("xrReleaseSwapchainImage(swapchain, &releaseInfo);");
844
+ this.emit("");
845
+ this.emit("// End frame");
846
+ this.emit("XrCompositionLayerProjection layer{XR_TYPE_COMPOSITION_LAYER_PROJECTION};");
847
+ this.emit("layer.space = appSpace;");
848
+ this.emit("std::array<XrCompositionLayerProjectionView, 2> projViews;");
849
+ this.emit("for (uint32_t eye = 0; eye < 2; eye++) {");
850
+ this.indent();
851
+ this.emit("projViews[eye] = {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW};");
852
+ this.emit("projViews[eye].pose = views[eye].pose;");
853
+ this.emit("projViews[eye].fov = views[eye].fov;");
854
+ this.emit("projViews[eye].subImage.swapchain = swapchain;");
855
+ this.emit("projViews[eye].subImage.imageArrayIndex = eye;");
856
+ this.emit("projViews[eye].subImage.imageRect.offset = {0, 0};");
857
+ this.emit("projViews[eye].subImage.imageRect.extent = {1920, 1920};");
858
+ this.dedent();
859
+ this.emit("}");
860
+ this.emit("layer.viewCount = 2;");
861
+ this.emit("layer.views = projViews.data();");
862
+ this.emit("");
863
+ this.emit("const XrCompositionLayerBaseHeader* layers[] = {");
864
+ this.indent();
865
+ this.emit("reinterpret_cast<const XrCompositionLayerBaseHeader*>(&layer)");
866
+ this.dedent();
867
+ this.emit("};");
868
+ this.emit("XrFrameEndInfo endInfo{XR_TYPE_FRAME_END_INFO};");
869
+ this.emit("endInfo.displayTime = predictedDisplayTime;");
870
+ this.emit("endInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;");
871
+ this.emit("endInfo.layerCount = 1;");
872
+ this.emit("endInfo.layers = layers;");
873
+ this.emit("xrEndFrame(session, &endInfo);");
874
+ this.dedent();
875
+ this.emit("}");
876
+ this.dedent();
877
+ this.emit("}");
878
+ }
879
+ // ---------------------------------------------------------------------------
880
+ // Hand tracking
881
+ // ---------------------------------------------------------------------------
882
+ emitHandTracking() {
883
+ this.emit("void initHandTracking() {");
884
+ this.indent();
885
+ this.emit("XrHandTrackerCreateInfoEXT createInfo{XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT};");
886
+ this.emit("");
887
+ this.emit("createInfo.hand = XR_HAND_LEFT_EXT;");
888
+ this.emit("createInfo.handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT;");
889
+ this.emit("xrCreateHandTrackerEXT(session, &createInfo, &handTrackerLeft);");
890
+ this.emit("");
891
+ this.emit("createInfo.hand = XR_HAND_RIGHT_EXT;");
892
+ this.emit("xrCreateHandTrackerEXT(session, &createInfo, &handTrackerRight);");
893
+ this.dedent();
894
+ this.emit("}");
895
+ this.emit("");
896
+ this.emit("void updateHandTracking(XrTime displayTime) {");
897
+ this.indent();
898
+ this.emit("XrHandJointLocationsEXT locations{XR_TYPE_HAND_JOINT_LOCATIONS_EXT};");
899
+ this.emit(`std::array<XrHandJointLocationEXT, XR_HAND_JOINT_COUNT_EXT> jointLocations;`);
900
+ this.emit("locations.jointCount = static_cast<uint32_t>(jointLocations.size());");
901
+ this.emit("locations.jointLocations = jointLocations.data();");
902
+ this.emit("");
903
+ this.emit("XrHandJointsLocateInfoEXT locateInfo{XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT};");
904
+ this.emit("locateInfo.baseSpace = appSpace;");
905
+ this.emit("locateInfo.time = displayTime;");
906
+ this.emit("");
907
+ this.emit("// Left hand");
908
+ this.emit("xrLocateHandJointsEXT(handTrackerLeft, &locateInfo, &locations);");
909
+ this.emit("if (locations.isActive) {");
910
+ this.indent();
911
+ this.emit("// Process left hand joint positions");
912
+ this.emit("for (uint32_t j = 0; j < XR_HAND_JOINT_COUNT_EXT; j++) {");
913
+ this.indent();
914
+ this.emit("const auto& loc = jointLocations[j];");
915
+ this.emit("glm::vec3 pos(loc.pose.position[0], loc.pose.position[1], loc.pose.position[2]);");
916
+ this.emit("// Update hand-tracked object transforms from joint data");
917
+ this.dedent();
918
+ this.emit("}");
919
+ this.dedent();
920
+ this.emit("}");
921
+ this.emit("");
922
+ this.emit("// Right hand");
923
+ this.emit("xrLocateHandJointsEXT(handTrackerRight, &locateInfo, &locations);");
924
+ this.emit("if (locations.isActive) {");
925
+ this.indent();
926
+ this.emit("for (uint32_t j = 0; j < XR_HAND_JOINT_COUNT_EXT; j++) {");
927
+ this.indent();
928
+ this.emit("const auto& loc = jointLocations[j];");
929
+ this.emit("glm::vec3 pos(loc.pose.position[0], loc.pose.position[1], loc.pose.position[2]);");
930
+ this.emit("// Update hand-tracked object transforms from joint data");
931
+ this.dedent();
932
+ this.emit("}");
933
+ this.dedent();
934
+ this.emit("}");
935
+ this.dedent();
936
+ this.emit("}");
937
+ }
938
+ // ---------------------------------------------------------------------------
939
+ // Helpers
940
+ // ---------------------------------------------------------------------------
941
+ emit(line) {
942
+ this.lines.push(this.options.indent.repeat(this.indentLevel) + line);
943
+ }
944
+ indent() {
945
+ this.indentLevel++;
946
+ }
947
+ dedent() {
948
+ if (this.indentLevel > 0) this.indentLevel--;
949
+ }
950
+ sanitizeName(name) {
951
+ return name.replace(/[^a-zA-Z0-9_]/g, "_");
952
+ }
953
+ findObjProp(obj, key) {
954
+ return obj.properties?.find((p) => p.key === key)?.value;
955
+ }
956
+ // ---------------------------------------------------------------------------
957
+ // Value conversion helpers
958
+ // ---------------------------------------------------------------------------
959
+ toCppVec3(arr) {
960
+ if (Array.isArray(arr) && arr.length >= 3) {
961
+ return `glm::vec3(${arr[0]}f, ${arr[1]}f, ${arr[2]}f)`;
962
+ }
963
+ if (typeof arr === "number") {
964
+ return `glm::vec3(${arr}f)`;
965
+ }
966
+ return "glm::vec3(0.0f)";
967
+ }
968
+ toCppColor(hex) {
969
+ if (typeof hex === "string" && hex.startsWith("#")) {
970
+ const h = hex.slice(1);
971
+ const r = (parseInt(h.substring(0, 2), 16) / 255).toFixed(3);
972
+ const g = (parseInt(h.substring(2, 4), 16) / 255).toFixed(3);
973
+ const b = (parseInt(h.substring(4, 6), 16) / 255).toFixed(3);
974
+ return `glm::vec4(${r}f, ${g}f, ${b}f, 1.0f)`;
975
+ }
976
+ if (typeof hex === "string") {
977
+ return `glm::vec4(1.0f) /* ${hex} */`;
978
+ }
979
+ return "glm::vec4(1.0f)";
980
+ }
981
+ mapShapeToVertexData(type) {
982
+ switch (type) {
983
+ case "cube":
984
+ case "box":
985
+ return "generateCubeVertices()";
986
+ case "sphere":
987
+ case "orb":
988
+ return "generateSphereVertices(32, 32)";
989
+ case "plane":
990
+ return "generatePlaneVertices()";
991
+ case "cylinder":
992
+ return "generateCylinderVertices(32)";
993
+ case "cone":
994
+ case "pyramid":
995
+ return "generateConeVertices(32)";
996
+ case "torus":
997
+ return "generateTorusVertices(32, 16)";
998
+ default:
999
+ return "generateCubeVertices()";
1000
+ }
1001
+ }
1002
+ // ---------------------------------------------------------------------------
1003
+ // Composition analysis helpers
1004
+ // ---------------------------------------------------------------------------
1005
+ compositionUsesAnchor(composition) {
1006
+ const check = (objs) => {
1007
+ if (!objs) return false;
1008
+ return objs.some(
1009
+ (o) => o.traits?.some(
1010
+ (t) => t.name === "anchor" || t.name === "persistent_anchor" || t.name === "shared_anchor"
1011
+ ) || check(o.children)
1012
+ );
1013
+ };
1014
+ return check(composition.objects);
1015
+ }
1016
+ collectAllObjects(composition) {
1017
+ const result = [];
1018
+ const collect = (objs) => {
1019
+ if (!objs) return;
1020
+ for (const obj of objs) {
1021
+ result.push(obj);
1022
+ if (obj.children) {
1023
+ collect(obj.children);
1024
+ }
1025
+ }
1026
+ };
1027
+ collect(composition.objects);
1028
+ const collectFromGroups = (groups) => {
1029
+ if (!groups) return;
1030
+ for (const group of groups) {
1031
+ collect(group.objects);
1032
+ if (group.groups) {
1033
+ collectFromGroups(group.groups);
1034
+ }
1035
+ }
1036
+ };
1037
+ collectFromGroups(composition.spatialGroups);
1038
+ return result;
1039
+ }
1040
+ };
1041
+ }
1042
+ });
1043
+
1044
+ export { OpenXRCompiler, OpenXRCompiler_exports, init_OpenXRCompiler };
1045
+ //# sourceMappingURL=chunk-QD32ADK6.js.map
1046
+ //# sourceMappingURL=chunk-QD32ADK6.js.map