@holoscript/core 6.0.3 → 6.1.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.
- package/README.md +40 -40
- package/bin/holoscript.cjs +3 -0
- package/dist/GLTFPipeline-SFIORFJU.js +16 -0
- package/dist/GLTFPipeline-VNNDPONV.cjs +37 -0
- package/dist/{HoloScriptPlusParser-BZR5DELQ.js → HoloScriptPlusParser-7FBIFUFC.js} +6 -5
- package/dist/{HoloScriptPlusParser-SBMYDNXO.cjs → HoloScriptPlusParser-A2W7OCN2.cjs} +17 -16
- package/dist/HoloScriptPlusParser-F2Z56FJR.js +10 -0
- package/dist/HoloScriptPlusParser-WKHRIH6T.cjs +27 -0
- package/dist/{USDZExporter-MHEHXZB4.cjs → USDZExporter-3FWJ25JI.cjs} +344 -16
- package/dist/{USDZExporter-YA55ZS35.js → USDZExporter-D2HQLQYK.js} +344 -16
- package/dist/agents/index.cjs +19 -0
- package/dist/agents/index.d.ts +100 -0
- package/dist/agents/index.js +17 -0
- package/dist/chunk-22W6NGYN.js +725 -0
- package/dist/{chunk-XSUZMPVQ.cjs → chunk-27MPVJVZ.cjs} +64 -28
- package/dist/{chunk-W76ETJTI.js → chunk-2A7FURVO.js} +44 -8
- package/dist/{chunk-C7BNX4XJ.js → chunk-2B7WVIDZ.js} +11 -8
- package/dist/chunk-2BSMSUCE.js +1941 -0
- package/dist/chunk-2HLIGOKU.cjs +5546 -0
- package/dist/{chunk-GC3YU46J.js → chunk-2M2DPHKB.js} +4 -4
- package/dist/{chunk-A6GO3DPZ.cjs → chunk-2YSNA2F2.cjs} +321 -49
- package/dist/{chunk-ZL6VJ6SN.js → chunk-33XCOVE3.js} +5 -5
- package/dist/chunk-3FOKASKO.cjs +348 -0
- package/dist/{chunk-XSF76QRU.js → chunk-4C57PR42.js} +3 -3
- package/dist/chunk-4N4SXXWF.js +769 -0
- package/dist/chunk-4PDEPEQW.cjs +41 -0
- package/dist/chunk-4R6SBXDB.js +45 -0
- package/dist/chunk-4SY77NA4.cjs +413 -0
- package/dist/{chunk-74YCHHTE.js → chunk-4UUKPCY4.js} +670 -116
- package/dist/{chunk-VZNKJZTT.cjs → chunk-52ULD552.cjs} +178 -113
- package/dist/{chunk-65RFOWZI.js → chunk-5CKA5SXU.js} +441 -23
- package/dist/chunk-5FSKKMR7.cjs +2092 -0
- package/dist/{chunk-FF3Q7ADR.js → chunk-5JEU52DW.js} +5 -3
- package/dist/chunk-5N54COB6.cjs +327 -0
- package/dist/chunk-5S7RKFGR.cjs +446 -0
- package/dist/{chunk-EJA7G2C4.cjs → chunk-5WUNN6ZN.cjs} +2 -2
- package/dist/{chunk-ELLQPFAF.js → chunk-6ASWLXXN.js} +24 -10
- package/dist/chunk-6CTRH7HT.cjs +1985 -0
- package/dist/{chunk-ARNKA274.cjs → chunk-6EX3I5P4.cjs} +6 -6
- package/dist/chunk-6FGQNDR4.js +5731 -0
- package/dist/{chunk-X4YVN7H3.cjs → chunk-6KMK2UXT.cjs} +152 -56
- package/dist/{chunk-KUJRR4FJ.js → chunk-6L4VE27M.js} +36 -24
- package/dist/{chunk-RT7LJRSF.cjs → chunk-6S6TKNEA.cjs} +7357 -8312
- package/dist/chunk-77V4GTCA.js +596 -0
- package/dist/{chunk-XH7SE4HH.cjs → chunk-7AD52FRS.cjs} +19 -19
- package/dist/chunk-7OPW2KO7.cjs +639 -0
- package/dist/chunk-A6KINLZJ.js +236 -0
- package/dist/chunk-AIA52I7T.cjs +543 -0
- package/dist/chunk-AIX25INK.cjs +602 -0
- package/dist/{chunk-WN3YF33G.cjs → chunk-AO4I2Z7M.cjs} +15 -17
- package/dist/{chunk-TSWTWZ42.cjs → chunk-BPICAGBV.cjs} +376 -209
- package/dist/chunk-BRQJKJGT.cjs +20 -0
- package/dist/{chunk-3FXV5S25.cjs → chunk-C37BHB7N.cjs} +6 -3
- package/dist/{chunk-XNMEH2BI.js → chunk-CBJY23VL.js} +3 -3
- package/dist/chunk-CIWWXYHZ.cjs +50 -0
- package/dist/{chunk-NTMZSDXM.cjs → chunk-DIL6DDDN.cjs} +101 -45
- package/dist/chunk-DMXC24WV.js +404 -0
- package/dist/{chunk-SPDELRRV.cjs → chunk-DTGBOSEM.cjs} +12 -12
- package/dist/chunk-E7JP3BS3.cjs +61 -0
- package/dist/{chunk-HJJLD366.js → chunk-EKBKLK7P.js} +3 -3
- package/dist/chunk-EKYL4PE3.cjs +404 -0
- package/dist/{chunk-7N3JIJMT.js → chunk-EMMC5CSQ.js} +12 -8
- package/dist/{chunk-EUFLX2PI.js → chunk-EOBB6A4B.js} +7263 -8214
- package/dist/chunk-EOFNVCM6.js +325 -0
- package/dist/{chunk-NKRKT6V2.js → chunk-ER4GATIU.js} +11 -10
- package/dist/{chunk-N5FTS757.cjs → chunk-EXKSFGSX.cjs} +7 -148
- package/dist/{chunk-LK5IAVH6.cjs → chunk-EXUP2BUM.cjs} +27 -27
- package/dist/chunk-FDSGHPAK.js +130 -0
- package/dist/chunk-FEWUHQNM.cjs +144 -0
- package/dist/{chunk-5TOFIR6L.js → chunk-FGGJQRLZ.js} +5 -142
- package/dist/chunk-FHP6LXJS.js +415 -0
- package/dist/{chunk-7LCYLPW2.cjs → chunk-FJPADH77.cjs} +7 -4
- package/dist/{chunk-HBZYCASG.js → chunk-FXKTYFYA.js} +203 -36
- package/dist/chunk-GCMWDSBZ.cjs +729 -0
- package/dist/chunk-GJNCFRJU.cjs +125 -0
- package/dist/{chunk-I3XGTIHM.cjs → chunk-GMP623FG.cjs} +16 -13
- package/dist/{chunk-CNVM7J3M.js → chunk-GN3KDX4W.js} +149 -53
- package/dist/{chunk-WFJIDI2N.cjs → chunk-GQYKQSTC.cjs} +10 -10
- package/dist/chunk-GTU2Z2WW.cjs +262 -0
- package/dist/chunk-GZG4KA4E.js +529 -0
- package/dist/{chunk-DIEDKX5B.cjs → chunk-H3MGK7TX.cjs} +45 -33
- package/dist/{chunk-DN7UFU63.cjs → chunk-H5DZIHJP.cjs} +14 -17
- package/dist/{chunk-DH5G2JUA.cjs → chunk-HANL7K2Q.cjs} +66 -53
- package/dist/{chunk-EGIZHYJP.cjs → chunk-HCCQLAA4.cjs} +2 -13
- package/dist/{chunk-HHS6FMOU.cjs → chunk-HGVXZDSK.cjs} +178 -29
- package/dist/{chunk-LBPEZQAF.js → chunk-HRODTEEO.js} +30 -10
- package/dist/{chunk-ZGTGVSTZ.js → chunk-HYNTS5CP.js} +2 -2
- package/dist/{chunk-RE3OKSYF.cjs → chunk-HZCQO4JM.cjs} +6 -6
- package/dist/{chunk-NCUHGRTZ.js → chunk-I2O7TW6B.js} +12 -8
- package/dist/chunk-IHESJZSW.js +4490 -0
- package/dist/{chunk-7H5UNJZD.cjs → chunk-IRWWS72C.cjs} +64 -22
- package/dist/{chunk-EMO7HAKJ.cjs → chunk-IVIA7K75.cjs} +691 -133
- package/dist/chunk-IVY74O6C.js +247 -0
- package/dist/chunk-J32ZJZJH.js +554 -0
- package/dist/chunk-JD7CIZ33.js +1949 -0
- package/dist/{chunk-7X2IEJIE.cjs → chunk-JIYN45TV.cjs} +41 -42
- package/dist/{chunk-XDXZM3ZP.cjs → chunk-KHPCJRI3.cjs} +24 -21
- package/dist/chunk-KKFZ3B6J.cjs +557 -0
- package/dist/chunk-KPJL34Y7.cjs +186 -0
- package/dist/{chunk-7KPI4EKH.cjs → chunk-KQTPCYTG.cjs} +130 -50
- package/dist/{chunk-F5LVGHNT.js → chunk-KX76JUQY.js} +3 -3
- package/dist/chunk-L4LFINPO.js +623 -0
- package/dist/{chunk-2UX5LRAP.cjs → chunk-L63H3SQ4.cjs} +46 -32
- package/dist/{chunk-NLPSZT4C.js → chunk-LAOCQJ2M.js} +64 -8
- package/dist/chunk-LM2VU56C.cjs +37 -0
- package/dist/chunk-M56JSP4A.js +400 -0
- package/dist/chunk-MBOOR7X4.js +18 -0
- package/dist/{chunk-PQLGZKMC.cjs → chunk-MJVIRCUV.cjs} +31 -27
- package/dist/{chunk-AC4BSHFV.js → chunk-MSMIFMBL.js} +135 -18
- package/dist/{chunk-56IF4NTA.js → chunk-MXFUTKCO.js} +18 -18
- package/dist/{chunk-NRUB55IT.cjs → chunk-MXJ5SS53.cjs} +450 -32
- package/dist/chunk-MXWNGCRS.js +2176 -0
- package/dist/chunk-MYY4PMWX.cjs +264 -0
- package/dist/chunk-N75IH2HY.js +258 -0
- package/dist/chunk-NG77ATEW.cjs +778 -0
- package/dist/chunk-NW5G5FBQ.js +215 -0
- package/dist/{chunk-4FCZDTD5.js → chunk-OEFY723R.js} +29 -16
- package/dist/chunk-OEV5RMZO.cjs +3042 -0
- package/dist/{chunk-VSXOIUCF.cjs → chunk-OIQYIIO3.cjs} +7 -7
- package/dist/{chunk-32TWR3HE.js → chunk-OL46QLBJ.js} +3 -12
- package/dist/chunk-OPZ7XDDI.js +487 -0
- package/dist/chunk-OSYNRVOV.cjs +243 -0
- package/dist/{chunk-HUFNKFA6.js → chunk-P7YIA5LN.js} +93 -13
- package/dist/chunk-PGANYCAG.cjs +220 -0
- package/dist/{chunk-CO2VM2DK.js → chunk-QAVXL2IH.js} +62 -20
- package/dist/{chunk-BO2OKHIY.js → chunk-QCCBXSCE.js} +1640 -1311
- package/dist/{chunk-WYH4GVZ5.js → chunk-QPOQ7VPI.js} +16 -13
- package/dist/{chunk-V42NTCFH.js → chunk-QTPMJRGS.js} +2331 -17
- package/dist/{chunk-FEFHPUEM.cjs → chunk-QWNQ523V.cjs} +1705 -1382
- package/dist/{chunk-VK5AXKO3.js → chunk-R3IVNY6P.js} +166 -101
- package/dist/chunk-R75BSDH7.cjs +50 -0
- package/dist/{chunk-AIUXRS74.cjs → chunk-RMHC2VG7.cjs} +2358 -41
- package/dist/chunk-RUXGBKPS.cjs +4517 -0
- package/dist/{chunk-PLMYCCA4.js → chunk-S5IFXW6E.js} +113 -9
- package/dist/{chunk-27LWW5FU.cjs → chunk-S6YWHCKV.cjs} +5 -5
- package/dist/{chunk-SUCBB66F.js → chunk-SIEXCILW.js} +3 -3
- package/dist/{chunk-CLYEIWA5.cjs → chunk-SLU6UPJI.cjs} +5 -3
- package/dist/{chunk-H6WMMLQK.cjs → chunk-T5J7ZKP3.cjs} +454 -61
- package/dist/chunk-TDCNJHWO.js +341 -0
- package/dist/{chunk-IHOUYQIA.js → chunk-TG7O4WBC.js} +5 -5
- package/dist/chunk-THCK6ECW.js +2085 -0
- package/dist/chunk-TJHVSBP2.js +439 -0
- package/dist/chunk-TK74TR4H.js +5541 -0
- package/dist/{chunk-BU5ZAFMC.js → chunk-U4NBQJBY.js} +11 -13
- package/dist/{chunk-Y5MUAYTO.js → chunk-UD3DSHZM.js} +10 -13
- package/dist/chunk-UDMYRFDZ.js +3038 -0
- package/dist/{chunk-PPULB4GG.cjs → chunk-UOIGFQXC.cjs} +90 -68
- package/dist/{chunk-EPWRXL6S.js → chunk-URG2SJLK.js} +41 -42
- package/dist/{chunk-VJVCD5T5.cjs → chunk-V73NPPTM.cjs} +152 -35
- package/dist/chunk-VECQYRXL.js +474 -0
- package/dist/chunk-VEXPG4WN.js +1989 -0
- package/dist/{chunk-4SMUJFHL.js → chunk-VMLKSV26.js} +9 -6
- package/dist/{chunk-HKCVM6OK.cjs → chunk-VSK7W3O5.cjs} +47 -27
- package/dist/chunk-VVKVQZI6.js +55 -0
- package/dist/{chunk-KDB6BUMB.js → chunk-W55Z7QIX.js} +172 -25
- package/dist/{chunk-BY3B7ZYV.cjs → chunk-W6P2GBHH.cjs} +3 -3
- package/dist/{chunk-PBA6NXCT.cjs → chunk-W6RW64BB.cjs} +11 -8
- package/dist/chunk-WDT3JTGM.cjs +483 -0
- package/dist/{chunk-26TLYBFD.js → chunk-WKX5AMOY.js} +3 -3
- package/dist/chunk-WNNE3PO3.js +34 -0
- package/dist/chunk-WRLUBRKS.cjs +1943 -0
- package/dist/chunk-WRNEH5MO.js +3169 -0
- package/dist/{chunk-54FHG2MX.js → chunk-WRWEX5ZF.js} +7 -4
- package/dist/chunk-X3GJPRVK.cjs +3246 -0
- package/dist/{chunk-4KJ2R7VP.cjs → chunk-XFXGA5IW.cjs} +126 -22
- package/dist/{chunk-L3Z2HIWJ.cjs → chunk-XHIV6326.cjs} +4 -4
- package/dist/chunk-XJAN7CZG.cjs +432 -0
- package/dist/chunk-XL6INWKT.js +121 -0
- package/dist/{chunk-KYM4XRFG.js → chunk-XMWZG36H.js} +4 -4
- package/dist/{chunk-BKIGPPVM.js → chunk-XSFNHP2E.js} +6 -3
- package/dist/{chunk-ODGMVILH.js → chunk-XT6JY5W5.js} +25 -3
- package/dist/chunk-XXZJEFKW.cjs +490 -0
- package/dist/chunk-Y3MWXQSB.cjs +5737 -0
- package/dist/chunk-YF2I3MV3.js +46 -0
- package/dist/{chunk-CMYAWUX3.js → chunk-YIMN575O.js} +445 -53
- package/dist/chunk-YIVFJNYV.js +176 -0
- package/dist/{chunk-V2ILLPHK.cjs → chunk-YKGPCZEE.cjs} +10 -10
- package/dist/chunk-YQELFNJV.js +39 -0
- package/dist/chunk-YSCKYJOB.cjs +2196 -0
- package/dist/chunk-Z5XMPRNC.cjs +5390 -0
- package/dist/{chunk-3FYZOR7S.cjs → chunk-ZDSYWBIE.cjs} +18 -18
- package/dist/{chunk-CQDOF3G7.cjs → chunk-ZKSS47EV.cjs} +24 -19
- package/dist/chunk-ZUL5AVTX.cjs +1993 -0
- package/dist/chunk-ZXBZVXDW.js +5386 -0
- package/dist/{chunk-AW7WAELW.js → chunk-ZZ7RO2UQ.js} +314 -46
- package/dist/cli/holoscript-runner.cjs +203 -206
- package/dist/cli/holoscript-runner.js +147 -150
- package/dist/codebase/index.cjs +1 -1
- package/dist/codebase/index.d.ts +25 -0
- package/dist/codebase/index.js +1 -1
- package/dist/compiler/agent-inference.cjs +10 -8
- package/dist/compiler/agent-inference.js +6 -4
- package/dist/compiler/android-xr.cjs +12 -8
- package/dist/compiler/android-xr.js +10 -6
- package/dist/compiler/android.cjs +12 -9
- package/dist/compiler/android.js +10 -7
- package/dist/compiler/ar.cjs +9 -7
- package/dist/compiler/ar.js +7 -5
- package/dist/compiler/babylon.cjs +12 -9
- package/dist/compiler/babylon.js +11 -8
- package/dist/compiler/business-quest.cjs +43 -0
- package/dist/compiler/business-quest.js +4 -0
- package/dist/compiler/coco.cjs +1 -1
- package/dist/compiler/coco.js +1 -1
- package/dist/compiler/context.cjs +25 -0
- package/dist/compiler/context.d.ts +28 -0
- package/dist/compiler/context.js +8 -0
- package/dist/compiler/domain-block-utils.cjs +161 -151
- package/dist/compiler/domain-block-utils.js +7 -5
- package/dist/compiler/dtdl.cjs +10 -8
- package/dist/compiler/dtdl.js +7 -5
- package/dist/compiler/gltf-pipeline.cjs +9 -9
- package/dist/compiler/gltf-pipeline.js +2 -2
- package/dist/compiler/godot.cjs +9 -7
- package/dist/compiler/godot.js +8 -6
- package/dist/compiler/incremental.cjs +12 -8
- package/dist/compiler/incremental.js +7 -3
- package/dist/compiler/index.cjs +5152 -814
- package/dist/compiler/index.d.ts +404 -21
- package/dist/compiler/index.js +5063 -859
- package/dist/compiler/ios.cjs +11 -9
- package/dist/compiler/ios.js +9 -7
- package/dist/compiler/llm-provider-capabilities.cjs +25 -0
- package/dist/compiler/llm-provider-capabilities.d.ts +43 -0
- package/dist/compiler/llm-provider-capabilities.js +8 -0
- package/dist/compiler/multi-layer.cjs +14 -17
- package/dist/compiler/multi-layer.js +13 -10
- package/dist/compiler/nodetoy.cjs +5 -5
- package/dist/compiler/nodetoy.js +2 -2
- package/dist/compiler/openxr.cjs +10 -7
- package/dist/compiler/openxr.js +9 -6
- package/dist/compiler/playcanvas.cjs +10 -8
- package/dist/compiler/playcanvas.js +9 -7
- package/dist/compiler/r3f.cjs +17 -14
- package/dist/compiler/r3f.d.ts +22 -0
- package/dist/compiler/r3f.js +12 -9
- package/dist/compiler/remotion.cjs +1 -1
- package/dist/compiler/remotion.js +1 -1
- package/dist/compiler/reproducibility.cjs +1 -1
- package/dist/compiler/reproducibility.js +1 -1
- package/dist/compiler/sdf.cjs +10 -8
- package/dist/compiler/sdf.js +8 -6
- package/dist/compiler/semantic-scene.cjs +7 -7
- package/dist/compiler/semantic-scene.js +2 -2
- package/dist/compiler/state.cjs +9 -6
- package/dist/compiler/state.js +7 -4
- package/dist/compiler/trait-composition.cjs +11 -8
- package/dist/compiler/trait-composition.js +7 -4
- package/dist/compiler/unity.cjs +10 -7
- package/dist/compiler/unity.js +9 -6
- package/dist/compiler/unreal.cjs +11 -8
- package/dist/compiler/unreal.js +9 -6
- package/dist/compiler/urdf.cjs +20 -14
- package/dist/compiler/urdf.js +8 -6
- package/dist/compiler/usd-physics.cjs +10 -8
- package/dist/compiler/usd-physics.js +7 -5
- package/dist/compiler/visionos.cjs +10 -7
- package/dist/compiler/visionos.js +9 -6
- package/dist/compiler/vrchat.cjs +10 -8
- package/dist/compiler/vrchat.js +8 -6
- package/dist/compiler/vrr.cjs +10 -8
- package/dist/compiler/vrr.js +8 -6
- package/dist/compiler/wasm.cjs +13 -11
- package/dist/compiler/wasm.js +8 -6
- package/dist/compiler/webgpu.cjs +9 -7
- package/dist/compiler/webgpu.js +8 -6
- package/dist/constants.d.ts +4 -0
- package/dist/coordinators/index.cjs +1266 -0
- package/dist/coordinators/index.d.ts +260 -0
- package/dist/coordinators/index.js +1259 -0
- package/dist/debugger.cjs +9 -7
- package/dist/debugger.js +7 -5
- package/dist/entries/interop.cjs +23 -21
- package/dist/entries/interop.d.ts +9 -0
- package/dist/entries/interop.js +5 -3
- package/dist/entries/scripting.cjs +18 -17
- package/dist/entries/scripting.d.ts +7 -0
- package/dist/entries/scripting.js +8 -7
- package/dist/hololand/index.cjs +146 -0
- package/dist/hololand/index.d.ts +70 -0
- package/dist/hololand/index.js +5 -0
- package/dist/index.cjs +21396 -39967
- package/dist/index.d.ts +1496 -40
- package/dist/index.js +21066 -40142
- package/dist/math/tropical-spmv.cjs +45 -0
- package/dist/math/tropical-spmv.js +4 -0
- package/dist/math/vec3.cjs +14 -14
- package/dist/math/vec3.js +2 -2
- package/dist/ml-dsa-FSKBTE3W.cjs +1265 -0
- package/dist/ml-dsa-Z7JDKW4L.js +1265 -0
- package/dist/paper-0c-spike/index.cjs +150 -0
- package/dist/paper-0c-spike/index.d.ts +29 -0
- package/dist/paper-0c-spike/index.js +141 -0
- package/dist/parser.cjs +45 -10
- package/dist/parser.d.ts +11 -0
- package/dist/parser.js +10 -7
- package/dist/{playwright-7DTEQCBD.cjs → playwright-3AT3AKTV.cjs} +1985 -1985
- package/dist/{playwright-BIZXMLD2.js → playwright-VZPDVUEQ.js} +3 -3
- package/dist/reconstruction/index.cjs +153 -0
- package/dist/reconstruction/index.d.ts +105 -0
- package/dist/reconstruction/index.js +8 -0
- package/dist/runtime.cjs +7 -5
- package/dist/runtime.js +6 -4
- package/dist/self-improvement/index.cjs +563 -0
- package/dist/self-improvement/index.d.ts +0 -48
- package/dist/self-improvement/index.js +545 -0
- package/dist/storage/index.cjs +10 -9
- package/dist/storage/index.d.ts +24 -0
- package/dist/storage/index.js +3 -2
- package/dist/testing.cjs +25 -0
- package/dist/testing.d.ts +70 -0
- package/dist/testing.js +4 -0
- package/dist/tools/index.d.ts +33 -0
- package/dist/traitDocs/traitDocs.cjs +33 -0
- package/dist/traitDocs/traitDocs.d.ts +69 -0
- package/dist/traitDocs/traitDocs.js +7 -0
- package/dist/traits/botanical-lotus.cjs +41 -0
- package/dist/traits/botanical-lotus.d.ts +172 -0
- package/dist/traits/botanical-lotus.js +4 -0
- package/dist/traits/engines/index.cjs +520 -0
- package/dist/traits/engines/index.d.ts +111 -0
- package/dist/traits/engines/index.js +380 -0
- package/dist/traits/index.cjs +14387 -4320
- package/dist/traits/index.d.ts +197 -0
- package/dist/traits/index.js +16455 -6958
- package/dist/traits/simulation-solver-factory.cjs +13 -0
- package/dist/traits/simulation-solver-factory.d.ts +23 -0
- package/dist/traits/simulation-solver-factory.js +4 -0
- package/dist/traits/webcam-gaze.cjs +35 -0
- package/dist/traits/webcam-gaze.d.ts +17 -0
- package/dist/traits/webcam-gaze.js +4 -0
- package/dist/type-checker.cjs +6 -5
- package/dist/type-checker.js +4 -3
- package/dist/world/index.cjs +947 -0
- package/dist/world/index.d.ts +147 -0
- package/dist/world/index.js +939 -0
- package/dist/world-model/index.cjs +1446 -0
- package/dist/world-model/index.d.ts +119 -0
- package/dist/world-model/index.js +1414 -0
- package/dist/wot/index.cjs +7 -7
- package/dist/wot/index.js +2 -2
- package/package.json +150 -23
- package/dist/GLTFPipeline-3KLWWUQO.cjs +0 -34
- package/dist/GLTFPipeline-LYII2ZVQ.js +0 -13
- package/dist/chunk-3KEU5QYY.cjs +0 -175
- package/dist/chunk-6OQBLABR.js +0 -5240
- package/dist/chunk-6WNCRE6F.js +0 -126
- package/dist/chunk-C2QHVHZF.js +0 -4066
- package/dist/chunk-CN4NOESF.cjs +0 -416
- package/dist/chunk-DXVCEFZB.js +0 -2027
- package/dist/chunk-ENV7K6XA.js +0 -282
- package/dist/chunk-H7XMORZI.js +0 -2731
- package/dist/chunk-HAN4V3PF.cjs +0 -2037
- package/dist/chunk-HF4OFY25.cjs +0 -4097
- package/dist/chunk-LER4WXW5.cjs +0 -286
- package/dist/chunk-M6FU6S22.js +0 -2911
- package/dist/chunk-MWEFR6YQ.js +0 -1857
- package/dist/chunk-PJMOXFPR.cjs +0 -1861
- package/dist/chunk-QHVVVN47.cjs +0 -2033
- package/dist/chunk-QWKUKVRE.js +0 -2026
- package/dist/chunk-UITWA6DV.cjs +0 -2829
- package/dist/chunk-UQW6SLM5.js +0 -172
- package/dist/chunk-WUXIRGZP.cjs +0 -2915
- package/dist/chunk-X67XRI2T.js +0 -410
- package/dist/chunk-Y7VK5TH3.cjs +0 -129
- package/dist/chunk-YCMQQQ5U.cjs +0 -5244
- package/dist/post-quantum-JTTAAGO3.cjs +0 -6
- package/dist/post-quantum-RVPVDEPI.js +0 -4
|
@@ -1,469 +1,642 @@
|
|
|
1
|
-
import { init_R3FCompiler, MATERIAL_PRESETS } from './chunk-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { init_R3FCompiler, MATERIAL_PRESETS } from './chunk-FXKTYFYA.js';
|
|
2
|
+
import { init_ProvenanceSemiring, ProvenanceSemiring } from './chunk-TJHVSBP2.js';
|
|
3
|
+
import { init_TraitCompositor, TraitCompositor } from './chunk-4C57PR42.js';
|
|
4
|
+
import { init_PlatformConditional, platformCategory, PLATFORM_CAPABILITIES, PLATFORM_CATEGORIES } from './chunk-GZG4KA4E.js';
|
|
5
|
+
import { init_DomainBlockCompilerMixin, compileDomainBlocks, inputToUSDA, compileInputBlock, navigationToUSDA, compileNavigationBlock, renderingToUSDA, compileRenderingBlock, proceduralToUSDA, compileProceduralBlock, web3ToUSDA, compileWeb3Block, architectureToUSDA, compileArchitectureBlock, musicToUSDA, compileMusicBlock, educationToUSDA, compileEducationBlock, datavizToUSDA, compileDataVizBlock, iotToUSDA, compileIoTBlock, compileRoboticsBlock, roboticsToUSDA, compileHealthcareBlock, healthcareToUSDA, compilePaymentBlock, paymentToUSDA, compileNarrativeBlock, narrativeToUSDA, compileWeatherBlock, weatherToUSD, compileAudioSourceBlock, audioSourceToUSD, compilePostProcessingBlock, postProcessingToUSD, compileParticleBlock, particlesToUSD, compilePhysicsBlock, compileMaterialBlock, materialToUSD } from './chunk-W55Z7QIX.js';
|
|
6
|
+
import { init_CompilerBase, CompilerBase } from './chunk-QTPMJRGS.js';
|
|
7
|
+
import { parsePipeline } from './chunk-J32ZJZJH.js';
|
|
8
|
+
import { __export, __esm } from './chunk-OL46QLBJ.js';
|
|
9
|
+
import { ANSCapabilityPath } from '@holoscript/core-types/ans';
|
|
5
10
|
|
|
6
|
-
// src/compiler/
|
|
7
|
-
var
|
|
8
|
-
__export(
|
|
9
|
-
|
|
11
|
+
// src/compiler/ThreeJSCompiler.ts
|
|
12
|
+
var ThreeJSCompiler_exports = {};
|
|
13
|
+
__export(ThreeJSCompiler_exports, {
|
|
14
|
+
ThreeJSCompiler: () => ThreeJSCompiler
|
|
10
15
|
});
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
"src/compiler/
|
|
16
|
+
var SHAPE_TO_THREE_GEOMETRY, ThreeJSCompiler;
|
|
17
|
+
var init_ThreeJSCompiler = __esm({
|
|
18
|
+
"src/compiler/ThreeJSCompiler.ts"() {
|
|
19
|
+
init_TraitCompositor();
|
|
20
|
+
init_ProvenanceSemiring();
|
|
14
21
|
init_CompilerBase();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
SHAPE_TO_THREE_GEOMETRY = {
|
|
23
|
+
sphere: "SphereGeometry",
|
|
24
|
+
orb: "SphereGeometry",
|
|
25
|
+
cube: "BoxGeometry",
|
|
26
|
+
box: "BoxGeometry",
|
|
27
|
+
cylinder: "CylinderGeometry",
|
|
28
|
+
cone: "ConeGeometry",
|
|
29
|
+
pyramid: "ConeGeometry",
|
|
30
|
+
plane: "PlaneGeometry",
|
|
31
|
+
ground: "PlaneGeometry",
|
|
32
|
+
torus: "TorusGeometry",
|
|
33
|
+
ring: "TorusGeometry",
|
|
34
|
+
capsule: "CapsuleGeometry"
|
|
35
|
+
};
|
|
36
|
+
ThreeJSCompiler = class extends CompilerBase {
|
|
37
|
+
constructor(options = {}) {
|
|
38
|
+
super();
|
|
39
|
+
this.compilerName = "ThreeJSCompiler";
|
|
40
|
+
this.lines = [];
|
|
41
|
+
this.indentLevel = 0;
|
|
42
|
+
this.options = {
|
|
43
|
+
className: options.className ?? "GeneratedScene",
|
|
44
|
+
enableShadows: options.enableShadows ?? true,
|
|
45
|
+
enablePostProcessing: options.enablePostProcessing ?? false,
|
|
46
|
+
indent: options.indent ?? " ",
|
|
47
|
+
provenanceHash: options.provenanceHash ?? ""
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
getRequiredCapability() {
|
|
51
|
+
return ANSCapabilityPath.R3F;
|
|
52
|
+
}
|
|
53
|
+
compile(composition, agentToken, outputPath) {
|
|
31
54
|
this.validateCompilerAccess(agentToken, outputPath);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
return code;
|
|
43
|
-
} else {
|
|
44
|
-
const code = this.generateHTMLPage(composition.name, elements, composition);
|
|
45
|
-
if (options?.generateDocs) {
|
|
46
|
-
return {
|
|
47
|
-
output: code,
|
|
48
|
-
documentation: this.generateDocumentation(composition, code, options.docsOptions)
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
return code;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
generateReactComponent(name, objects, composition, options) {
|
|
55
|
-
this._slotImports.clear();
|
|
56
|
-
this._uiImports.clear();
|
|
57
|
-
this._stateFields.clear();
|
|
58
|
-
this._fetchCalls = [];
|
|
59
|
-
this._options = options || {};
|
|
60
|
-
const safeName = name.replace(/[^a-zA-Z0-9]/g, "");
|
|
61
|
-
if (composition?.state?.properties) {
|
|
62
|
-
for (const prop of composition.state.properties) {
|
|
63
|
-
this._stateFields.set(prop.key, prop.value ?? null);
|
|
64
|
-
}
|
|
55
|
+
this.lines = [];
|
|
56
|
+
this.indentLevel = 0;
|
|
57
|
+
this.emit("// Auto-generated by HoloScript ThreeJSCompiler");
|
|
58
|
+
this.emit(
|
|
59
|
+
`// Source: composition "${this.escapeStringValue(composition.name, "TypeScript")}"`
|
|
60
|
+
);
|
|
61
|
+
if (this.options.provenanceHash) {
|
|
62
|
+
this.emit(`// Provenance Hash: ${this.options.provenanceHash}`);
|
|
65
63
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
this.emit("");
|
|
65
|
+
this.emitImports(composition);
|
|
66
|
+
this.emit("");
|
|
67
|
+
this.emit(`export class ${this.options.className} {`);
|
|
68
|
+
this.indent();
|
|
69
|
+
this.emit("private scene: THREE.Scene;");
|
|
70
|
+
this.emit("private renderer: THREE.WebGLRenderer;");
|
|
71
|
+
this.emit("private camera: THREE.PerspectiveCamera;");
|
|
72
|
+
this.emit("private canvas: HTMLCanvasElement;");
|
|
73
|
+
this.emit("private frameId: number = 0;");
|
|
74
|
+
this.emit("");
|
|
75
|
+
this.emit("constructor(canvas: HTMLCanvasElement) {");
|
|
76
|
+
this.indent();
|
|
77
|
+
this.emit("this.canvas = canvas;");
|
|
78
|
+
this.emit("this.scene = new THREE.Scene();");
|
|
79
|
+
this.emit(
|
|
80
|
+
"this.renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: false });"
|
|
73
81
|
);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
const stateHooks = [];
|
|
81
|
-
for (const [key, value] of this._stateFields) {
|
|
82
|
-
const capitalKey = key.charAt(0).toUpperCase() + key.slice(1);
|
|
83
|
-
const initValue = JSON.stringify(value);
|
|
84
|
-
stateHooks.push(` const [${key}, set${capitalKey}] = useState(${initValue === void 0 ? "null" : initValue});`);
|
|
85
|
-
}
|
|
86
|
-
const fetchEffects = [];
|
|
87
|
-
for (const f of this._fetchCalls) {
|
|
88
|
-
fetchEffects.push(` useEffect(() => {
|
|
89
|
-
fetch(\`${f.endpoint}\`${f.method !== "GET" ? `, { method: '${f.method}' }` : ""})
|
|
90
|
-
.then(r => r.json())
|
|
91
|
-
.then(set${f.name.charAt(0).toUpperCase() + f.name.slice(1)})
|
|
92
|
-
.catch(console.error);
|
|
93
|
-
}, []);`);
|
|
94
|
-
}
|
|
95
|
-
return `${imports.join("\n")}
|
|
96
|
-
|
|
97
|
-
// @generated by HoloScript Native2DCompiler \u2014 DO NOT EDIT
|
|
98
|
-
export function ${safeName}Component() {
|
|
99
|
-
${stateHooks.join("\n")}
|
|
100
|
-
${fetchEffects.join("\n")}
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<div className="holoscript-2d-root w-full h-full">
|
|
104
|
-
${jsx}
|
|
105
|
-
</div>
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export default ${safeName}Component;
|
|
110
|
-
`;
|
|
111
|
-
}
|
|
112
|
-
generateReactNode(obj) {
|
|
113
|
-
const traits = this.extractTraits(obj);
|
|
114
|
-
if (traits.slot) {
|
|
115
|
-
const slotName = traits.slot.name || obj.name || "Slot";
|
|
116
|
-
const configuredSlot = this._options.slots?.[String(slotName)];
|
|
117
|
-
const component = traits.slot.component || configuredSlot?.component || slotName;
|
|
118
|
-
const importPath = traits.slot.import || configuredSlot?.importPath || `@/components/${component}`;
|
|
119
|
-
this._slotImports.set(slotName, { component, importPath });
|
|
120
|
-
const propsStr = traits.slot.props ? ` {...${JSON.stringify(traits.slot.props)}}` : "";
|
|
121
|
-
return `<div data-holo-slot="${slotName}">
|
|
122
|
-
<${component}${propsStr} />
|
|
123
|
-
</div>`;
|
|
124
|
-
}
|
|
125
|
-
if (traits.fetch) {
|
|
126
|
-
const name = traits.fetch.into || "data";
|
|
127
|
-
const endpoint = traits.fetch.endpoint || "/api/data";
|
|
128
|
-
const method = traits.fetch.method || "GET";
|
|
129
|
-
this._fetchCalls.push({ name, endpoint, method });
|
|
130
|
-
if (!this._stateFields.has(name)) {
|
|
131
|
-
this._stateFields.set(name, null);
|
|
132
|
-
}
|
|
82
|
+
this.emit("this.renderer.setPixelRatio(window.devicePixelRatio);");
|
|
83
|
+
this.emit("this.renderer.setSize(canvas.clientWidth, canvas.clientHeight);");
|
|
84
|
+
if (this.options.enableShadows) {
|
|
85
|
+
this.emit("this.renderer.shadowMap.enabled = true;");
|
|
86
|
+
this.emit("this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;");
|
|
133
87
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
"h3"
|
|
147
|
-
].includes(tag)) ; else if (tag === "container") {
|
|
148
|
-
tag = "div";
|
|
149
|
-
} else if (traits.link || tag === "link") {
|
|
150
|
-
tag = "a";
|
|
151
|
-
} else if (traits.button || tag === "button") {
|
|
152
|
-
tag = "button";
|
|
153
|
-
} else if (traits.image || tag === "image") {
|
|
154
|
-
tag = "img";
|
|
155
|
-
} else if (traits.input || tag === "input") {
|
|
156
|
-
tag = "input";
|
|
157
|
-
} else if (traits.text || tag === "text") {
|
|
158
|
-
tag = this.mapTextVariantToTag(traits.text?.variant || "body");
|
|
88
|
+
this.emit(
|
|
89
|
+
"this.camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000);"
|
|
90
|
+
);
|
|
91
|
+
this.emit("this.camera.position.set(0, 2, 10);");
|
|
92
|
+
this.dedent();
|
|
93
|
+
this.emit("}");
|
|
94
|
+
this.emit("");
|
|
95
|
+
this.emit("async build(): Promise<void> {");
|
|
96
|
+
this.indent();
|
|
97
|
+
if (composition.environment) this.emitEnvironment(composition.environment);
|
|
98
|
+
if (composition.lights?.length) {
|
|
99
|
+
for (const light of composition.lights) this.emitLight(light);
|
|
159
100
|
} else {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const combinedStyles = { ...styles };
|
|
172
|
-
if (traits.theme?.style) {
|
|
173
|
-
traits.theme.style.split(";").forEach((rule) => {
|
|
174
|
-
const [key, ...valueParts] = rule.split(":");
|
|
175
|
-
const value = valueParts.join(":");
|
|
176
|
-
if (key && value) {
|
|
177
|
-
const camelKey = key.trim().replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
|
178
|
-
combinedStyles[camelKey] = value.trim();
|
|
179
|
-
}
|
|
180
|
-
});
|
|
101
|
+
this.emit("// Default lighting");
|
|
102
|
+
this.emit("const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);");
|
|
103
|
+
this.emit("this.scene.add(ambientLight);");
|
|
104
|
+
this.emit("const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);");
|
|
105
|
+
this.emit("dirLight.position.set(5, 10, 5);");
|
|
106
|
+
if (this.options.enableShadows) {
|
|
107
|
+
this.emit("dirLight.castShadow = true;");
|
|
108
|
+
this.emit("dirLight.shadow.mapSize.set(2048, 2048);");
|
|
109
|
+
}
|
|
110
|
+
this.emit("this.scene.add(dirLight);");
|
|
111
|
+
this.emit("");
|
|
181
112
|
}
|
|
182
|
-
if (
|
|
183
|
-
|
|
113
|
+
if (composition.camera) this.emitCamera(composition.camera);
|
|
114
|
+
if (composition.objects?.length) {
|
|
115
|
+
for (const obj of composition.objects) this.emitObject(obj);
|
|
184
116
|
}
|
|
185
|
-
if (
|
|
186
|
-
|
|
117
|
+
if (composition.spatialGroups?.length) {
|
|
118
|
+
for (const g of composition.spatialGroups) this.emitGroup(g);
|
|
187
119
|
}
|
|
188
|
-
if (
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
} catch (e) {
|
|
195
|
-
}
|
|
120
|
+
if (composition.zones?.length) {
|
|
121
|
+
for (const z of composition.zones) this.emitZone(z);
|
|
122
|
+
}
|
|
123
|
+
if (composition.audio?.length) {
|
|
124
|
+
for (const a of composition.audio) this.emitAudio(a);
|
|
196
125
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
126
|
+
this.emitRenderLoop();
|
|
127
|
+
this.dedent();
|
|
128
|
+
this.emit("}");
|
|
129
|
+
this.emit("");
|
|
130
|
+
this.emit("dispose(): void {");
|
|
131
|
+
this.indent();
|
|
132
|
+
this.emit("cancelAnimationFrame(this.frameId);");
|
|
133
|
+
this.emit("this.renderer.dispose();");
|
|
134
|
+
this.emit("this.scene.clear();");
|
|
135
|
+
this.dedent();
|
|
136
|
+
this.emit("}");
|
|
137
|
+
this.dedent();
|
|
138
|
+
this.emit("}");
|
|
139
|
+
return this.lines.join("\n");
|
|
140
|
+
}
|
|
141
|
+
// --- Imports ---
|
|
142
|
+
emitImports(_composition) {
|
|
143
|
+
this.emit('import * as THREE from "three";');
|
|
144
|
+
if (this.options.enablePostProcessing) {
|
|
145
|
+
this.emit('import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";');
|
|
146
|
+
this.emit(
|
|
147
|
+
'import { RenderPass } from "three/addons/postprocessing/RenderPass.js";'
|
|
148
|
+
);
|
|
149
|
+
this.emit(
|
|
150
|
+
'import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";'
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// --- Environment ---
|
|
155
|
+
emitEnvironment(env) {
|
|
156
|
+
for (const prop of env.properties) {
|
|
157
|
+
if (prop.key === "background" || prop.key === "skybox" || prop.key === "preset") {
|
|
158
|
+
if (typeof prop.value === "string" && prop.value.startsWith("#")) {
|
|
159
|
+
this.emit(`this.scene.background = new THREE.Color(${this.toThreeColorHex(prop.value)});`);
|
|
207
160
|
} else {
|
|
208
|
-
|
|
161
|
+
this.emit(`// skybox: "${prop.value}" \u2014 load via THREE.CubeTextureLoader`);
|
|
162
|
+
}
|
|
163
|
+
} else if (prop.key === "fog" && typeof prop.value === "object") {
|
|
164
|
+
const fog = prop.value;
|
|
165
|
+
const near = fog.near ?? 10;
|
|
166
|
+
const far = fog.far ?? 100;
|
|
167
|
+
const color = this.toThreeColorHex(fog.color ?? "#cccccc");
|
|
168
|
+
this.emit(`this.scene.fog = new THREE.Fog(${color}, ${near}, ${far});`);
|
|
169
|
+
} else if (prop.key === "ambient_light") {
|
|
170
|
+
this.emit(
|
|
171
|
+
`this.scene.add(new THREE.AmbientLight(0xffffff, ${prop.value ?? 0.5}));`
|
|
172
|
+
);
|
|
173
|
+
} else if (prop.key === "ground") {
|
|
174
|
+
this.emit(
|
|
175
|
+
`const groundGeom = new THREE.PlaneGeometry(100, 100);`
|
|
176
|
+
);
|
|
177
|
+
this.emit(
|
|
178
|
+
`const groundMat = new THREE.MeshStandardMaterial({ color: 0x888888, roughness: 0.8 });`
|
|
179
|
+
);
|
|
180
|
+
this.emit(`const ground = new THREE.Mesh(groundGeom, groundMat);`);
|
|
181
|
+
this.emit(`ground.rotation.x = -Math.PI / 2;`);
|
|
182
|
+
if (this.options.enableShadows) {
|
|
183
|
+
this.emit(`ground.receiveShadow = true;`);
|
|
209
184
|
}
|
|
185
|
+
this.emit(`this.scene.add(ground);`);
|
|
210
186
|
}
|
|
211
187
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
let
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
188
|
+
this.emit("");
|
|
189
|
+
}
|
|
190
|
+
// --- Objects ---
|
|
191
|
+
emitObject(obj, parentVar) {
|
|
192
|
+
const v = this.sanitizeName(obj.name);
|
|
193
|
+
let geom = "cube";
|
|
194
|
+
let modelSrc;
|
|
195
|
+
let textContent;
|
|
196
|
+
let position;
|
|
197
|
+
let rotation;
|
|
198
|
+
let scale;
|
|
199
|
+
let size;
|
|
200
|
+
const mat = {};
|
|
201
|
+
for (const p of obj.properties) {
|
|
202
|
+
switch (p.key) {
|
|
203
|
+
case "geometry":
|
|
204
|
+
case "mesh":
|
|
205
|
+
case "type":
|
|
206
|
+
if (typeof p.value === "string") geom = p.value;
|
|
207
|
+
break;
|
|
208
|
+
case "position":
|
|
209
|
+
if (Array.isArray(p.value)) position = p.value;
|
|
210
|
+
break;
|
|
211
|
+
case "rotation":
|
|
212
|
+
if (Array.isArray(p.value)) rotation = p.value;
|
|
213
|
+
break;
|
|
214
|
+
case "scale":
|
|
215
|
+
scale = p.value;
|
|
216
|
+
break;
|
|
217
|
+
case "size":
|
|
218
|
+
size = p.value;
|
|
219
|
+
break;
|
|
220
|
+
case "color":
|
|
221
|
+
mat.color = p.value;
|
|
222
|
+
break;
|
|
223
|
+
case "roughness":
|
|
224
|
+
mat.roughness = p.value;
|
|
225
|
+
break;
|
|
226
|
+
case "metalness":
|
|
227
|
+
case "metallic":
|
|
228
|
+
mat.metalness = p.value;
|
|
229
|
+
break;
|
|
230
|
+
case "opacity":
|
|
231
|
+
mat.opacity = p.value;
|
|
232
|
+
break;
|
|
233
|
+
case "emissive":
|
|
234
|
+
mat.emissive = p.value;
|
|
235
|
+
break;
|
|
236
|
+
case "emissive_intensity":
|
|
237
|
+
case "emissiveIntensity":
|
|
238
|
+
mat.emissiveIntensity = p.value;
|
|
239
|
+
break;
|
|
240
|
+
case "material":
|
|
241
|
+
if (typeof p.value === "object" && p.value !== null)
|
|
242
|
+
Object.assign(mat, p.value);
|
|
243
|
+
break;
|
|
244
|
+
case "model":
|
|
245
|
+
case "src":
|
|
246
|
+
case "source":
|
|
247
|
+
if (typeof p.value === "string") modelSrc = p.value;
|
|
248
|
+
break;
|
|
249
|
+
case "text":
|
|
250
|
+
if (typeof p.value === "string") textContent = p.value;
|
|
251
|
+
break;
|
|
250
252
|
}
|
|
251
253
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
<script>
|
|
272
|
-
function navigate(path) { window.location.href = path; }
|
|
273
|
-
function submitNewsletter(e) { e.preventDefault(); alert('Subscribed!'); }
|
|
274
|
-
</script>
|
|
275
|
-
</body>
|
|
276
|
-
</html>`;
|
|
277
|
-
}
|
|
278
|
-
generateHTMLNode(obj) {
|
|
279
|
-
const node = obj;
|
|
280
|
-
const traits = this.extractTraits(obj);
|
|
281
|
-
const nodeType = typeof node.type === "string" ? node.type.toLowerCase() : void 0;
|
|
282
|
-
let tag = traits.theme?.tag || traits.panel?.tag || nodeType || "div";
|
|
283
|
-
if ([
|
|
284
|
-
"nav",
|
|
285
|
-
"section",
|
|
286
|
-
"main",
|
|
287
|
-
"footer",
|
|
288
|
-
"form",
|
|
289
|
-
"style",
|
|
290
|
-
"a",
|
|
291
|
-
"header",
|
|
292
|
-
"h1",
|
|
293
|
-
"h2",
|
|
294
|
-
"h3"
|
|
295
|
-
].includes(tag)) ; else if (tag === "container") {
|
|
296
|
-
tag = "div";
|
|
297
|
-
} else if (traits.link || tag === "link") {
|
|
298
|
-
tag = "a";
|
|
299
|
-
} else if (traits.button || tag === "button") {
|
|
300
|
-
tag = "button";
|
|
301
|
-
} else if (traits.image || tag === "image") {
|
|
302
|
-
tag = "img";
|
|
303
|
-
} else if (traits.input || tag === "input") {
|
|
304
|
-
tag = "input";
|
|
305
|
-
} else if (traits.text || tag === "text") {
|
|
306
|
-
tag = this.mapTextVariantToTag(traits.text?.variant || "body");
|
|
254
|
+
this.emit(`// Object: ${this.escapeStringValue(obj.name, "TypeScript")}`);
|
|
255
|
+
if (modelSrc) {
|
|
256
|
+
this.emit(`// GLTFLoader required for model: "${modelSrc}"`);
|
|
257
|
+
this.emit(`// import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";`);
|
|
258
|
+
this.emit(`const ${v}Loader = new GLTFLoader();`);
|
|
259
|
+
this.emit(
|
|
260
|
+
`const ${v}Gltf = await new Promise<THREE.Group>((resolve, reject) => { ${v}Loader.load("${modelSrc}", (g) => resolve(g.scene), undefined, reject); });`
|
|
261
|
+
);
|
|
262
|
+
this.emit(`const ${v} = ${v}Gltf;`);
|
|
263
|
+
this.emit(`this.scene.add(${v});`);
|
|
264
|
+
} else if (geom === "text" || textContent) {
|
|
265
|
+
this.emit(`// Text geometry requires THREE.FontLoader / troika-three-text`);
|
|
266
|
+
this.emit(`const ${v}Geom = new THREE.PlaneGeometry(2, 0.5);`);
|
|
267
|
+
this.emit(
|
|
268
|
+
`const ${v}Mat = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true });`
|
|
269
|
+
);
|
|
270
|
+
this.emit(`const ${v} = new THREE.Mesh(${v}Geom, ${v}Mat);`);
|
|
271
|
+
this.emit(`// Text content: "${textContent || ""}"`);
|
|
272
|
+
this.emit(`this.scene.add(${v});`);
|
|
307
273
|
} else {
|
|
308
|
-
|
|
274
|
+
const geomArgs = this.geometryArgs(geom, size);
|
|
275
|
+
const geomClass = SHAPE_TO_THREE_GEOMETRY[geom] ?? "BoxGeometry";
|
|
276
|
+
this.emit(`const ${v}Geom = new THREE.${geomClass}(${geomArgs});`);
|
|
277
|
+
const matProps = this.buildMaterialProps(mat);
|
|
278
|
+
this.emit(`const ${v}Mat = new THREE.MeshStandardMaterial({ ${matProps} });`);
|
|
279
|
+
this.emit(`const ${v} = new THREE.Mesh(${v}Geom, ${v}Mat);`);
|
|
280
|
+
this.emit(`this.scene.add(${v});`);
|
|
309
281
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
282
|
+
if (position)
|
|
283
|
+
this.emit(`${v}.position.set(${position[0]}, ${position[1]}, ${position[2]});`);
|
|
284
|
+
if (rotation)
|
|
285
|
+
this.emit(`${v}.rotation.set(${rotation[0]}, ${rotation[1]}, ${rotation[2]});`);
|
|
286
|
+
if (scale) {
|
|
287
|
+
if (Array.isArray(scale)) {
|
|
288
|
+
this.emit(`${v}.scale.set(${scale[0]}, ${scale[1]}, ${scale[2]});`);
|
|
289
|
+
} else {
|
|
290
|
+
this.emit(`${v}.scale.setScalar(${scale});`);
|
|
291
|
+
}
|
|
315
292
|
}
|
|
316
|
-
if (
|
|
317
|
-
|
|
293
|
+
if (parentVar) this.emit(`${parentVar}.add(${v});`);
|
|
294
|
+
const physicsTraits = (obj.traits || []).filter(
|
|
295
|
+
(t) => t.name === "physics" || t.name === "collidable"
|
|
296
|
+
);
|
|
297
|
+
if (physicsTraits.length > 0) {
|
|
298
|
+
const semiring = new ProvenanceSemiring();
|
|
299
|
+
const applications = physicsTraits.map((t) => ({
|
|
300
|
+
name: t.name,
|
|
301
|
+
config: t.config || {},
|
|
302
|
+
context: obj.provenance?.context
|
|
303
|
+
}));
|
|
304
|
+
const { config: physicsConfig } = semiring.add(applications);
|
|
305
|
+
const isStatic = (physicsConfig.type || "dynamic") === "static";
|
|
306
|
+
this.emit(
|
|
307
|
+
`// @physics \u2014 mass: ${physicsConfig.mass ?? 1}, type: ${isStatic ? "static" : "dynamic"}`
|
|
308
|
+
);
|
|
309
|
+
this.emit(
|
|
310
|
+
`// Use a physics library (cannon-es, rapier, ammo.js) to attach a rigid body to ${v}`
|
|
311
|
+
);
|
|
318
312
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
313
|
+
for (const trait of obj.traits || []) {
|
|
314
|
+
if (trait.name === "physics" || trait.name === "collidable") {
|
|
315
|
+
continue;
|
|
316
|
+
} else if (trait.name === "shadow") {
|
|
317
|
+
if (this.options.enableShadows) {
|
|
318
|
+
this.emit(`${v}.castShadow = true;`);
|
|
319
|
+
this.emit(`${v}.receiveShadow = true;`);
|
|
320
|
+
}
|
|
321
|
+
} else if (trait.name === "grabbable") {
|
|
322
|
+
this.emit(`// @grabbable \u2014 attach raycaster pointer-down handler to ${v}`);
|
|
323
|
+
} else if (trait.name === "hoverable") {
|
|
324
|
+
this.emit(`// @hoverable \u2014 attach raycaster pointer-move handler to ${v}`);
|
|
325
|
+
} else if (trait.name === "gaussian_splat") {
|
|
326
|
+
this.emit(
|
|
327
|
+
`// @gaussian_splat \u2014 use @mkkellogg/gaussian-splats-3d or three-splat for ${v}`
|
|
328
|
+
);
|
|
329
|
+
} else if (trait.name === "object_tracking") {
|
|
330
|
+
this.emit(`// @object_tracking \u2014 WebXR hit-test for ${v}`);
|
|
331
|
+
} else if (trait.name === "eye_tracked") {
|
|
332
|
+
this.emit(`// @eye_tracked \u2014 WebXR eye tracking for ${v}`);
|
|
333
|
+
} else if (trait.name === "controlnet") {
|
|
334
|
+
this.emit(
|
|
335
|
+
`// @controlnet(model: "${trait.config?.model || "canny"}") \u2014 route to inference API for ${v}`
|
|
336
|
+
);
|
|
337
|
+
} else {
|
|
338
|
+
this.emit(
|
|
339
|
+
`// @${this.escapeStringValue(trait.name, "TypeScript")}: ${JSON.stringify(trait.config || {})}`
|
|
340
|
+
);
|
|
323
341
|
}
|
|
324
|
-
props += ` style="${styleStr}"`;
|
|
325
|
-
}
|
|
326
|
-
if (classes.length > 0) {
|
|
327
|
-
props += ` class="${classes.join(" ")}"`;
|
|
328
342
|
}
|
|
329
|
-
if (traits.
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
343
|
+
if (obj.traits && obj.traits.length > 0) {
|
|
344
|
+
const traitNames = obj.traits.map((t) => t.name);
|
|
345
|
+
const compositor = new TraitCompositor();
|
|
346
|
+
const composed = compositor.compose(traitNames);
|
|
347
|
+
if (Object.keys(composed).length > 0) {
|
|
348
|
+
this.emit(`// TraitCompositor: composed ${traitNames.join(" + ")}`);
|
|
349
|
+
const composedProps = this.buildMaterialProps(composed);
|
|
350
|
+
if (composedProps) {
|
|
351
|
+
this.emit(
|
|
352
|
+
`Object.assign((${v}.material as THREE.MeshStandardMaterial), { ${composedProps} });`
|
|
353
|
+
);
|
|
334
354
|
}
|
|
335
|
-
} catch (e) {
|
|
336
355
|
}
|
|
337
356
|
}
|
|
338
|
-
if (
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
extractTraits(obj) {
|
|
361
|
-
const map = {};
|
|
362
|
-
const node = obj;
|
|
363
|
-
if (!node.traits) return map;
|
|
364
|
-
for (const t of node.traits) {
|
|
365
|
-
map[t.name] = t.config || {};
|
|
366
|
-
if (t.name === "tailwind" && typeof t.config === "string") {
|
|
367
|
-
map[t.name] = { classes: t.config };
|
|
357
|
+
if (obj.children?.length) {
|
|
358
|
+
for (const child of obj.children) this.emitObject(child, v);
|
|
359
|
+
}
|
|
360
|
+
this.emit("");
|
|
361
|
+
}
|
|
362
|
+
// --- Groups ---
|
|
363
|
+
emitGroup(group, parentVar) {
|
|
364
|
+
const v = this.sanitizeName(group.name);
|
|
365
|
+
this.emit(
|
|
366
|
+
`const ${v} = new THREE.Group(); // "${this.escapeStringValue(group.name, "TypeScript")}"`
|
|
367
|
+
);
|
|
368
|
+
for (const p of group.properties) {
|
|
369
|
+
if (p.key === "position" && Array.isArray(p.value))
|
|
370
|
+
this.emit(`${v}.position.set(${p.value[0]}, ${p.value[1]}, ${p.value[2]});`);
|
|
371
|
+
else if (p.key === "rotation" && Array.isArray(p.value))
|
|
372
|
+
this.emit(`${v}.rotation.set(${p.value[0]}, ${p.value[1]}, ${p.value[2]});`);
|
|
373
|
+
else if (p.key === "scale") {
|
|
374
|
+
if (Array.isArray(p.value)) {
|
|
375
|
+
this.emit(`${v}.scale.set(${p.value[0]}, ${p.value[1]}, ${p.value[2]});`);
|
|
376
|
+
} else {
|
|
377
|
+
this.emit(`${v}.scale.setScalar(${p.value});`);
|
|
378
|
+
}
|
|
368
379
|
}
|
|
369
380
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
return "h1";
|
|
376
|
-
case "h2":
|
|
377
|
-
return "h2";
|
|
378
|
-
case "h3":
|
|
379
|
-
return "h3";
|
|
380
|
-
case "subtitle":
|
|
381
|
-
return "h4";
|
|
382
|
-
case "caption":
|
|
383
|
-
return "span";
|
|
384
|
-
case "emoji":
|
|
385
|
-
return "span";
|
|
386
|
-
default:
|
|
387
|
-
return "p";
|
|
381
|
+
const addTarget = parentVar ? parentVar : "this.scene";
|
|
382
|
+
this.emit(`${addTarget}.add(${v});`);
|
|
383
|
+
for (const obj of group.objects) this.emitObject(obj, v);
|
|
384
|
+
if (group.groups) {
|
|
385
|
+
for (const sub of group.groups) this.emitGroup(sub, v);
|
|
388
386
|
}
|
|
387
|
+
this.emit("");
|
|
389
388
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
389
|
+
// --- Lights ---
|
|
390
|
+
emitLight(light) {
|
|
391
|
+
const v = this.sanitizeName(light.name);
|
|
392
|
+
let position;
|
|
393
|
+
let color;
|
|
394
|
+
let intensity;
|
|
395
|
+
let direction;
|
|
396
|
+
let castShadow = false;
|
|
397
|
+
let angle;
|
|
398
|
+
let distance;
|
|
399
|
+
let penumbra;
|
|
400
|
+
for (const p of light.properties) {
|
|
401
|
+
if (p.key === "position" && Array.isArray(p.value)) position = p.value;
|
|
402
|
+
else if (p.key === "color") color = p.value;
|
|
403
|
+
else if (p.key === "intensity") intensity = p.value;
|
|
404
|
+
else if (p.key === "direction" && Array.isArray(p.value)) direction = p.value;
|
|
405
|
+
else if (p.key === "cast_shadow" || p.key === "castShadow") castShadow = !!p.value;
|
|
406
|
+
else if (p.key === "angle") angle = p.value;
|
|
407
|
+
else if (p.key === "distance") distance = p.value;
|
|
408
|
+
else if (p.key === "penumbra") penumbra = p.value;
|
|
409
|
+
}
|
|
410
|
+
const colorHex = this.toThreeColorHex(color ?? "#ffffff");
|
|
411
|
+
const intStr = intensity !== void 0 ? String(intensity) : "1.0";
|
|
412
|
+
switch (light.lightType) {
|
|
413
|
+
case "hemisphere":
|
|
414
|
+
case "ambient":
|
|
415
|
+
this.emit(`const ${v} = new THREE.AmbientLight(${colorHex}, ${intStr});`);
|
|
416
|
+
this.emit(`this.scene.add(${v});`);
|
|
417
|
+
break;
|
|
418
|
+
case "directional": {
|
|
419
|
+
this.emit(`const ${v} = new THREE.DirectionalLight(${colorHex}, ${intStr});`);
|
|
420
|
+
const pos = position ?? direction ?? [5, 10, 5];
|
|
421
|
+
this.emit(`${v}.position.set(${pos[0]}, ${pos[1]}, ${pos[2]});`);
|
|
422
|
+
if (castShadow && this.options.enableShadows) {
|
|
423
|
+
this.emit(`${v}.castShadow = true;`);
|
|
424
|
+
this.emit(`${v}.shadow.mapSize.set(2048, 2048);`);
|
|
425
|
+
this.emit(`${v}.shadow.camera.near = 0.1;`);
|
|
426
|
+
this.emit(`${v}.shadow.camera.far = 500;`);
|
|
427
|
+
}
|
|
428
|
+
this.emit(`this.scene.add(${v});`);
|
|
429
|
+
break;
|
|
398
430
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
431
|
+
case "point": {
|
|
432
|
+
const distStr = distance !== void 0 ? String(distance) : "0";
|
|
433
|
+
this.emit(
|
|
434
|
+
`const ${v} = new THREE.PointLight(${colorHex}, ${intStr}, ${distStr});`
|
|
435
|
+
);
|
|
436
|
+
if (position) this.emit(`${v}.position.set(${position[0]}, ${position[1]}, ${position[2]});`);
|
|
437
|
+
if (castShadow && this.options.enableShadows) this.emit(`${v}.castShadow = true;`);
|
|
438
|
+
this.emit(`this.scene.add(${v});`);
|
|
439
|
+
break;
|
|
402
440
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
if (
|
|
431
|
-
if (
|
|
432
|
-
if (
|
|
433
|
-
if (
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
437
|
-
if (
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
if (traits.button.variant === "glow")
|
|
446
|
-
classes.push("bg-indigo-600 text-white glow-btn hover:bg-indigo-500");
|
|
447
|
-
if (traits.button.size === "lg") classes.push("px-6 py-3 text-lg");
|
|
448
|
-
if (traits.button.size === "sm") classes.push("px-3 py-1 text-sm");
|
|
449
|
-
}
|
|
450
|
-
if (traits.card) {
|
|
451
|
-
if (traits.card.shadow === "md") classes.push("shadow-md");
|
|
452
|
-
if (traits.card.shadow === "lg") classes.push("shadow-lg");
|
|
453
|
-
if (traits.card.hover === "glow") classes.push("lift-card");
|
|
454
|
-
}
|
|
455
|
-
if (traits.input) {
|
|
456
|
-
classes.push(
|
|
457
|
-
"px-4 py-2 rounded-lg border border-gray-700 bg-gray-900 text-white focus:ring-2 focus:ring-indigo-500 outline-none"
|
|
441
|
+
case "spot": {
|
|
442
|
+
const angleRad = angle !== void 0 ? `${angle} * Math.PI / 180` : "Math.PI / 6";
|
|
443
|
+
const pen = penumbra ?? 0.1;
|
|
444
|
+
this.emit(
|
|
445
|
+
`const ${v} = new THREE.SpotLight(${colorHex}, ${intStr}, ${distance ?? 0}, ${angleRad}, ${pen});`
|
|
446
|
+
);
|
|
447
|
+
if (position) this.emit(`${v}.position.set(${position[0]}, ${position[1]}, ${position[2]});`);
|
|
448
|
+
if (castShadow && this.options.enableShadows) this.emit(`${v}.castShadow = true;`);
|
|
449
|
+
this.emit(`this.scene.add(${v});`);
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
default:
|
|
453
|
+
this.emit(`// Light "${light.lightType}" not mapped \u2014 using AmbientLight fallback`);
|
|
454
|
+
this.emit(`const ${v} = new THREE.AmbientLight(${colorHex}, ${intStr});`);
|
|
455
|
+
this.emit(`this.scene.add(${v});`);
|
|
456
|
+
}
|
|
457
|
+
this.emit("");
|
|
458
|
+
}
|
|
459
|
+
// --- Camera ---
|
|
460
|
+
emitCamera(camera) {
|
|
461
|
+
let position;
|
|
462
|
+
let target;
|
|
463
|
+
let fov;
|
|
464
|
+
let near;
|
|
465
|
+
let far;
|
|
466
|
+
for (const p of camera.properties) {
|
|
467
|
+
if (p.key === "position" && Array.isArray(p.value)) position = p.value;
|
|
468
|
+
else if (p.key === "target" && Array.isArray(p.value)) target = p.value;
|
|
469
|
+
else if (p.key === "fov") fov = p.value;
|
|
470
|
+
else if (p.key === "near") near = p.value;
|
|
471
|
+
else if (p.key === "far") far = p.value;
|
|
472
|
+
}
|
|
473
|
+
if (fov !== void 0) this.emit(`this.camera.fov = ${fov};`);
|
|
474
|
+
if (near !== void 0) this.emit(`this.camera.near = ${near};`);
|
|
475
|
+
if (far !== void 0) this.emit(`this.camera.far = ${far};`);
|
|
476
|
+
if (position)
|
|
477
|
+
this.emit(
|
|
478
|
+
`this.camera.position.set(${position[0]}, ${position[1]}, ${position[2]});`
|
|
479
|
+
);
|
|
480
|
+
if (target) {
|
|
481
|
+
this.emit(
|
|
482
|
+
`this.camera.lookAt(new THREE.Vector3(${target[0]}, ${target[1]}, ${target[2]}));`
|
|
458
483
|
);
|
|
459
484
|
}
|
|
460
|
-
|
|
461
|
-
|
|
485
|
+
this.emit(`this.camera.updateProjectionMatrix();`);
|
|
486
|
+
this.emit("");
|
|
487
|
+
}
|
|
488
|
+
// --- Audio ---
|
|
489
|
+
emitAudio(audio) {
|
|
490
|
+
const v = this.sanitizeName(audio.name);
|
|
491
|
+
let src = "";
|
|
492
|
+
let loop = false;
|
|
493
|
+
let volume = 1;
|
|
494
|
+
let spatial = false;
|
|
495
|
+
for (const p of audio.properties) {
|
|
496
|
+
if (p.key === "src" || p.key === "source") src = String(p.value);
|
|
497
|
+
else if (p.key === "loop") loop = !!p.value;
|
|
498
|
+
else if (p.key === "volume") volume = p.value;
|
|
499
|
+
else if (p.key === "spatial") spatial = !!p.value;
|
|
500
|
+
}
|
|
501
|
+
if (spatial) {
|
|
502
|
+
this.emit(`const ${v}Listener = new THREE.AudioListener();`);
|
|
503
|
+
this.emit(`this.camera.add(${v}Listener);`);
|
|
504
|
+
this.emit(`const ${v} = new THREE.PositionalAudio(${v}Listener);`);
|
|
505
|
+
} else {
|
|
506
|
+
this.emit(`const ${v}Listener = new THREE.AudioListener();`);
|
|
507
|
+
this.emit(`this.camera.add(${v}Listener);`);
|
|
508
|
+
this.emit(`const ${v} = new THREE.Audio(${v}Listener);`);
|
|
462
509
|
}
|
|
463
|
-
|
|
510
|
+
this.emit(`const ${v}Loader = new THREE.AudioLoader();`);
|
|
511
|
+
this.emit(
|
|
512
|
+
`${v}Loader.load("${src}", (buffer) => { ${v}.setBuffer(buffer); ${v}.setLoop(${loop}); ${v}.setVolume(${volume}); ${v}.play(); });`
|
|
513
|
+
);
|
|
514
|
+
this.emit("");
|
|
464
515
|
}
|
|
465
|
-
|
|
466
|
-
|
|
516
|
+
// --- Zones ---
|
|
517
|
+
emitZone(zone) {
|
|
518
|
+
const v = this.sanitizeName(zone.name);
|
|
519
|
+
let shape = "box";
|
|
520
|
+
let position;
|
|
521
|
+
let size;
|
|
522
|
+
let radius;
|
|
523
|
+
for (const p of zone.properties) {
|
|
524
|
+
if (p.key === "shape") shape = String(p.value);
|
|
525
|
+
else if (p.key === "position" && Array.isArray(p.value)) position = p.value;
|
|
526
|
+
else if (p.key === "size") size = p.value;
|
|
527
|
+
else if (p.key === "radius") radius = p.value;
|
|
528
|
+
}
|
|
529
|
+
if (shape === "sphere") {
|
|
530
|
+
this.emit(
|
|
531
|
+
`const ${v}Geom = new THREE.SphereGeometry(${radius ?? 5}, 16, 16);`
|
|
532
|
+
);
|
|
533
|
+
} else {
|
|
534
|
+
const s = Array.isArray(size) ? size : [size ?? 5, size ?? 5, size ?? 5];
|
|
535
|
+
this.emit(`const ${v}Geom = new THREE.BoxGeometry(${s[0]}, ${s[1]}, ${s[2]});`);
|
|
536
|
+
}
|
|
537
|
+
this.emit(
|
|
538
|
+
`const ${v}Mat = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true, visible: false });`
|
|
539
|
+
);
|
|
540
|
+
this.emit(`const ${v} = new THREE.Mesh(${v}Geom, ${v}Mat);`);
|
|
541
|
+
if (position) this.emit(`${v}.position.set(${position[0]}, ${position[1]}, ${position[2]});`);
|
|
542
|
+
this.emit(`this.scene.add(${v}); // trigger zone (invisible)`);
|
|
543
|
+
if (zone.handlers?.length) {
|
|
544
|
+
this.emit(
|
|
545
|
+
`// Zone handlers: attach raycaster intersection checks for ${v}`
|
|
546
|
+
);
|
|
547
|
+
for (const h of zone.handlers) {
|
|
548
|
+
this.emit(
|
|
549
|
+
`// on ${this.escapeStringValue(h.event, "TypeScript")}: implement via raycaster.intersectObject(${v})`
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
this.emit("");
|
|
554
|
+
}
|
|
555
|
+
// --- Render Loop ---
|
|
556
|
+
emitRenderLoop() {
|
|
557
|
+
this.emit("// Render loop");
|
|
558
|
+
this.emit("const animate = (): void => {");
|
|
559
|
+
this.indent();
|
|
560
|
+
this.emit("this.frameId = requestAnimationFrame(animate);");
|
|
561
|
+
this.emit("this.renderer.render(this.scene, this.camera);");
|
|
562
|
+
this.dedent();
|
|
563
|
+
this.emit("};");
|
|
564
|
+
this.emit("animate();");
|
|
565
|
+
this.emit("");
|
|
566
|
+
this.emit("// Resize handler");
|
|
567
|
+
this.emit('window.addEventListener("resize", () => {');
|
|
568
|
+
this.indent();
|
|
569
|
+
this.emit("const w = this.canvas.clientWidth, h = this.canvas.clientHeight;");
|
|
570
|
+
this.emit("this.renderer.setSize(w, h);");
|
|
571
|
+
this.emit("this.camera.aspect = w / h;");
|
|
572
|
+
this.emit("this.camera.updateProjectionMatrix();");
|
|
573
|
+
this.dedent();
|
|
574
|
+
this.emit("});");
|
|
575
|
+
}
|
|
576
|
+
// --- Value Helpers ---
|
|
577
|
+
toThreeColorHex(value) {
|
|
578
|
+
if (typeof value === "string" && value.startsWith("#")) {
|
|
579
|
+
return `0x${value.slice(1)}`;
|
|
580
|
+
}
|
|
581
|
+
if (typeof value === "number") return `0x${value.toString(16).padStart(6, "0")}`;
|
|
582
|
+
return "0xffffff";
|
|
583
|
+
}
|
|
584
|
+
buildMaterialProps(mat) {
|
|
585
|
+
const parts = [];
|
|
586
|
+
if (mat.color !== void 0) {
|
|
587
|
+
parts.push(`color: ${this.toThreeColorHex(mat.color)}`);
|
|
588
|
+
}
|
|
589
|
+
if (mat.roughness !== void 0) parts.push(`roughness: ${mat.roughness}`);
|
|
590
|
+
if (mat.metalness !== void 0) parts.push(`metalness: ${mat.metalness}`);
|
|
591
|
+
if (mat.opacity !== void 0 && mat.opacity < 1) {
|
|
592
|
+
parts.push(`opacity: ${mat.opacity}`, "transparent: true");
|
|
593
|
+
}
|
|
594
|
+
if (mat.emissive !== void 0) {
|
|
595
|
+
parts.push(`emissive: ${this.toThreeColorHex(mat.emissive)}`);
|
|
596
|
+
}
|
|
597
|
+
if (mat.emissiveIntensity !== void 0) {
|
|
598
|
+
parts.push(`emissiveIntensity: ${mat.emissiveIntensity}`);
|
|
599
|
+
}
|
|
600
|
+
return parts.join(", ");
|
|
601
|
+
}
|
|
602
|
+
geometryArgs(type, size) {
|
|
603
|
+
const s = typeof size === "number" ? size : 1;
|
|
604
|
+
switch (type) {
|
|
605
|
+
case "sphere":
|
|
606
|
+
case "orb":
|
|
607
|
+
return `${s * 0.5}, 32, 32`;
|
|
608
|
+
case "cube":
|
|
609
|
+
case "box":
|
|
610
|
+
return `${s}, ${s}, ${s}`;
|
|
611
|
+
case "cylinder":
|
|
612
|
+
return `${s * 0.5}, ${s * 0.5}, ${s * 2}, 32`;
|
|
613
|
+
case "cone":
|
|
614
|
+
case "pyramid":
|
|
615
|
+
return `${s * 0.5}, ${s * 2}, ${type === "pyramid" ? 4 : 32}`;
|
|
616
|
+
case "plane":
|
|
617
|
+
case "ground":
|
|
618
|
+
return `${s}, ${s}`;
|
|
619
|
+
case "torus":
|
|
620
|
+
case "ring":
|
|
621
|
+
return `${s * 0.5}, ${s * 0.15}, 16, 64`;
|
|
622
|
+
case "capsule":
|
|
623
|
+
return `${s * 0.3}, ${s * 0.6}, 4, 16`;
|
|
624
|
+
default:
|
|
625
|
+
return `${s}, ${s}, ${s}`;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
// --- Emit Helpers ---
|
|
629
|
+
emit(line) {
|
|
630
|
+
this.lines.push(this.options.indent.repeat(this.indentLevel) + line);
|
|
631
|
+
}
|
|
632
|
+
indent() {
|
|
633
|
+
this.indentLevel++;
|
|
634
|
+
}
|
|
635
|
+
dedent() {
|
|
636
|
+
this.indentLevel = Math.max(0, this.indentLevel - 1);
|
|
637
|
+
}
|
|
638
|
+
sanitizeName(name) {
|
|
639
|
+
return name.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
467
640
|
}
|
|
468
641
|
};
|
|
469
642
|
}
|
|
@@ -479,7 +652,6 @@ var A2AAgentCardCompiler, A2AAgentCardCompiler_default;
|
|
|
479
652
|
var init_A2AAgentCardCompiler = __esm({
|
|
480
653
|
"src/compiler/A2AAgentCardCompiler.ts"() {
|
|
481
654
|
init_CompilerBase();
|
|
482
|
-
init_ANSNamespace();
|
|
483
655
|
A2AAgentCardCompiler = class extends CompilerBase {
|
|
484
656
|
constructor(options = {}) {
|
|
485
657
|
super();
|
|
@@ -633,9 +805,7 @@ var init_A2AAgentCardCompiler = __esm({
|
|
|
633
805
|
}
|
|
634
806
|
}
|
|
635
807
|
if (examples.length === 0) {
|
|
636
|
-
examples.push(
|
|
637
|
-
`Create a ${this.escapeStringValue(template.name, "JSON")} instance`
|
|
638
|
-
);
|
|
808
|
+
examples.push(`Create a ${this.escapeStringValue(template.name, "JSON")} instance`);
|
|
639
809
|
}
|
|
640
810
|
return {
|
|
641
811
|
id: this.sanitizeId(template.name),
|
|
@@ -663,9 +833,7 @@ var init_A2AAgentCardCompiler = __esm({
|
|
|
663
833
|
}
|
|
664
834
|
const examples = [];
|
|
665
835
|
if (objTraitNames.includes("sensor")) {
|
|
666
|
-
examples.push(
|
|
667
|
-
`Read sensor data from ${this.escapeStringValue(obj.name, "JSON")}`
|
|
668
|
-
);
|
|
836
|
+
examples.push(`Read sensor data from ${this.escapeStringValue(obj.name, "JSON")}`);
|
|
669
837
|
}
|
|
670
838
|
if (objTraitNames.includes("networked")) {
|
|
671
839
|
examples.push(
|
|
@@ -756,26 +924,10 @@ var init_A2AAgentCardCompiler = __esm({
|
|
|
756
924
|
* Compile a domain-specific block into a specialized skill.
|
|
757
925
|
*/
|
|
758
926
|
compileDomainBlockSkill(block) {
|
|
759
|
-
const domainTags = {
|
|
760
|
-
iot: ["iot", "sensor", "telemetry", "digital-twin"],
|
|
761
|
-
robotics: ["robotics", "control", "actuator", "simulation"],
|
|
762
|
-
dataviz: ["data-visualization", "analytics", "dashboard"],
|
|
763
|
-
education: ["education", "learning", "curriculum"],
|
|
764
|
-
healthcare: ["healthcare", "medical", "monitoring"],
|
|
765
|
-
music: ["music", "audio", "composition"],
|
|
766
|
-
architecture: ["architecture", "building", "design"],
|
|
767
|
-
web3: ["web3", "blockchain", "smart-contract"],
|
|
768
|
-
physics: ["physics", "simulation", "collision"],
|
|
769
|
-
material: ["material", "rendering", "pbr"],
|
|
770
|
-
vfx: ["vfx", "particles", "visual-effects"],
|
|
771
|
-
weather: ["weather", "atmosphere", "environmental"],
|
|
772
|
-
navigation: ["navigation", "pathfinding", "ai"],
|
|
773
|
-
procedural: ["procedural", "generation", "algorithms"]
|
|
774
|
-
};
|
|
775
927
|
const tags = [
|
|
776
928
|
block.domain,
|
|
777
929
|
block.keyword,
|
|
778
|
-
...domainTags
|
|
930
|
+
...block.domainTags?.length ? block.domainTags : [],
|
|
779
931
|
...block.traits
|
|
780
932
|
];
|
|
781
933
|
return {
|
|
@@ -943,9 +1095,7 @@ var init_A2AAgentCardCompiler = __esm({
|
|
|
943
1095
|
*/
|
|
944
1096
|
generateDescription(composition) {
|
|
945
1097
|
const parts = [];
|
|
946
|
-
parts.push(
|
|
947
|
-
`HoloScript agent "${this.escapeStringValue(composition.name, "JSON")}"`
|
|
948
|
-
);
|
|
1098
|
+
parts.push(`HoloScript agent "${this.escapeStringValue(composition.name, "JSON")}"`);
|
|
949
1099
|
const features = [];
|
|
950
1100
|
if (composition.templates?.length) {
|
|
951
1101
|
features.push(`${composition.templates.length} template(s)`);
|
|
@@ -1564,7 +1714,6 @@ var NIRCompiler, NIRCompiler_default;
|
|
|
1564
1714
|
var init_NIRCompiler = __esm({
|
|
1565
1715
|
"src/compiler/NIRCompiler.ts"() {
|
|
1566
1716
|
init_CompilerBase();
|
|
1567
|
-
init_ANSNamespace();
|
|
1568
1717
|
init_NIRTraitMap();
|
|
1569
1718
|
NIRCompiler = class extends CompilerBase {
|
|
1570
1719
|
constructor(options = {}) {
|
|
@@ -1911,691 +2060,21 @@ var init_NIRCompiler = __esm({
|
|
|
1911
2060
|
}
|
|
1912
2061
|
});
|
|
1913
2062
|
|
|
1914
|
-
// src/parser/PipelineParser.ts
|
|
1915
|
-
function stripComments(source) {
|
|
1916
|
-
const lines = source.split("\n");
|
|
1917
|
-
return lines.map((line) => {
|
|
1918
|
-
let inString = null;
|
|
1919
|
-
for (let i = 0; i < line.length; i++) {
|
|
1920
|
-
const ch = line[i];
|
|
1921
|
-
if (inString) {
|
|
1922
|
-
if (ch === inString && line[i - 1] !== "\\") inString = null;
|
|
1923
|
-
} else if (ch === '"' || ch === "'") {
|
|
1924
|
-
inString = ch;
|
|
1925
|
-
} else if (ch === "/" && line[i + 1] === "/") {
|
|
1926
|
-
return line.substring(0, i);
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
return line;
|
|
1930
|
-
}).join("\n");
|
|
1931
|
-
}
|
|
1932
|
-
function parseDuration(value) {
|
|
1933
|
-
const match = value.match(/^(\d+)(s|m|h|d)$/);
|
|
1934
|
-
if (!match) return void 0;
|
|
1935
|
-
return { value: parseInt(match[1], 10), unit: match[2] };
|
|
1936
|
-
}
|
|
1937
|
-
function extractBlock(source, keyword, name) {
|
|
1938
|
-
const results = [];
|
|
1939
|
-
const namePattern = "(\\w+)";
|
|
1940
|
-
const regex = new RegExp(`${keyword}\\s+${namePattern}\\s*\\{`, "g");
|
|
1941
|
-
let match;
|
|
1942
|
-
while ((match = regex.exec(source)) !== null) {
|
|
1943
|
-
const blockName = match[1];
|
|
1944
|
-
const startLine = source.substring(0, match.index).split("\n").length;
|
|
1945
|
-
const startIdx = source.indexOf("{", match.index);
|
|
1946
|
-
let depth = 1;
|
|
1947
|
-
let i = startIdx + 1;
|
|
1948
|
-
while (i < source.length && depth > 0) {
|
|
1949
|
-
if (source[i] === "{") depth++;
|
|
1950
|
-
if (source[i] === "}") depth--;
|
|
1951
|
-
i++;
|
|
1952
|
-
}
|
|
1953
|
-
results.push({
|
|
1954
|
-
content: source.substring(startIdx + 1, i - 1),
|
|
1955
|
-
name: blockName,
|
|
1956
|
-
startLine
|
|
1957
|
-
});
|
|
1958
|
-
}
|
|
1959
|
-
return results;
|
|
1960
|
-
}
|
|
1961
|
-
function parseProperties(content) {
|
|
1962
|
-
const props = {};
|
|
1963
|
-
const lines = content.split("\n");
|
|
1964
|
-
for (const line of lines) {
|
|
1965
|
-
const trimmed = line.trim();
|
|
1966
|
-
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
1967
|
-
const kvMatch = trimmed.match(/^(\w+)\s*:\s+(.+)$/);
|
|
1968
|
-
if (kvMatch) {
|
|
1969
|
-
const key = kvMatch[1];
|
|
1970
|
-
let val = kvMatch[2].trim();
|
|
1971
|
-
if (typeof val === "string" && val.endsWith(",")) {
|
|
1972
|
-
val = val.slice(0, -1).trim();
|
|
1973
|
-
}
|
|
1974
|
-
if (typeof val === "string") {
|
|
1975
|
-
const strVal = val;
|
|
1976
|
-
if (strVal.startsWith('"') && strVal.endsWith('"')) {
|
|
1977
|
-
val = strVal.slice(1, -1);
|
|
1978
|
-
} else if (strVal.startsWith("'") && strVal.endsWith("'")) {
|
|
1979
|
-
val = strVal.slice(1, -1);
|
|
1980
|
-
} else if (strVal === "true") {
|
|
1981
|
-
val = true;
|
|
1982
|
-
} else if (strVal === "false") {
|
|
1983
|
-
val = false;
|
|
1984
|
-
} else if (/^\d+$/.test(strVal)) {
|
|
1985
|
-
val = parseInt(strVal, 10);
|
|
1986
|
-
} else if (/^\d+\.\d+$/.test(strVal)) {
|
|
1987
|
-
val = parseFloat(strVal);
|
|
1988
|
-
}
|
|
1989
|
-
}
|
|
1990
|
-
props[key] = val;
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
return props;
|
|
1994
|
-
}
|
|
1995
|
-
function parseNestedBlock(content, keyword) {
|
|
1996
|
-
const blocks = extractBlock(content, keyword);
|
|
1997
|
-
if (blocks.length === 0) return void 0;
|
|
1998
|
-
return parseProperties(blocks[0].content);
|
|
1999
|
-
}
|
|
2000
|
-
function parseFieldMappings(content) {
|
|
2001
|
-
const mappings = [];
|
|
2002
|
-
const lines = content.split("\n");
|
|
2003
|
-
for (const line of lines) {
|
|
2004
|
-
const trimmed = line.trim();
|
|
2005
|
-
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
2006
|
-
const mapMatch = trimmed.match(/^(\w+)\s*->\s*(\w+)(?:\s*:\s*(.+))?$/);
|
|
2007
|
-
if (mapMatch) {
|
|
2008
|
-
const transforms = mapMatch[3] ? mapMatch[3].split(":").map((t) => t.trim()).filter(Boolean) : [];
|
|
2009
|
-
mappings.push({
|
|
2010
|
-
from: mapMatch[1],
|
|
2011
|
-
to: mapMatch[2],
|
|
2012
|
-
transforms
|
|
2013
|
-
});
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
return mappings;
|
|
2017
|
-
}
|
|
2018
|
-
function parseValidateFields(content) {
|
|
2019
|
-
const fields = [];
|
|
2020
|
-
const lines = content.split("\n");
|
|
2021
|
-
for (const line of lines) {
|
|
2022
|
-
const trimmed = line.trim();
|
|
2023
|
-
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
2024
|
-
const vMatch = trimmed.match(/^(\w+)\s*:\s*(.+)$/);
|
|
2025
|
-
if (vMatch) {
|
|
2026
|
-
const rules = vMatch[2].split(",").map((r) => r.trim()).filter(Boolean);
|
|
2027
|
-
fields.push({ field: vMatch[1], rules });
|
|
2028
|
-
}
|
|
2029
|
-
}
|
|
2030
|
-
return fields;
|
|
2031
|
-
}
|
|
2032
|
-
function parseBranchRoutes(content) {
|
|
2033
|
-
const routes = [];
|
|
2034
|
-
const lines = content.split("\n");
|
|
2035
|
-
for (const line of lines) {
|
|
2036
|
-
const trimmed = line.trim();
|
|
2037
|
-
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
2038
|
-
const whenMatch = trimmed.match(/^when\s+(.+?)\s*->\s*sink\s+(\w+)$/);
|
|
2039
|
-
if (whenMatch) {
|
|
2040
|
-
routes.push({ condition: whenMatch[1], sinkName: whenMatch[2] });
|
|
2041
|
-
continue;
|
|
2042
|
-
}
|
|
2043
|
-
const defaultMatch = trimmed.match(/^default\s*->\s*sink\s+(\w+)$/);
|
|
2044
|
-
if (defaultMatch) {
|
|
2045
|
-
routes.push({ condition: "default", sinkName: defaultMatch[1] });
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
return routes;
|
|
2049
|
-
}
|
|
2050
|
-
function parseStringArray(content) {
|
|
2051
|
-
const match = content.match(/\[([\s\S]*?)\]/);
|
|
2052
|
-
if (!match) return [];
|
|
2053
|
-
return match[1].split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
|
|
2054
|
-
}
|
|
2055
|
-
function parsePipeline(source) {
|
|
2056
|
-
const errors = [];
|
|
2057
|
-
const clean = stripComments(source);
|
|
2058
|
-
const pipelineBlocks = extractBlock(clean, "pipeline");
|
|
2059
|
-
if (pipelineBlocks.length === 0) {
|
|
2060
|
-
const quotedMatch = clean.match(/pipeline\s+["']([^"']+)["']\s*\{/);
|
|
2061
|
-
if (!quotedMatch) {
|
|
2062
|
-
return { success: false, errors: [{ message: "No pipeline block found" }] };
|
|
2063
|
-
}
|
|
2064
|
-
const startIdx = clean.indexOf("{", quotedMatch.index);
|
|
2065
|
-
let depth = 1;
|
|
2066
|
-
let i = startIdx + 1;
|
|
2067
|
-
while (i < clean.length && depth > 0) {
|
|
2068
|
-
if (clean[i] === "{") depth++;
|
|
2069
|
-
if (clean[i] === "}") depth--;
|
|
2070
|
-
i++;
|
|
2071
|
-
}
|
|
2072
|
-
const pipelineContent = clean.substring(startIdx + 1, i - 1);
|
|
2073
|
-
return parsePipelineContent(quotedMatch[1], pipelineContent, errors);
|
|
2074
|
-
}
|
|
2075
|
-
return parsePipelineContent(pipelineBlocks[0].name, pipelineBlocks[0].content, errors);
|
|
2076
|
-
}
|
|
2077
|
-
function parsePipelineContent(name, content, errors) {
|
|
2078
|
-
const invalidKeywords = [
|
|
2079
|
-
"environment",
|
|
2080
|
-
"spatial_group",
|
|
2081
|
-
"template",
|
|
2082
|
-
"object",
|
|
2083
|
-
"orb",
|
|
2084
|
-
"theme",
|
|
2085
|
-
"light",
|
|
2086
|
-
"camera",
|
|
2087
|
-
"audio",
|
|
2088
|
-
"zone",
|
|
2089
|
-
"timeline",
|
|
2090
|
-
"particle_system",
|
|
2091
|
-
"effects",
|
|
2092
|
-
"ui",
|
|
2093
|
-
"npc",
|
|
2094
|
-
"quest",
|
|
2095
|
-
"dialogue",
|
|
2096
|
-
"ability",
|
|
2097
|
-
"achievement",
|
|
2098
|
-
"talent_tree",
|
|
2099
|
-
"behavior",
|
|
2100
|
-
"state_machine",
|
|
2101
|
-
"shape",
|
|
2102
|
-
"terrain",
|
|
2103
|
-
"waypoints",
|
|
2104
|
-
"spawn_group",
|
|
2105
|
-
"composition",
|
|
2106
|
-
"constraint",
|
|
2107
|
-
"sub_orb",
|
|
2108
|
-
"norm",
|
|
2109
|
-
"metanorm"
|
|
2110
|
-
];
|
|
2111
|
-
for (const keyword of invalidKeywords) {
|
|
2112
|
-
if (new RegExp(`\\b${keyword}\\b`).test(content)) {
|
|
2113
|
-
errors.push({
|
|
2114
|
-
message: `SyntaxError: '${keyword}' is not valid in a pipeline context. Use .holo for spatial compositions or .hsplus for behaviors.`
|
|
2115
|
-
});
|
|
2116
|
-
}
|
|
2117
|
-
}
|
|
2118
|
-
const props = parseProperties(content);
|
|
2119
|
-
const schedule = typeof props.schedule === "string" ? props.schedule : void 0;
|
|
2120
|
-
const timeout = typeof props.timeout === "string" ? parseDuration(props.timeout) : void 0;
|
|
2121
|
-
let retry;
|
|
2122
|
-
const retryBlock = parseNestedBlock(content, "retry");
|
|
2123
|
-
if (retryBlock) {
|
|
2124
|
-
retry = {
|
|
2125
|
-
max: typeof retryBlock.max === "number" ? retryBlock.max : 3,
|
|
2126
|
-
backoff: retryBlock.backoff || "exponential"
|
|
2127
|
-
};
|
|
2128
|
-
}
|
|
2129
|
-
const sources = [];
|
|
2130
|
-
for (const block of extractBlock(content, "source")) {
|
|
2131
|
-
const p = parseProperties(block.content);
|
|
2132
|
-
sources.push({
|
|
2133
|
-
kind: "source",
|
|
2134
|
-
name: block.name,
|
|
2135
|
-
type: p.type || "rest",
|
|
2136
|
-
endpoint: p.endpoint,
|
|
2137
|
-
path: p.path,
|
|
2138
|
-
pattern: p.pattern,
|
|
2139
|
-
since: p.since,
|
|
2140
|
-
method: p.method,
|
|
2141
|
-
auth: parseNestedBlock(block.content, "auth"),
|
|
2142
|
-
pagination: parseNestedBlock(block.content, "pagination"),
|
|
2143
|
-
properties: p
|
|
2144
|
-
});
|
|
2145
|
-
}
|
|
2146
|
-
const transforms = [];
|
|
2147
|
-
for (const block of extractBlock(content, "transform")) {
|
|
2148
|
-
const p = parseProperties(block.content);
|
|
2149
|
-
const mappings = parseFieldMappings(block.content);
|
|
2150
|
-
const hasType = p.type !== void 0;
|
|
2151
|
-
transforms.push({
|
|
2152
|
-
kind: "transform",
|
|
2153
|
-
name: block.name,
|
|
2154
|
-
type: hasType ? p.type : mappings.length > 0 ? "field_mapping" : void 0,
|
|
2155
|
-
mappings: mappings.length > 0 ? mappings : void 0,
|
|
2156
|
-
model: p.model,
|
|
2157
|
-
prompt: p.prompt,
|
|
2158
|
-
input: p.input,
|
|
2159
|
-
output: p.output,
|
|
2160
|
-
server: p.server,
|
|
2161
|
-
tool: p.tool,
|
|
2162
|
-
method: p.method,
|
|
2163
|
-
url: p.url,
|
|
2164
|
-
timeout: typeof p.timeout === "string" ? parseDuration(p.timeout) : void 0,
|
|
2165
|
-
where: p.where,
|
|
2166
|
-
properties: p
|
|
2167
|
-
});
|
|
2168
|
-
}
|
|
2169
|
-
const filters = [];
|
|
2170
|
-
for (const block of extractBlock(content, "filter")) {
|
|
2171
|
-
const p = parseProperties(block.content);
|
|
2172
|
-
if (!p.where) {
|
|
2173
|
-
errors.push({ message: `Filter "${block.name}" missing 'where' clause`, line: block.startLine, block: block.name });
|
|
2174
|
-
}
|
|
2175
|
-
filters.push({
|
|
2176
|
-
kind: "filter",
|
|
2177
|
-
name: block.name,
|
|
2178
|
-
where: p.where || ""
|
|
2179
|
-
});
|
|
2180
|
-
}
|
|
2181
|
-
const validates = [];
|
|
2182
|
-
for (const block of extractBlock(content, "validate")) {
|
|
2183
|
-
validates.push({
|
|
2184
|
-
kind: "validate",
|
|
2185
|
-
name: block.name,
|
|
2186
|
-
fields: parseValidateFields(block.content)
|
|
2187
|
-
});
|
|
2188
|
-
}
|
|
2189
|
-
const merges = [];
|
|
2190
|
-
for (const block of extractBlock(content, "merge")) {
|
|
2191
|
-
const p = parseProperties(block.content);
|
|
2192
|
-
const fromArr = typeof p.from === "string" ? parseStringArray(p.from) : [];
|
|
2193
|
-
merges.push({
|
|
2194
|
-
kind: "merge",
|
|
2195
|
-
name: block.name,
|
|
2196
|
-
from: fromArr,
|
|
2197
|
-
dedup: parseNestedBlock(block.content, "dedup"),
|
|
2198
|
-
strategy: p.strategy
|
|
2199
|
-
});
|
|
2200
|
-
}
|
|
2201
|
-
const branches = [];
|
|
2202
|
-
for (const block of extractBlock(content, "branch")) {
|
|
2203
|
-
branches.push({
|
|
2204
|
-
kind: "branch",
|
|
2205
|
-
name: block.name,
|
|
2206
|
-
routes: parseBranchRoutes(block.content)
|
|
2207
|
-
});
|
|
2208
|
-
}
|
|
2209
|
-
const sinks = [];
|
|
2210
|
-
for (const block of extractBlock(content, "sink")) {
|
|
2211
|
-
const p = parseProperties(block.content);
|
|
2212
|
-
sinks.push({
|
|
2213
|
-
kind: "sink",
|
|
2214
|
-
name: block.name,
|
|
2215
|
-
type: p.type || "rest",
|
|
2216
|
-
endpoint: p.endpoint,
|
|
2217
|
-
path: p.path,
|
|
2218
|
-
method: p.method,
|
|
2219
|
-
auth: parseNestedBlock(block.content, "auth"),
|
|
2220
|
-
batch: parseNestedBlock(block.content, "batch"),
|
|
2221
|
-
onError: parseNestedBlock(block.content, "on_error"),
|
|
2222
|
-
format: p.format,
|
|
2223
|
-
append: p.append,
|
|
2224
|
-
server: p.server,
|
|
2225
|
-
tool: p.tool,
|
|
2226
|
-
properties: p
|
|
2227
|
-
});
|
|
2228
|
-
}
|
|
2229
|
-
const steps = [
|
|
2230
|
-
...sources,
|
|
2231
|
-
...merges,
|
|
2232
|
-
...transforms,
|
|
2233
|
-
...filters,
|
|
2234
|
-
...validates,
|
|
2235
|
-
...branches,
|
|
2236
|
-
...sinks
|
|
2237
|
-
];
|
|
2238
|
-
if (sources.length === 0) {
|
|
2239
|
-
errors.push({ message: "Pipeline has no sources" });
|
|
2240
|
-
}
|
|
2241
|
-
if (sinks.length === 0) {
|
|
2242
|
-
errors.push({ message: "Pipeline has no sinks" });
|
|
2243
|
-
}
|
|
2244
|
-
const pipeline = {
|
|
2245
|
-
name,
|
|
2246
|
-
schedule,
|
|
2247
|
-
timeout,
|
|
2248
|
-
retry,
|
|
2249
|
-
steps,
|
|
2250
|
-
sources,
|
|
2251
|
-
transforms,
|
|
2252
|
-
filters,
|
|
2253
|
-
validates,
|
|
2254
|
-
merges,
|
|
2255
|
-
branches,
|
|
2256
|
-
sinks
|
|
2257
|
-
};
|
|
2258
|
-
return { success: errors.length === 0, pipeline, errors };
|
|
2259
|
-
}
|
|
2260
|
-
function isPipelineSource(source) {
|
|
2261
|
-
return /pipeline\s+["']?\w/.test(source);
|
|
2262
|
-
}
|
|
2263
|
-
|
|
2264
|
-
// src/compiler/platform/PlatformConditional.ts
|
|
2265
|
-
var PLATFORM_CATEGORIES = {
|
|
2266
|
-
vr: ["quest3", "pcvr", "visionos", "android-xr"],
|
|
2267
|
-
ar: ["visionos-ar", "android-xr-ar", "webxr"],
|
|
2268
|
-
mobile: ["ios", "android"],
|
|
2269
|
-
desktop: ["windows", "macos", "linux", "web"],
|
|
2270
|
-
automotive: ["android-auto", "carplay"],
|
|
2271
|
-
wearable: ["watchos", "wearos"]
|
|
2272
|
-
};
|
|
2273
|
-
var ALL_PLATFORMS = Object.values(
|
|
2274
|
-
PLATFORM_CATEGORIES
|
|
2275
|
-
).flat();
|
|
2276
|
-
function platformCategory(target) {
|
|
2277
|
-
for (const [cat, platforms] of Object.entries(PLATFORM_CATEGORIES)) {
|
|
2278
|
-
if (platforms.includes(target)) return cat;
|
|
2279
|
-
}
|
|
2280
|
-
return "desktop";
|
|
2281
|
-
}
|
|
2282
|
-
var PLATFORM_CAPABILITIES = {
|
|
2283
|
-
quest3: {
|
|
2284
|
-
spatialTracking: true,
|
|
2285
|
-
handTracking: true,
|
|
2286
|
-
eyeTracking: true,
|
|
2287
|
-
haptics: true,
|
|
2288
|
-
spatialAudio: true,
|
|
2289
|
-
gpu3D: true,
|
|
2290
|
-
arCamera: true,
|
|
2291
|
-
gps: false,
|
|
2292
|
-
npu: true,
|
|
2293
|
-
webxrSupport: true,
|
|
2294
|
-
frameBudgetMs: 11.1,
|
|
2295
|
-
agentBudgetMs: 5,
|
|
2296
|
-
computeModel: "edge-first"
|
|
2297
|
-
},
|
|
2298
|
-
pcvr: {
|
|
2299
|
-
spatialTracking: true,
|
|
2300
|
-
handTracking: true,
|
|
2301
|
-
eyeTracking: true,
|
|
2302
|
-
haptics: true,
|
|
2303
|
-
spatialAudio: true,
|
|
2304
|
-
gpu3D: true,
|
|
2305
|
-
arCamera: false,
|
|
2306
|
-
gps: false,
|
|
2307
|
-
npu: false,
|
|
2308
|
-
webxrSupport: true,
|
|
2309
|
-
frameBudgetMs: 11.1,
|
|
2310
|
-
agentBudgetMs: 5,
|
|
2311
|
-
computeModel: "edge-first"
|
|
2312
|
-
},
|
|
2313
|
-
visionos: {
|
|
2314
|
-
spatialTracking: true,
|
|
2315
|
-
handTracking: true,
|
|
2316
|
-
eyeTracking: true,
|
|
2317
|
-
haptics: false,
|
|
2318
|
-
spatialAudio: true,
|
|
2319
|
-
gpu3D: true,
|
|
2320
|
-
arCamera: true,
|
|
2321
|
-
gps: false,
|
|
2322
|
-
npu: true,
|
|
2323
|
-
webxrSupport: false,
|
|
2324
|
-
frameBudgetMs: 11.1,
|
|
2325
|
-
agentBudgetMs: 5,
|
|
2326
|
-
computeModel: "edge-first"
|
|
2327
|
-
},
|
|
2328
|
-
"android-xr": {
|
|
2329
|
-
spatialTracking: true,
|
|
2330
|
-
handTracking: true,
|
|
2331
|
-
eyeTracking: true,
|
|
2332
|
-
haptics: true,
|
|
2333
|
-
spatialAudio: true,
|
|
2334
|
-
gpu3D: true,
|
|
2335
|
-
arCamera: true,
|
|
2336
|
-
gps: true,
|
|
2337
|
-
npu: true,
|
|
2338
|
-
webxrSupport: true,
|
|
2339
|
-
frameBudgetMs: 11.1,
|
|
2340
|
-
agentBudgetMs: 5,
|
|
2341
|
-
computeModel: "edge-first"
|
|
2342
|
-
},
|
|
2343
|
-
"visionos-ar": {
|
|
2344
|
-
spatialTracking: true,
|
|
2345
|
-
handTracking: true,
|
|
2346
|
-
eyeTracking: true,
|
|
2347
|
-
haptics: false,
|
|
2348
|
-
spatialAudio: true,
|
|
2349
|
-
gpu3D: true,
|
|
2350
|
-
arCamera: true,
|
|
2351
|
-
gps: true,
|
|
2352
|
-
npu: true,
|
|
2353
|
-
webxrSupport: false,
|
|
2354
|
-
frameBudgetMs: 16.6,
|
|
2355
|
-
agentBudgetMs: 10,
|
|
2356
|
-
computeModel: "edge-first"
|
|
2357
|
-
},
|
|
2358
|
-
"android-xr-ar": {
|
|
2359
|
-
spatialTracking: true,
|
|
2360
|
-
handTracking: true,
|
|
2361
|
-
eyeTracking: false,
|
|
2362
|
-
haptics: true,
|
|
2363
|
-
spatialAudio: true,
|
|
2364
|
-
gpu3D: true,
|
|
2365
|
-
arCamera: true,
|
|
2366
|
-
gps: true,
|
|
2367
|
-
npu: true,
|
|
2368
|
-
webxrSupport: true,
|
|
2369
|
-
frameBudgetMs: 16.6,
|
|
2370
|
-
agentBudgetMs: 10,
|
|
2371
|
-
computeModel: "edge-first"
|
|
2372
|
-
},
|
|
2373
|
-
webxr: {
|
|
2374
|
-
spatialTracking: true,
|
|
2375
|
-
handTracking: false,
|
|
2376
|
-
eyeTracking: false,
|
|
2377
|
-
haptics: false,
|
|
2378
|
-
spatialAudio: false,
|
|
2379
|
-
gpu3D: true,
|
|
2380
|
-
arCamera: true,
|
|
2381
|
-
gps: false,
|
|
2382
|
-
npu: false,
|
|
2383
|
-
webxrSupport: true,
|
|
2384
|
-
frameBudgetMs: 16.6,
|
|
2385
|
-
agentBudgetMs: 15,
|
|
2386
|
-
computeModel: "cloud-first"
|
|
2387
|
-
},
|
|
2388
|
-
ios: {
|
|
2389
|
-
spatialTracking: false,
|
|
2390
|
-
handTracking: false,
|
|
2391
|
-
eyeTracking: false,
|
|
2392
|
-
haptics: true,
|
|
2393
|
-
spatialAudio: false,
|
|
2394
|
-
gpu3D: true,
|
|
2395
|
-
arCamera: true,
|
|
2396
|
-
gps: true,
|
|
2397
|
-
npu: true,
|
|
2398
|
-
webxrSupport: false,
|
|
2399
|
-
frameBudgetMs: 16.6,
|
|
2400
|
-
agentBudgetMs: 100,
|
|
2401
|
-
computeModel: "cloud-first"
|
|
2402
|
-
},
|
|
2403
|
-
android: {
|
|
2404
|
-
spatialTracking: false,
|
|
2405
|
-
handTracking: false,
|
|
2406
|
-
eyeTracking: false,
|
|
2407
|
-
haptics: true,
|
|
2408
|
-
spatialAudio: false,
|
|
2409
|
-
gpu3D: true,
|
|
2410
|
-
arCamera: true,
|
|
2411
|
-
gps: true,
|
|
2412
|
-
npu: true,
|
|
2413
|
-
webxrSupport: true,
|
|
2414
|
-
frameBudgetMs: 16.6,
|
|
2415
|
-
agentBudgetMs: 100,
|
|
2416
|
-
computeModel: "cloud-first"
|
|
2417
|
-
},
|
|
2418
|
-
windows: {
|
|
2419
|
-
spatialTracking: false,
|
|
2420
|
-
handTracking: false,
|
|
2421
|
-
eyeTracking: false,
|
|
2422
|
-
haptics: false,
|
|
2423
|
-
spatialAudio: false,
|
|
2424
|
-
gpu3D: true,
|
|
2425
|
-
arCamera: false,
|
|
2426
|
-
gps: false,
|
|
2427
|
-
npu: false,
|
|
2428
|
-
webxrSupport: true,
|
|
2429
|
-
frameBudgetMs: 16.6,
|
|
2430
|
-
agentBudgetMs: 200,
|
|
2431
|
-
computeModel: "cloud-first"
|
|
2432
|
-
},
|
|
2433
|
-
macos: {
|
|
2434
|
-
spatialTracking: false,
|
|
2435
|
-
handTracking: false,
|
|
2436
|
-
eyeTracking: false,
|
|
2437
|
-
haptics: false,
|
|
2438
|
-
spatialAudio: false,
|
|
2439
|
-
gpu3D: true,
|
|
2440
|
-
arCamera: false,
|
|
2441
|
-
gps: false,
|
|
2442
|
-
npu: true,
|
|
2443
|
-
webxrSupport: true,
|
|
2444
|
-
frameBudgetMs: 16.6,
|
|
2445
|
-
agentBudgetMs: 200,
|
|
2446
|
-
computeModel: "cloud-first"
|
|
2447
|
-
},
|
|
2448
|
-
linux: {
|
|
2449
|
-
spatialTracking: false,
|
|
2450
|
-
handTracking: false,
|
|
2451
|
-
eyeTracking: false,
|
|
2452
|
-
haptics: false,
|
|
2453
|
-
spatialAudio: false,
|
|
2454
|
-
gpu3D: true,
|
|
2455
|
-
arCamera: false,
|
|
2456
|
-
gps: false,
|
|
2457
|
-
npu: false,
|
|
2458
|
-
webxrSupport: true,
|
|
2459
|
-
frameBudgetMs: 16.6,
|
|
2460
|
-
agentBudgetMs: 200,
|
|
2461
|
-
computeModel: "cloud-first"
|
|
2462
|
-
},
|
|
2463
|
-
web: {
|
|
2464
|
-
spatialTracking: false,
|
|
2465
|
-
handTracking: false,
|
|
2466
|
-
eyeTracking: false,
|
|
2467
|
-
haptics: false,
|
|
2468
|
-
spatialAudio: false,
|
|
2469
|
-
gpu3D: true,
|
|
2470
|
-
arCamera: false,
|
|
2471
|
-
gps: false,
|
|
2472
|
-
npu: false,
|
|
2473
|
-
webxrSupport: true,
|
|
2474
|
-
frameBudgetMs: 16.6,
|
|
2475
|
-
agentBudgetMs: 200,
|
|
2476
|
-
computeModel: "cloud-first"
|
|
2477
|
-
},
|
|
2478
|
-
"android-auto": {
|
|
2479
|
-
spatialTracking: false,
|
|
2480
|
-
handTracking: false,
|
|
2481
|
-
eyeTracking: false,
|
|
2482
|
-
haptics: false,
|
|
2483
|
-
spatialAudio: true,
|
|
2484
|
-
gpu3D: false,
|
|
2485
|
-
arCamera: false,
|
|
2486
|
-
gps: true,
|
|
2487
|
-
npu: false,
|
|
2488
|
-
webxrSupport: false,
|
|
2489
|
-
frameBudgetMs: 30,
|
|
2490
|
-
agentBudgetMs: 15,
|
|
2491
|
-
computeModel: "safety-critical"
|
|
2492
|
-
},
|
|
2493
|
-
carplay: {
|
|
2494
|
-
spatialTracking: false,
|
|
2495
|
-
handTracking: false,
|
|
2496
|
-
eyeTracking: false,
|
|
2497
|
-
haptics: false,
|
|
2498
|
-
spatialAudio: true,
|
|
2499
|
-
gpu3D: false,
|
|
2500
|
-
arCamera: false,
|
|
2501
|
-
gps: true,
|
|
2502
|
-
npu: false,
|
|
2503
|
-
webxrSupport: false,
|
|
2504
|
-
frameBudgetMs: 30,
|
|
2505
|
-
agentBudgetMs: 15,
|
|
2506
|
-
computeModel: "safety-critical"
|
|
2507
|
-
},
|
|
2508
|
-
watchos: {
|
|
2509
|
-
spatialTracking: false,
|
|
2510
|
-
handTracking: false,
|
|
2511
|
-
eyeTracking: false,
|
|
2512
|
-
haptics: true,
|
|
2513
|
-
spatialAudio: false,
|
|
2514
|
-
gpu3D: false,
|
|
2515
|
-
arCamera: false,
|
|
2516
|
-
gps: true,
|
|
2517
|
-
npu: true,
|
|
2518
|
-
webxrSupport: false,
|
|
2519
|
-
frameBudgetMs: 33.3,
|
|
2520
|
-
agentBudgetMs: 50,
|
|
2521
|
-
computeModel: "cloud-first"
|
|
2522
|
-
},
|
|
2523
|
-
wearos: {
|
|
2524
|
-
spatialTracking: false,
|
|
2525
|
-
handTracking: false,
|
|
2526
|
-
eyeTracking: false,
|
|
2527
|
-
haptics: true,
|
|
2528
|
-
spatialAudio: false,
|
|
2529
|
-
gpu3D: false,
|
|
2530
|
-
arCamera: false,
|
|
2531
|
-
gps: true,
|
|
2532
|
-
npu: false,
|
|
2533
|
-
webxrSupport: false,
|
|
2534
|
-
frameBudgetMs: 33.3,
|
|
2535
|
-
agentBudgetMs: 50,
|
|
2536
|
-
computeModel: "cloud-first"
|
|
2537
|
-
}
|
|
2538
|
-
};
|
|
2539
|
-
var DEFAULT_EMBODIMENT = {
|
|
2540
|
-
vr: "Avatar3D",
|
|
2541
|
-
ar: "SpatialPersona",
|
|
2542
|
-
mobile: "UI2D",
|
|
2543
|
-
desktop: "FullGUI",
|
|
2544
|
-
automotive: "VoiceHUD",
|
|
2545
|
-
wearable: "UI2D"
|
|
2546
|
-
};
|
|
2547
|
-
function resolvePlatforms(condition) {
|
|
2548
|
-
let platforms = /* @__PURE__ */ new Set();
|
|
2549
|
-
if (condition.include) {
|
|
2550
|
-
for (const p of condition.include) platforms.add(p);
|
|
2551
|
-
}
|
|
2552
|
-
if (condition.includeCategories) {
|
|
2553
|
-
for (const cat of condition.includeCategories) {
|
|
2554
|
-
for (const p of PLATFORM_CATEGORIES[cat]) platforms.add(p);
|
|
2555
|
-
}
|
|
2556
|
-
}
|
|
2557
|
-
if (!condition.include && !condition.includeCategories) {
|
|
2558
|
-
for (const p of ALL_PLATFORMS) platforms.add(p);
|
|
2559
|
-
}
|
|
2560
|
-
if (condition.exclude) {
|
|
2561
|
-
for (const p of condition.exclude) platforms.delete(p);
|
|
2562
|
-
}
|
|
2563
|
-
if (condition.requireCapabilities) {
|
|
2564
|
-
platforms = new Set(
|
|
2565
|
-
[...platforms].filter((p) => {
|
|
2566
|
-
const caps = PLATFORM_CAPABILITIES[p];
|
|
2567
|
-
return condition.requireCapabilities.every((cap) => {
|
|
2568
|
-
const val = caps[cap];
|
|
2569
|
-
return typeof val === "boolean" ? val : Number(val) > 0;
|
|
2570
|
-
});
|
|
2571
|
-
})
|
|
2572
|
-
);
|
|
2573
|
-
}
|
|
2574
|
-
return [...platforms];
|
|
2575
|
-
}
|
|
2576
|
-
function matchesPlatform(target, condition) {
|
|
2577
|
-
return resolvePlatforms(condition).includes(target);
|
|
2578
|
-
}
|
|
2579
|
-
function selectBlock(target, blocks) {
|
|
2580
|
-
for (const block of blocks) {
|
|
2581
|
-
if (matchesPlatform(target, block.condition)) return block.body;
|
|
2582
|
-
}
|
|
2583
|
-
return void 0;
|
|
2584
|
-
}
|
|
2585
|
-
function embodimentFor(target) {
|
|
2586
|
-
return DEFAULT_EMBODIMENT[platformCategory(target)];
|
|
2587
|
-
}
|
|
2588
|
-
function agentBudgetFor(target) {
|
|
2589
|
-
return PLATFORM_CAPABILITIES[target].agentBudgetMs;
|
|
2590
|
-
}
|
|
2591
|
-
function hasCapability(target, cap) {
|
|
2592
|
-
const val = PLATFORM_CAPABILITIES[target][cap];
|
|
2593
|
-
return typeof val === "boolean" ? val : Number(val) > 0;
|
|
2594
|
-
}
|
|
2595
|
-
|
|
2596
2063
|
// src/compiler/USDZPipeline.ts
|
|
2597
2064
|
init_DomainBlockCompilerMixin();
|
|
2598
2065
|
init_R3FCompiler();
|
|
2066
|
+
function presetString(p, k) {
|
|
2067
|
+
const v = p[k];
|
|
2068
|
+
return typeof v === "string" ? v : void 0;
|
|
2069
|
+
}
|
|
2070
|
+
function presetNumber(p, k) {
|
|
2071
|
+
const v = p[k];
|
|
2072
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
2073
|
+
}
|
|
2074
|
+
function presetBoolean(p, k) {
|
|
2075
|
+
const v = p[k];
|
|
2076
|
+
return typeof v === "boolean" ? v : void 0;
|
|
2077
|
+
}
|
|
2599
2078
|
var _USDZPipeline = class _USDZPipeline {
|
|
2600
2079
|
constructor(options = {}) {
|
|
2601
2080
|
this.materials = /* @__PURE__ */ new Map();
|
|
@@ -2816,31 +2295,47 @@ ${domainBlocksOutput}` : materials,
|
|
|
2816
2295
|
const presetName = typeof material === "string" ? material : typeof materialPreset === "string" ? materialPreset : void 0;
|
|
2817
2296
|
if (presetName && MATERIAL_PRESETS[presetName]) {
|
|
2818
2297
|
const preset = MATERIAL_PRESETS[presetName];
|
|
2819
|
-
|
|
2820
|
-
if (
|
|
2821
|
-
|
|
2822
|
-
if (
|
|
2823
|
-
|
|
2824
|
-
if (
|
|
2825
|
-
|
|
2826
|
-
if (
|
|
2827
|
-
|
|
2828
|
-
if (
|
|
2829
|
-
|
|
2830
|
-
if (
|
|
2831
|
-
|
|
2832
|
-
if (
|
|
2833
|
-
|
|
2834
|
-
if (
|
|
2835
|
-
|
|
2836
|
-
if (
|
|
2837
|
-
|
|
2838
|
-
if (
|
|
2839
|
-
|
|
2840
|
-
if (
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2298
|
+
const colorStr = presetString(preset, "color");
|
|
2299
|
+
if (colorStr) mat.baseColor = this.hexToRGB(colorStr);
|
|
2300
|
+
const metal = presetNumber(preset, "metalness");
|
|
2301
|
+
if (metal !== void 0) mat.metallic = metal;
|
|
2302
|
+
const rough = presetNumber(preset, "roughness");
|
|
2303
|
+
if (rough !== void 0) mat.roughness = rough;
|
|
2304
|
+
const op = presetNumber(preset, "opacity");
|
|
2305
|
+
if (op !== void 0) mat.opacity = op;
|
|
2306
|
+
const emissiveStr = presetString(preset, "emissive");
|
|
2307
|
+
if (emissiveStr) mat.emissiveColor = this.hexToRGB(emissiveStr);
|
|
2308
|
+
const emissiveInt = presetNumber(preset, "emissiveIntensity");
|
|
2309
|
+
if (emissiveInt !== void 0) mat.emissiveIntensity = emissiveInt;
|
|
2310
|
+
const trans = presetNumber(preset, "transmission");
|
|
2311
|
+
if (trans !== void 0) mat.transmission = trans;
|
|
2312
|
+
const ior = presetNumber(preset, "ior");
|
|
2313
|
+
if (ior !== void 0) mat.ior = ior;
|
|
2314
|
+
const thick = presetNumber(preset, "thickness");
|
|
2315
|
+
if (thick !== void 0) mat.thickness = thick;
|
|
2316
|
+
const cc = presetNumber(preset, "clearcoat");
|
|
2317
|
+
if (cc !== void 0) mat.clearcoat = cc;
|
|
2318
|
+
const ccr = presetNumber(preset, "clearcoatRoughness");
|
|
2319
|
+
if (ccr !== void 0) mat.clearcoatRoughness = ccr;
|
|
2320
|
+
const sheen = presetNumber(preset, "sheen");
|
|
2321
|
+
if (sheen !== void 0) mat.sheen = sheen;
|
|
2322
|
+
const sheenR = presetNumber(preset, "sheenRoughness");
|
|
2323
|
+
if (sheenR !== void 0) mat.sheenRoughness = sheenR;
|
|
2324
|
+
const sheenColorStr = presetString(preset, "sheenColor");
|
|
2325
|
+
if (sheenColorStr) mat.sheenColor = this.hexToRGB(sheenColorStr);
|
|
2326
|
+
const irid = presetNumber(preset, "iridescence");
|
|
2327
|
+
if (irid !== void 0) mat.iridescence = irid;
|
|
2328
|
+
const iridIor = presetNumber(preset, "iridescenceIOR");
|
|
2329
|
+
if (iridIor !== void 0) mat.iridescenceIOR = iridIor;
|
|
2330
|
+
const aniso = presetNumber(preset, "anisotropy");
|
|
2331
|
+
if (aniso !== void 0) mat.anisotropy = aniso;
|
|
2332
|
+
const anisoRot = presetNumber(preset, "anisotropyRotation");
|
|
2333
|
+
if (anisoRot !== void 0) mat.anisotropyRotation = anisoRot;
|
|
2334
|
+
const attColorStr = presetString(preset, "attenuationColor");
|
|
2335
|
+
if (attColorStr) mat.attenuationColor = this.hexToRGB(attColorStr);
|
|
2336
|
+
const attDist = presetNumber(preset, "attenuationDistance");
|
|
2337
|
+
if (attDist !== void 0) mat.attenuationDistance = attDist;
|
|
2338
|
+
if (presetBoolean(preset, "transparent") && mat.opacity === void 0) mat.opacity = 0.99;
|
|
2844
2339
|
}
|
|
2845
2340
|
if (typeof color === "string") {
|
|
2846
2341
|
mat.baseColor = this.hexToRGB(color);
|
|
@@ -3382,6 +2877,864 @@ _USDZPipeline.TEXTURE_CHANNEL_MAP = {
|
|
|
3382
2877
|
};
|
|
3383
2878
|
var USDZPipeline = _USDZPipeline;
|
|
3384
2879
|
|
|
2880
|
+
// src/compiler/GaussianSplattingCompiler.ts
|
|
2881
|
+
init_CompilerBase();
|
|
2882
|
+
var GAUSSIAN_SPLAT_TRAIT_NAME = "gaussian_splat";
|
|
2883
|
+
var MULTIPLAYER_TRAIT_NAME = "multiplayer";
|
|
2884
|
+
function detectMultiUserSharedSort(composition) {
|
|
2885
|
+
const objects = composition.objects ?? [];
|
|
2886
|
+
for (const obj of objects) {
|
|
2887
|
+
if (objectHasBothTraits(obj)) return true;
|
|
2888
|
+
}
|
|
2889
|
+
return false;
|
|
2890
|
+
}
|
|
2891
|
+
function objectHasBothTraits(obj) {
|
|
2892
|
+
const traits = obj.traits ?? [];
|
|
2893
|
+
let hasSplat = false;
|
|
2894
|
+
let hasMultiplayer = false;
|
|
2895
|
+
for (const t of traits) {
|
|
2896
|
+
if (t.name === GAUSSIAN_SPLAT_TRAIT_NAME) hasSplat = true;
|
|
2897
|
+
else if (t.name === MULTIPLAYER_TRAIT_NAME) hasMultiplayer = true;
|
|
2898
|
+
if (hasSplat && hasMultiplayer) return true;
|
|
2899
|
+
}
|
|
2900
|
+
const childrenLike = obj.children ?? obj.objects ?? [];
|
|
2901
|
+
for (const child of childrenLike) {
|
|
2902
|
+
if (objectHasBothTraits(child)) return true;
|
|
2903
|
+
}
|
|
2904
|
+
return false;
|
|
2905
|
+
}
|
|
2906
|
+
var SHARED_SORT_SHADER_PATH = "packages/engine/src/gpu/shaders/splat-shared-sort.wgsl";
|
|
2907
|
+
var GaussianSplattingCompiler = class extends CompilerBase {
|
|
2908
|
+
constructor(options = {}) {
|
|
2909
|
+
super();
|
|
2910
|
+
this.compilerName = "GaussianSplattingCompiler";
|
|
2911
|
+
this.options = {
|
|
2912
|
+
format: options.format ?? "glb",
|
|
2913
|
+
colorSpace: options.colorSpace ?? "srgb_rec709_display",
|
|
2914
|
+
generator: options.generator ?? "HoloScript GaussianSplattingCompiler v1.0.0",
|
|
2915
|
+
copyright: options.copyright ?? "",
|
|
2916
|
+
shDegree: options.shDegree ?? 0
|
|
2917
|
+
};
|
|
2918
|
+
}
|
|
2919
|
+
getRequiredCapability() {
|
|
2920
|
+
return ANSCapabilityPath.GLTF;
|
|
2921
|
+
}
|
|
2922
|
+
compile(composition, agentToken, outputPath) {
|
|
2923
|
+
this.validateCompilerAccess(agentToken, outputPath);
|
|
2924
|
+
const { data, warnings } = this.extractGaussianData(composition);
|
|
2925
|
+
const result = this.buildGLTF(data);
|
|
2926
|
+
if (warnings && warnings.length > 0) {
|
|
2927
|
+
result.warnings = warnings;
|
|
2928
|
+
}
|
|
2929
|
+
return result;
|
|
2930
|
+
}
|
|
2931
|
+
/**
|
|
2932
|
+
* Extended compile that runs the standard glTF export AND reports
|
|
2933
|
+
* compile-time WebGPU emit flags derived from trait co-occurrence.
|
|
2934
|
+
*
|
|
2935
|
+
* The standard `compile()` API is left unchanged so existing call sites
|
|
2936
|
+
* (MCP `compile_to_3dgs`, ExportManager) keep their contract. Callers that
|
|
2937
|
+
* need the shared-sort flag opt in via this method.
|
|
2938
|
+
*
|
|
2939
|
+
* @see detectMultiUserSharedSort (the detection rule)
|
|
2940
|
+
* @see SHARED_SORT_SHADER_PATH (the kernel artifact path)
|
|
2941
|
+
*/
|
|
2942
|
+
compileExtended(composition, agentToken, outputPath) {
|
|
2943
|
+
const gltf = this.compile(composition, agentToken, outputPath);
|
|
2944
|
+
const multiUserSharedSort = detectMultiUserSharedSort(composition);
|
|
2945
|
+
return {
|
|
2946
|
+
gltf,
|
|
2947
|
+
multiUserSharedSort,
|
|
2948
|
+
sharedSortShaderPath: multiUserSharedSort ? SHARED_SORT_SHADER_PATH : void 0
|
|
2949
|
+
};
|
|
2950
|
+
}
|
|
2951
|
+
/**
|
|
2952
|
+
* Instance accessor for the multi-user shared-sort detector. Mirrors the
|
|
2953
|
+
* standalone `detectMultiUserSharedSort()` export — provided so callers
|
|
2954
|
+
* holding a compiler instance can run the check without a second import.
|
|
2955
|
+
*/
|
|
2956
|
+
detectMultiUserSharedSort(composition) {
|
|
2957
|
+
return detectMultiUserSharedSort(composition);
|
|
2958
|
+
}
|
|
2959
|
+
// ─── Data extraction ────────────────────────────────────────────────────────
|
|
2960
|
+
extractGaussianData(composition) {
|
|
2961
|
+
for (const obj of composition.objects ?? []) {
|
|
2962
|
+
const trait = obj.traits?.find((t) => t.name === "gaussian_splat");
|
|
2963
|
+
if (trait && trait.config) {
|
|
2964
|
+
const p = trait.config;
|
|
2965
|
+
const positions = this.parseFloatArray(p.positions);
|
|
2966
|
+
const scales = this.parseFloatArray(p.scales);
|
|
2967
|
+
const rotations = this.parseFloatArray(p.rotations);
|
|
2968
|
+
let colors = this.parseFloatArray(p.colors);
|
|
2969
|
+
const opacities = this.parseFloatArray(p.opacities);
|
|
2970
|
+
if (positions && scales && rotations && colors && opacities) {
|
|
2971
|
+
const count = positions.length / 3;
|
|
2972
|
+
if (scales.length === count * 3 && rotations.length === count * 4 && (colors.length === count * 4 || colors.length === count * 3) && opacities.length === count) {
|
|
2973
|
+
if (colors.length === count * 3) {
|
|
2974
|
+
colors = this.expandRgbToRgba(colors, count);
|
|
2975
|
+
}
|
|
2976
|
+
return {
|
|
2977
|
+
data: {
|
|
2978
|
+
positions,
|
|
2979
|
+
scales,
|
|
2980
|
+
rotations,
|
|
2981
|
+
colors,
|
|
2982
|
+
opacities,
|
|
2983
|
+
shCoefficients: this.parseFloatArray(p.shCoefficients),
|
|
2984
|
+
count
|
|
2985
|
+
}
|
|
2986
|
+
};
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
if (positions && colors) {
|
|
2990
|
+
const count = positions.length / 3;
|
|
2991
|
+
if (colors.length === count * 3 || colors.length === count * 4) {
|
|
2992
|
+
return { data: this.computeCovarianceFromPointCloud(positions, colors) };
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
return {
|
|
2998
|
+
data: this.generateDemoGrid(),
|
|
2999
|
+
warnings: ["No valid @gaussian_splat trait data found; falling back to demo grid"]
|
|
3000
|
+
};
|
|
3001
|
+
}
|
|
3002
|
+
expandRgbToRgba(rgb, count) {
|
|
3003
|
+
const rgba = new Float32Array(count * 4);
|
|
3004
|
+
for (let i = 0; i < count; i++) {
|
|
3005
|
+
rgba[i * 4] = rgb[i * 3];
|
|
3006
|
+
rgba[i * 4 + 1] = rgb[i * 3 + 1];
|
|
3007
|
+
rgba[i * 4 + 2] = rgb[i * 3 + 2];
|
|
3008
|
+
rgba[i * 4 + 3] = 1;
|
|
3009
|
+
}
|
|
3010
|
+
return rgba;
|
|
3011
|
+
}
|
|
3012
|
+
parseFloatArray(value) {
|
|
3013
|
+
if (value instanceof Float32Array) return value;
|
|
3014
|
+
if (Array.isArray(value)) {
|
|
3015
|
+
const nums = value.map((v) => typeof v === "number" ? v : Number(v));
|
|
3016
|
+
return new Float32Array(nums);
|
|
3017
|
+
}
|
|
3018
|
+
return void 0;
|
|
3019
|
+
}
|
|
3020
|
+
// ─── Covariance from point cloud (HoloMap raw output) ───────────────────────
|
|
3021
|
+
/**
|
|
3022
|
+
* Compute per-point Gaussian parameters from a raw point cloud.
|
|
3023
|
+
*
|
|
3024
|
+
* For each point we find k nearest neighbours, compute the 3x3 covariance
|
|
3025
|
+
* matrix of that neighbourhood, eigen-decompose it via Jacobi rotations,
|
|
3026
|
+
* and derive:
|
|
3027
|
+
* - scales = sqrt(eigenvalues) (isotropic minimum clamp)
|
|
3028
|
+
* - rotation = quaternion from eigenvector basis
|
|
3029
|
+
* - opacity = 1.0 (uniform)
|
|
3030
|
+
* - colors = passed through (RGB expanded to RGBA if needed)
|
|
3031
|
+
*/
|
|
3032
|
+
computeCovarianceFromPointCloud(positions, colors) {
|
|
3033
|
+
const n = Math.floor(positions.length / 3);
|
|
3034
|
+
const k = Math.min(12, Math.max(4, n - 1));
|
|
3035
|
+
const scales = new Float32Array(n * 3);
|
|
3036
|
+
const rotations = new Float32Array(n * 4);
|
|
3037
|
+
const opacities = new Float32Array(n);
|
|
3038
|
+
let rgbaColors;
|
|
3039
|
+
if (colors.length === n * 3) {
|
|
3040
|
+
rgbaColors = this.expandRgbToRgba(colors, n);
|
|
3041
|
+
} else {
|
|
3042
|
+
rgbaColors = colors;
|
|
3043
|
+
}
|
|
3044
|
+
const grid = this.buildSpatialGrid(positions, n);
|
|
3045
|
+
for (let i = 0; i < n; i++) {
|
|
3046
|
+
const px = positions[i * 3];
|
|
3047
|
+
const py = positions[i * 3 + 1];
|
|
3048
|
+
const pz = positions[i * 3 + 2];
|
|
3049
|
+
const neighbours = this.findKNearestNeighbours(grid, positions, n, px, py, pz, k, i);
|
|
3050
|
+
let meanX = 0, meanY = 0, meanZ = 0;
|
|
3051
|
+
for (const idx of neighbours) {
|
|
3052
|
+
meanX += positions[idx * 3];
|
|
3053
|
+
meanY += positions[idx * 3 + 1];
|
|
3054
|
+
meanZ += positions[idx * 3 + 2];
|
|
3055
|
+
}
|
|
3056
|
+
const invM = 1 / neighbours.length;
|
|
3057
|
+
meanX *= invM;
|
|
3058
|
+
meanY *= invM;
|
|
3059
|
+
meanZ *= invM;
|
|
3060
|
+
let c00 = 0, c01 = 0, c02 = 0, c11 = 0, c12 = 0, c22 = 0;
|
|
3061
|
+
for (const idx of neighbours) {
|
|
3062
|
+
const dx = positions[idx * 3] - meanX;
|
|
3063
|
+
const dy = positions[idx * 3 + 1] - meanY;
|
|
3064
|
+
const dz = positions[idx * 3 + 2] - meanZ;
|
|
3065
|
+
c00 += dx * dx;
|
|
3066
|
+
c01 += dx * dy;
|
|
3067
|
+
c02 += dx * dz;
|
|
3068
|
+
c11 += dy * dy;
|
|
3069
|
+
c12 += dy * dz;
|
|
3070
|
+
c22 += dz * dz;
|
|
3071
|
+
}
|
|
3072
|
+
const invLen = 1 / (neighbours.length - 1 || 1);
|
|
3073
|
+
c00 *= invLen;
|
|
3074
|
+
c01 *= invLen;
|
|
3075
|
+
c02 *= invLen;
|
|
3076
|
+
c11 *= invLen;
|
|
3077
|
+
c12 *= invLen;
|
|
3078
|
+
c22 *= invLen;
|
|
3079
|
+
const ev = this.jacobiEigenvalues3([
|
|
3080
|
+
c00,
|
|
3081
|
+
c01,
|
|
3082
|
+
c02,
|
|
3083
|
+
c01,
|
|
3084
|
+
c11,
|
|
3085
|
+
c12,
|
|
3086
|
+
c02,
|
|
3087
|
+
c12,
|
|
3088
|
+
c22
|
|
3089
|
+
]);
|
|
3090
|
+
const minScale = 1e-3;
|
|
3091
|
+
scales[i * 3] = Math.max(minScale, Math.sqrt(Math.abs(ev.values[0])));
|
|
3092
|
+
scales[i * 3 + 1] = Math.max(minScale, Math.sqrt(Math.abs(ev.values[1])));
|
|
3093
|
+
scales[i * 3 + 2] = Math.max(minScale, Math.sqrt(Math.abs(ev.values[2])));
|
|
3094
|
+
const q = this.rotationMatrixToQuaternion(ev.vectors);
|
|
3095
|
+
rotations[i * 4] = q[0];
|
|
3096
|
+
rotations[i * 4 + 1] = q[1];
|
|
3097
|
+
rotations[i * 4 + 2] = q[2];
|
|
3098
|
+
rotations[i * 4 + 3] = q[3];
|
|
3099
|
+
opacities[i] = 1;
|
|
3100
|
+
}
|
|
3101
|
+
return {
|
|
3102
|
+
positions,
|
|
3103
|
+
scales,
|
|
3104
|
+
rotations,
|
|
3105
|
+
colors: rgbaColors,
|
|
3106
|
+
opacities,
|
|
3107
|
+
count: n
|
|
3108
|
+
};
|
|
3109
|
+
}
|
|
3110
|
+
/** Simple uniform-grid spatial hash for k-NN acceleration. */
|
|
3111
|
+
buildSpatialGrid(positions, n) {
|
|
3112
|
+
let minX = Infinity, minY = Infinity, minZ = Infinity;
|
|
3113
|
+
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
3114
|
+
for (let i = 0; i < n; i++) {
|
|
3115
|
+
const x = positions[i * 3];
|
|
3116
|
+
const y = positions[i * 3 + 1];
|
|
3117
|
+
const z = positions[i * 3 + 2];
|
|
3118
|
+
if (x < minX) minX = x;
|
|
3119
|
+
if (y < minY) minY = y;
|
|
3120
|
+
if (z < minZ) minZ = z;
|
|
3121
|
+
if (x > maxX) maxX = x;
|
|
3122
|
+
if (y > maxY) maxY = y;
|
|
3123
|
+
if (z > maxZ) maxZ = z;
|
|
3124
|
+
}
|
|
3125
|
+
const extent = Math.max(maxX - minX, maxY - minY, maxZ - minZ, 1e-6);
|
|
3126
|
+
const cellsPerAxis = Math.max(1, Math.round(Math.pow(n / 8, 1 / 3)));
|
|
3127
|
+
const cellSize = extent / cellsPerAxis;
|
|
3128
|
+
const grid = /* @__PURE__ */ new Map();
|
|
3129
|
+
for (let i = 0; i < n; i++) {
|
|
3130
|
+
const cx = Math.floor((positions[i * 3] - minX) / cellSize);
|
|
3131
|
+
const cy = Math.floor((positions[i * 3 + 1] - minY) / cellSize);
|
|
3132
|
+
const cz = Math.floor((positions[i * 3 + 2] - minZ) / cellSize);
|
|
3133
|
+
const key = `${cx},${cy},${cz}`;
|
|
3134
|
+
const arr = grid.get(key);
|
|
3135
|
+
if (arr) {
|
|
3136
|
+
arr.push(i);
|
|
3137
|
+
} else {
|
|
3138
|
+
grid.set(key, [i]);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
return grid;
|
|
3142
|
+
}
|
|
3143
|
+
findKNearestNeighbours(grid, positions, n, px, py, pz, k, selfIdx) {
|
|
3144
|
+
if (n <= 2048) {
|
|
3145
|
+
const dists = [];
|
|
3146
|
+
for (let i = 0; i < n; i++) {
|
|
3147
|
+
const dx = positions[i * 3] - px;
|
|
3148
|
+
const dy = positions[i * 3 + 1] - py;
|
|
3149
|
+
const dz = positions[i * 3 + 2] - pz;
|
|
3150
|
+
dists.push({ idx: i, d2: dx * dx + dy * dy + dz * dz });
|
|
3151
|
+
}
|
|
3152
|
+
dists.sort((a, b) => a.d2 - b.d2);
|
|
3153
|
+
return dists.slice(0, k + 1).map((d) => d.idx);
|
|
3154
|
+
}
|
|
3155
|
+
const radius = this.estimateSearchRadius(positions, n);
|
|
3156
|
+
const radius2 = radius * radius;
|
|
3157
|
+
const candidates = [];
|
|
3158
|
+
for (let i = 0; i < n; i++) {
|
|
3159
|
+
const dx = positions[i * 3] - px;
|
|
3160
|
+
const dy = positions[i * 3 + 1] - py;
|
|
3161
|
+
const dz = positions[i * 3 + 2] - pz;
|
|
3162
|
+
const d2 = dx * dx + dy * dy + dz * dz;
|
|
3163
|
+
if (d2 <= radius2) {
|
|
3164
|
+
candidates.push({ idx: i, d2 });
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
candidates.sort((a, b) => a.d2 - b.d2);
|
|
3168
|
+
return candidates.slice(0, k + 1).map((c) => c.idx);
|
|
3169
|
+
}
|
|
3170
|
+
estimateSearchRadius(positions, n) {
|
|
3171
|
+
const sampleCount = Math.min(256, n);
|
|
3172
|
+
let totalDist = 0;
|
|
3173
|
+
let counted = 0;
|
|
3174
|
+
const step = Math.max(1, Math.floor(n / sampleCount));
|
|
3175
|
+
for (let i = 0; i < n; i += step) {
|
|
3176
|
+
let minD2 = Infinity;
|
|
3177
|
+
const px = positions[i * 3];
|
|
3178
|
+
const py = positions[i * 3 + 1];
|
|
3179
|
+
const pz = positions[i * 3 + 2];
|
|
3180
|
+
for (let j = 0; j < n; j++) {
|
|
3181
|
+
if (i === j) continue;
|
|
3182
|
+
const dx = positions[j * 3] - px;
|
|
3183
|
+
const dy = positions[j * 3 + 1] - py;
|
|
3184
|
+
const dz = positions[j * 3 + 2] - pz;
|
|
3185
|
+
const d2 = dx * dx + dy * dy + dz * dz;
|
|
3186
|
+
if (d2 < minD2) minD2 = d2;
|
|
3187
|
+
}
|
|
3188
|
+
if (minD2 < Infinity) {
|
|
3189
|
+
totalDist += Math.sqrt(minD2);
|
|
3190
|
+
counted++;
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
const avg = counted > 0 ? totalDist / counted : 0.1;
|
|
3194
|
+
return avg * 3;
|
|
3195
|
+
}
|
|
3196
|
+
/** Jacobi eigenvalue decomposition for a 3x3 symmetric matrix.
|
|
3197
|
+
* Returns eigenvalues (descending) and eigenvectors as column-major 3x3.
|
|
3198
|
+
*/
|
|
3199
|
+
jacobiEigenvalues3(a) {
|
|
3200
|
+
let m = [
|
|
3201
|
+
[a[0], a[1], a[2]],
|
|
3202
|
+
[a[3], a[4], a[5]],
|
|
3203
|
+
[a[6], a[7], a[8]]
|
|
3204
|
+
];
|
|
3205
|
+
let v = [
|
|
3206
|
+
[1, 0, 0],
|
|
3207
|
+
[0, 1, 0],
|
|
3208
|
+
[0, 0, 1]
|
|
3209
|
+
];
|
|
3210
|
+
const eps = 1e-10;
|
|
3211
|
+
const maxSweeps = 50;
|
|
3212
|
+
for (let sweep = 0; sweep < maxSweeps; sweep++) {
|
|
3213
|
+
let offDiagSum = 0;
|
|
3214
|
+
for (let p = 0; p < 3; p++) {
|
|
3215
|
+
for (let q = p + 1; q < 3; q++) {
|
|
3216
|
+
offDiagSum += Math.abs(m[p][q]);
|
|
3217
|
+
if (Math.abs(m[p][q]) < eps) continue;
|
|
3218
|
+
const tau = (m[q][q] - m[p][p]) / (2 * m[p][q]);
|
|
3219
|
+
let t;
|
|
3220
|
+
if (tau >= 0) {
|
|
3221
|
+
t = 1 / (tau + Math.sqrt(1 + tau * tau));
|
|
3222
|
+
} else {
|
|
3223
|
+
t = 1 / (tau - Math.sqrt(1 + tau * tau));
|
|
3224
|
+
}
|
|
3225
|
+
const c = 1 / Math.sqrt(1 + t * t);
|
|
3226
|
+
const s = t * c;
|
|
3227
|
+
const mpp = m[p][p];
|
|
3228
|
+
const mqq = m[q][q];
|
|
3229
|
+
const mpq = m[p][q];
|
|
3230
|
+
m[p][p] = c * c * mpp - 2 * s * c * mpq + s * s * mqq;
|
|
3231
|
+
m[q][q] = s * s * mpp + 2 * s * c * mpq + c * c * mqq;
|
|
3232
|
+
m[p][q] = 0;
|
|
3233
|
+
m[q][p] = 0;
|
|
3234
|
+
for (let r = 0; r < 3; r++) {
|
|
3235
|
+
if (r !== p && r !== q) {
|
|
3236
|
+
const mr_p = m[r][p];
|
|
3237
|
+
const mr_q = m[r][q];
|
|
3238
|
+
m[r][p] = c * mr_p - s * mr_q;
|
|
3239
|
+
m[p][r] = m[r][p];
|
|
3240
|
+
m[r][q] = s * mr_p + c * mr_q;
|
|
3241
|
+
m[q][r] = m[r][q];
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
for (let r = 0; r < 3; r++) {
|
|
3245
|
+
const vr_p = v[r][p];
|
|
3246
|
+
const vr_q = v[r][q];
|
|
3247
|
+
v[r][p] = c * vr_p - s * vr_q;
|
|
3248
|
+
v[r][q] = s * vr_p + c * vr_q;
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
if (offDiagSum < eps) break;
|
|
3253
|
+
}
|
|
3254
|
+
const vals = [m[0][0], m[1][1], m[2][2]];
|
|
3255
|
+
const cols = [
|
|
3256
|
+
[v[0][0], v[1][0], v[2][0]],
|
|
3257
|
+
[v[0][1], v[1][1], v[2][1]],
|
|
3258
|
+
[v[0][2], v[1][2], v[2][2]]
|
|
3259
|
+
];
|
|
3260
|
+
const order = [0, 1, 2].sort((i, j) => vals[j] - vals[i]);
|
|
3261
|
+
return {
|
|
3262
|
+
values: [vals[order[0]], vals[order[1]], vals[order[2]]],
|
|
3263
|
+
vectors: [
|
|
3264
|
+
cols[order[0]][0],
|
|
3265
|
+
cols[order[1]][0],
|
|
3266
|
+
cols[order[2]][0],
|
|
3267
|
+
cols[order[0]][1],
|
|
3268
|
+
cols[order[1]][1],
|
|
3269
|
+
cols[order[2]][1],
|
|
3270
|
+
cols[order[0]][2],
|
|
3271
|
+
cols[order[1]][2],
|
|
3272
|
+
cols[order[2]][2]
|
|
3273
|
+
]
|
|
3274
|
+
};
|
|
3275
|
+
}
|
|
3276
|
+
rotationMatrixToQuaternion(m) {
|
|
3277
|
+
const trace = m[0] + m[4] + m[8];
|
|
3278
|
+
let qw, qx, qy, qz;
|
|
3279
|
+
if (trace > 0) {
|
|
3280
|
+
const s = 0.5 / Math.sqrt(trace + 1);
|
|
3281
|
+
qw = 0.25 / s;
|
|
3282
|
+
qx = (m[5] - m[7]) * s;
|
|
3283
|
+
qy = (m[6] - m[2]) * s;
|
|
3284
|
+
qz = (m[1] - m[3]) * s;
|
|
3285
|
+
} else if (m[0] > m[4] && m[0] > m[8]) {
|
|
3286
|
+
const s = 2 * Math.sqrt(1 + m[0] - m[4] - m[8]);
|
|
3287
|
+
qw = (m[5] - m[7]) / s;
|
|
3288
|
+
qx = 0.25 * s;
|
|
3289
|
+
qy = (m[3] + m[1]) / s;
|
|
3290
|
+
qz = (m[6] + m[2]) / s;
|
|
3291
|
+
} else if (m[4] > m[8]) {
|
|
3292
|
+
const s = 2 * Math.sqrt(1 + m[4] - m[0] - m[8]);
|
|
3293
|
+
qw = (m[6] - m[2]) / s;
|
|
3294
|
+
qx = (m[3] + m[1]) / s;
|
|
3295
|
+
qy = 0.25 * s;
|
|
3296
|
+
qz = (m[7] + m[5]) / s;
|
|
3297
|
+
} else {
|
|
3298
|
+
const s = 2 * Math.sqrt(1 + m[8] - m[0] - m[4]);
|
|
3299
|
+
qw = (m[1] - m[3]) / s;
|
|
3300
|
+
qx = (m[6] + m[2]) / s;
|
|
3301
|
+
qy = (m[7] + m[5]) / s;
|
|
3302
|
+
qz = 0.25 * s;
|
|
3303
|
+
}
|
|
3304
|
+
const norm = Math.sqrt(qx * qx + qy * qy + qz * qz + qw * qw) || 1;
|
|
3305
|
+
return [qx / norm, qy / norm, qz / norm, qw / norm];
|
|
3306
|
+
}
|
|
3307
|
+
generateDemoGrid() {
|
|
3308
|
+
const count = 8;
|
|
3309
|
+
const positions = new Float32Array(count * 3);
|
|
3310
|
+
const scales = new Float32Array(count * 3);
|
|
3311
|
+
const rotations = new Float32Array(count * 4);
|
|
3312
|
+
const colors = new Float32Array(count * 4);
|
|
3313
|
+
const opacities = new Float32Array(count);
|
|
3314
|
+
let i = 0;
|
|
3315
|
+
for (let x = 0; x < 2; x++) {
|
|
3316
|
+
for (let y = 0; y < 2; y++) {
|
|
3317
|
+
for (let z = 0; z < 2; z++) {
|
|
3318
|
+
positions[i * 3] = x * 0.5;
|
|
3319
|
+
positions[i * 3 + 1] = y * 0.5;
|
|
3320
|
+
positions[i * 3 + 2] = z * 0.5;
|
|
3321
|
+
scales[i * 3] = 0.1;
|
|
3322
|
+
scales[i * 3 + 1] = 0.1;
|
|
3323
|
+
scales[i * 3 + 2] = 0.1;
|
|
3324
|
+
rotations[i * 4] = 0;
|
|
3325
|
+
rotations[i * 4 + 1] = 0;
|
|
3326
|
+
rotations[i * 4 + 2] = 0;
|
|
3327
|
+
rotations[i * 4 + 3] = 1;
|
|
3328
|
+
colors[i * 4] = 0.8;
|
|
3329
|
+
colors[i * 4 + 1] = 0.3;
|
|
3330
|
+
colors[i * 4 + 2] = 0.3;
|
|
3331
|
+
colors[i * 4 + 3] = 1;
|
|
3332
|
+
opacities[i] = 1;
|
|
3333
|
+
i++;
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
return { positions, scales, rotations, colors, opacities, count };
|
|
3338
|
+
}
|
|
3339
|
+
// ─── glTF builder ─────────────────────────────────────────────────────────
|
|
3340
|
+
buildGLTF(data) {
|
|
3341
|
+
const N = data.count;
|
|
3342
|
+
const bufferData = this.buildBuffer(data);
|
|
3343
|
+
const bufferViews = this.buildBufferViews(N);
|
|
3344
|
+
const accessors = this.buildAccessors(N);
|
|
3345
|
+
const primitive = {
|
|
3346
|
+
attributes: {
|
|
3347
|
+
POSITION: 0,
|
|
3348
|
+
_ROTATION: 1,
|
|
3349
|
+
_SCALE: 2,
|
|
3350
|
+
_OPACITY: 3,
|
|
3351
|
+
COLOR_0: 4
|
|
3352
|
+
},
|
|
3353
|
+
mode: 0,
|
|
3354
|
+
// POINTS
|
|
3355
|
+
extensions: {
|
|
3356
|
+
KHR_gaussian_splatting: {
|
|
3357
|
+
colorSpace: this.options.colorSpace
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3360
|
+
};
|
|
3361
|
+
const mesh = {
|
|
3362
|
+
name: "GaussianSplatMesh",
|
|
3363
|
+
primitives: [primitive]
|
|
3364
|
+
};
|
|
3365
|
+
const node = {
|
|
3366
|
+
name: "GaussianSplatNode",
|
|
3367
|
+
mesh: 0
|
|
3368
|
+
};
|
|
3369
|
+
const gltf = {
|
|
3370
|
+
asset: {
|
|
3371
|
+
version: "2.0",
|
|
3372
|
+
generator: this.options.generator,
|
|
3373
|
+
...this.options.copyright ? { copyright: this.options.copyright } : {}
|
|
3374
|
+
},
|
|
3375
|
+
scene: 0,
|
|
3376
|
+
scenes: [{ name: "Scene", nodes: [0] }],
|
|
3377
|
+
nodes: [node],
|
|
3378
|
+
meshes: [mesh],
|
|
3379
|
+
accessors,
|
|
3380
|
+
bufferViews,
|
|
3381
|
+
buffers: [{ byteLength: bufferData.byteLength }],
|
|
3382
|
+
extensionsUsed: ["KHR_gaussian_splatting"]
|
|
3383
|
+
};
|
|
3384
|
+
const stats = {
|
|
3385
|
+
nodeCount: 1,
|
|
3386
|
+
meshCount: 1,
|
|
3387
|
+
materialCount: 0,
|
|
3388
|
+
textureCount: 0,
|
|
3389
|
+
animationCount: 0,
|
|
3390
|
+
totalVertices: N,
|
|
3391
|
+
totalTriangles: 0,
|
|
3392
|
+
fileSizeBytes: 0
|
|
3393
|
+
};
|
|
3394
|
+
if (this.options.format === "glb") {
|
|
3395
|
+
const binary = this.createGLB(gltf, bufferData);
|
|
3396
|
+
stats.fileSizeBytes = binary.byteLength;
|
|
3397
|
+
return { binary, stats };
|
|
3398
|
+
}
|
|
3399
|
+
stats.fileSizeBytes = JSON.stringify(gltf).length + bufferData.byteLength;
|
|
3400
|
+
return { json: gltf, buffer: bufferData, stats };
|
|
3401
|
+
}
|
|
3402
|
+
// ─── Binary layout ──────────────────────────────────────────────────────────
|
|
3403
|
+
buildBuffer(data) {
|
|
3404
|
+
const N = data.count;
|
|
3405
|
+
const logScales = new Float32Array(N * 3);
|
|
3406
|
+
for (let i = 0; i < N * 3; i++) {
|
|
3407
|
+
logScales[i] = Math.log(Math.max(data.scales[i], 1e-8));
|
|
3408
|
+
}
|
|
3409
|
+
const size = N * 3 * 4 + N * 4 * 4 + N * 3 * 4 + N * 4 + N * 4 * 4;
|
|
3410
|
+
const buf = new Uint8Array(size);
|
|
3411
|
+
let off = 0;
|
|
3412
|
+
const write = (arr) => {
|
|
3413
|
+
const view = new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
3414
|
+
buf.set(view, off);
|
|
3415
|
+
off += arr.byteLength;
|
|
3416
|
+
};
|
|
3417
|
+
write(data.positions);
|
|
3418
|
+
write(data.rotations);
|
|
3419
|
+
write(logScales);
|
|
3420
|
+
write(data.opacities);
|
|
3421
|
+
write(data.colors);
|
|
3422
|
+
return buf;
|
|
3423
|
+
}
|
|
3424
|
+
buildBufferViews(N) {
|
|
3425
|
+
let off = 0;
|
|
3426
|
+
const views = [];
|
|
3427
|
+
const add = (len) => {
|
|
3428
|
+
views.push({ buffer: 0, byteOffset: off, byteLength: len });
|
|
3429
|
+
off += len;
|
|
3430
|
+
return views.length - 1;
|
|
3431
|
+
};
|
|
3432
|
+
add(N * 3 * 4);
|
|
3433
|
+
add(N * 4 * 4);
|
|
3434
|
+
add(N * 3 * 4);
|
|
3435
|
+
add(N * 4);
|
|
3436
|
+
add(N * 4 * 4);
|
|
3437
|
+
return views;
|
|
3438
|
+
}
|
|
3439
|
+
buildAccessors(N) {
|
|
3440
|
+
let bv = 0;
|
|
3441
|
+
const accs = [];
|
|
3442
|
+
const add = (type, compType, count) => {
|
|
3443
|
+
accs.push({ bufferView: bv++, componentType: compType, count, type });
|
|
3444
|
+
};
|
|
3445
|
+
add("VEC3", 5126, N);
|
|
3446
|
+
add("VEC4", 5126, N);
|
|
3447
|
+
add("VEC3", 5126, N);
|
|
3448
|
+
add("SCALAR", 5126, N);
|
|
3449
|
+
add("VEC4", 5126, N);
|
|
3450
|
+
return accs;
|
|
3451
|
+
}
|
|
3452
|
+
// ─── GLB assembler (mirrors GLTFPipeline) ─────────────────────────────────
|
|
3453
|
+
createGLB(gltf, buffer) {
|
|
3454
|
+
const jsonString = JSON.stringify(gltf);
|
|
3455
|
+
const jsonBuffer = new TextEncoder().encode(jsonString);
|
|
3456
|
+
const jsonPadding = (4 - jsonBuffer.byteLength % 4) % 4;
|
|
3457
|
+
const paddedJsonLength = jsonBuffer.byteLength + jsonPadding;
|
|
3458
|
+
const binPadding = (4 - buffer.byteLength % 4) % 4;
|
|
3459
|
+
const paddedBinLength = buffer.byteLength + binPadding;
|
|
3460
|
+
const totalSize = 12 + 8 + paddedJsonLength + 8 + paddedBinLength;
|
|
3461
|
+
const output = new ArrayBuffer(totalSize);
|
|
3462
|
+
const view = new DataView(output);
|
|
3463
|
+
const bytes = new Uint8Array(output);
|
|
3464
|
+
let offset = 0;
|
|
3465
|
+
view.setUint32(offset, 1179937895, true);
|
|
3466
|
+
offset += 4;
|
|
3467
|
+
view.setUint32(offset, 2, true);
|
|
3468
|
+
offset += 4;
|
|
3469
|
+
view.setUint32(offset, totalSize, true);
|
|
3470
|
+
offset += 4;
|
|
3471
|
+
view.setUint32(offset, paddedJsonLength, true);
|
|
3472
|
+
offset += 4;
|
|
3473
|
+
view.setUint32(offset, 1313821514, true);
|
|
3474
|
+
offset += 4;
|
|
3475
|
+
bytes.set(jsonBuffer, offset);
|
|
3476
|
+
offset += jsonBuffer.byteLength;
|
|
3477
|
+
for (let i = 0; i < jsonPadding; i++) bytes[offset++] = 32;
|
|
3478
|
+
view.setUint32(offset, paddedBinLength, true);
|
|
3479
|
+
offset += 4;
|
|
3480
|
+
view.setUint32(offset, 5130562, true);
|
|
3481
|
+
offset += 4;
|
|
3482
|
+
bytes.set(buffer, offset);
|
|
3483
|
+
offset += buffer.byteLength;
|
|
3484
|
+
for (let i = 0; i < binPadding; i++) bytes[offset++] = 0;
|
|
3485
|
+
return new Uint8Array(output);
|
|
3486
|
+
}
|
|
3487
|
+
};
|
|
3488
|
+
function createGaussianSplattingCompiler(options) {
|
|
3489
|
+
return new GaussianSplattingCompiler(options);
|
|
3490
|
+
}
|
|
3491
|
+
|
|
3492
|
+
// src/compiler/SpatialPartitionPass.ts
|
|
3493
|
+
var MAX_DEPTH = 8;
|
|
3494
|
+
var SCALE_PER_SPLAT_UNIT = 1e-6;
|
|
3495
|
+
var MIN_SCALE = 1e-9;
|
|
3496
|
+
var SpatialPartitionPass = class {
|
|
3497
|
+
constructor(options = {}) {
|
|
3498
|
+
this.maxDepth = options.maxDepth ?? MAX_DEPTH;
|
|
3499
|
+
this.scalePerSplatUnit = options.scalePerSplatUnit ?? SCALE_PER_SPLAT_UNIT;
|
|
3500
|
+
this.includeUnpositioned = options.includeUnpositioned ?? true;
|
|
3501
|
+
}
|
|
3502
|
+
/**
|
|
3503
|
+
* Run the pass over a HoloComposition and return the serializable result.
|
|
3504
|
+
*/
|
|
3505
|
+
run(composition) {
|
|
3506
|
+
const rawSources = [];
|
|
3507
|
+
this.collectFromComposition(composition, rawSources);
|
|
3508
|
+
if (rawSources.length === 0) {
|
|
3509
|
+
return this.emptyResult(composition.name);
|
|
3510
|
+
}
|
|
3511
|
+
const maxScaleInScene = Math.max(
|
|
3512
|
+
...rawSources.map((s) => Math.max(s.maxSplats * this.scalePerSplatUnit, MIN_SCALE))
|
|
3513
|
+
);
|
|
3514
|
+
const anchors = [];
|
|
3515
|
+
const lodDist = {};
|
|
3516
|
+
let objectsWalked = 0;
|
|
3517
|
+
for (const src of rawSources) {
|
|
3518
|
+
objectsWalked++;
|
|
3519
|
+
if (!this.includeUnpositioned && !src.hasPosition) continue;
|
|
3520
|
+
const scale = Math.max(src.maxSplats * this.scalePerSplatUnit, MIN_SCALE);
|
|
3521
|
+
const lodLevel = this.computeLODLevel(scale, maxScaleInScene);
|
|
3522
|
+
const provenanceHash = src.sourceFile ? deterministicHash(`file:${src.sourceFile}:${src.maxSplats}`) : deterministicHash(`${src.objectName}:${lodLevel}:${src.maxSplats}`);
|
|
3523
|
+
const anchor = {
|
|
3524
|
+
id: `spa_${sanitiseId(src.objectName)}_l${lodLevel}`,
|
|
3525
|
+
position: src.position,
|
|
3526
|
+
scale,
|
|
3527
|
+
lodLevel,
|
|
3528
|
+
gaussianCount: src.maxSplats,
|
|
3529
|
+
importance: src.importance,
|
|
3530
|
+
provenanceHash,
|
|
3531
|
+
...src.sourceFile ? { sourceFile: src.sourceFile } : {}
|
|
3532
|
+
};
|
|
3533
|
+
anchors.push(anchor);
|
|
3534
|
+
lodDist[lodLevel] = (lodDist[lodLevel] ?? 0) + 1;
|
|
3535
|
+
}
|
|
3536
|
+
anchors.sort((a, b) => a.lodLevel - b.lodLevel);
|
|
3537
|
+
const bounds = computeBounds(anchors);
|
|
3538
|
+
const merkleRoot = computeMerkleRoot(anchors);
|
|
3539
|
+
const totalGaussians = anchors.reduce((s, a) => s + a.gaussianCount, 0);
|
|
3540
|
+
const maxLodLevel = anchors.length > 0 ? Math.max(...anchors.map((a) => a.lodLevel)) : 0;
|
|
3541
|
+
return {
|
|
3542
|
+
schema: "spatial-partition/v1",
|
|
3543
|
+
compositionName: composition.name,
|
|
3544
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3545
|
+
anchors,
|
|
3546
|
+
bounds,
|
|
3547
|
+
merkleRoot,
|
|
3548
|
+
totalGaussians,
|
|
3549
|
+
stats: {
|
|
3550
|
+
objectsWalked,
|
|
3551
|
+
anchorsEmitted: anchors.length,
|
|
3552
|
+
lodLevelDistribution: lodDist,
|
|
3553
|
+
maxLodLevel,
|
|
3554
|
+
maxScaleInScene
|
|
3555
|
+
}
|
|
3556
|
+
};
|
|
3557
|
+
}
|
|
3558
|
+
// ── LOD level computation (same algorithm as OctreeLODSystem.computeLODLevelFromScale) ──
|
|
3559
|
+
computeLODLevel(scale, maxScaleInScene) {
|
|
3560
|
+
if (scale <= 0 || maxScaleInScene <= 0) return this.maxDepth - 1;
|
|
3561
|
+
if (scale >= maxScaleInScene) return 0;
|
|
3562
|
+
const ratio = maxScaleInScene / scale;
|
|
3563
|
+
const level = Math.floor(Math.log2(ratio));
|
|
3564
|
+
return Math.min(Math.max(0, level), this.maxDepth - 1);
|
|
3565
|
+
}
|
|
3566
|
+
// ── AST Walk (mirrors GaussianBudgetAnalyzer.collectGaussianSources) ─────────
|
|
3567
|
+
collectFromComposition(composition, out) {
|
|
3568
|
+
if (composition.objects) {
|
|
3569
|
+
for (const obj of composition.objects) {
|
|
3570
|
+
this.collectFromObject(obj, out);
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
if (composition.spatialGroups) {
|
|
3574
|
+
for (const group of composition.spatialGroups) {
|
|
3575
|
+
this.collectFromGroup(group, out);
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
if (composition.conditionals) {
|
|
3579
|
+
for (const cond of composition.conditionals) {
|
|
3580
|
+
if (cond.objects) {
|
|
3581
|
+
for (const obj of cond.objects) this.collectFromObject(obj, out);
|
|
3582
|
+
}
|
|
3583
|
+
if (cond.elseObjects) {
|
|
3584
|
+
for (const obj of cond.elseObjects) this.collectFromObject(obj, out);
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
if (composition.iterators) {
|
|
3589
|
+
for (const iter of composition.iterators) {
|
|
3590
|
+
if (iter.objects) {
|
|
3591
|
+
for (const obj of iter.objects) this.collectFromObject(obj, out);
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
collectFromObject(obj, out) {
|
|
3597
|
+
if (obj.traits) {
|
|
3598
|
+
for (const trait of obj.traits) {
|
|
3599
|
+
if (trait.name === "gaussian_splat") {
|
|
3600
|
+
const src = this.extractSource(obj, trait);
|
|
3601
|
+
if (src) out.push(src);
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
if (obj.children) {
|
|
3606
|
+
for (const child of obj.children) {
|
|
3607
|
+
this.collectFromObject(child, out);
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
}
|
|
3611
|
+
collectFromGroup(group, out) {
|
|
3612
|
+
if (group.objects) {
|
|
3613
|
+
for (const obj of group.objects) this.collectFromObject(obj, out);
|
|
3614
|
+
}
|
|
3615
|
+
if (group.groups) {
|
|
3616
|
+
for (const sub of group.groups) this.collectFromGroup(sub, out);
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3619
|
+
extractSource(obj, trait) {
|
|
3620
|
+
const config = trait.config ?? {};
|
|
3621
|
+
const maxSplats = typeof config.max_splats === "number" ? config.max_splats : 5e4;
|
|
3622
|
+
const sourceFile = typeof config.src === "string" ? config.src : typeof config.source === "string" ? config.source : void 0;
|
|
3623
|
+
const importance = typeof config.importance === "number" ? Math.max(0, Math.min(1, config.importance)) : 0.5;
|
|
3624
|
+
let posArr = null;
|
|
3625
|
+
if (obj.position && typeof obj.position.x === "number") {
|
|
3626
|
+
posArr = [obj.position.x, obj.position.y, obj.position.z];
|
|
3627
|
+
} else {
|
|
3628
|
+
const posProp = obj.properties?.find((p) => p.key === "position")?.value;
|
|
3629
|
+
if (Array.isArray(posProp) && posProp.length >= 3) {
|
|
3630
|
+
posArr = [Number(posProp[0]), Number(posProp[1]), Number(posProp[2])];
|
|
3631
|
+
} else if (posProp !== null && typeof posProp === "object" && !Array.isArray(posProp) && typeof posProp["x"] === "number") {
|
|
3632
|
+
const pobj = posProp;
|
|
3633
|
+
posArr = [pobj.x, pobj.y, pobj.z];
|
|
3634
|
+
}
|
|
3635
|
+
}
|
|
3636
|
+
return {
|
|
3637
|
+
objectName: obj.name ?? `unnamed_${Math.random().toString(36).slice(2, 7)}`,
|
|
3638
|
+
position: posArr ?? [0, 0, 0],
|
|
3639
|
+
hasPosition: posArr !== null,
|
|
3640
|
+
maxSplats,
|
|
3641
|
+
sourceFile,
|
|
3642
|
+
importance
|
|
3643
|
+
};
|
|
3644
|
+
}
|
|
3645
|
+
// ── Empty-composition fast path ─────────────────────────────────────────────
|
|
3646
|
+
emptyResult(compositionName) {
|
|
3647
|
+
return {
|
|
3648
|
+
schema: "spatial-partition/v1",
|
|
3649
|
+
compositionName,
|
|
3650
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3651
|
+
anchors: [],
|
|
3652
|
+
bounds: {
|
|
3653
|
+
min: { x: 0, y: 0, z: 0 },
|
|
3654
|
+
max: { x: 0, y: 0, z: 0 },
|
|
3655
|
+
center: { x: 0, y: 0, z: 0 },
|
|
3656
|
+
halfSize: 0
|
|
3657
|
+
},
|
|
3658
|
+
merkleRoot: "0".repeat(64),
|
|
3659
|
+
totalGaussians: 0,
|
|
3660
|
+
stats: {
|
|
3661
|
+
objectsWalked: 0,
|
|
3662
|
+
anchorsEmitted: 0,
|
|
3663
|
+
lodLevelDistribution: {},
|
|
3664
|
+
maxLodLevel: 0,
|
|
3665
|
+
maxScaleInScene: 0
|
|
3666
|
+
}
|
|
3667
|
+
};
|
|
3668
|
+
}
|
|
3669
|
+
};
|
|
3670
|
+
function deterministicHash(input) {
|
|
3671
|
+
let h0 = 2166136261;
|
|
3672
|
+
let h1 = 3521423859;
|
|
3673
|
+
for (let i = 0; i < input.length; i++) {
|
|
3674
|
+
const c = input.charCodeAt(i);
|
|
3675
|
+
h0 = Math.imul(h0 ^ c, 16777619) >>> 0;
|
|
3676
|
+
h1 = Math.imul(h1 ^ c, 16777619) >>> 0;
|
|
3677
|
+
}
|
|
3678
|
+
const hex0 = h0.toString(16).padStart(8, "0");
|
|
3679
|
+
const hex1 = h1.toString(16).padStart(8, "0");
|
|
3680
|
+
const base = (hex0 + hex1).repeat(4).slice(0, 64);
|
|
3681
|
+
return base;
|
|
3682
|
+
}
|
|
3683
|
+
function computeMerkleRoot(anchors) {
|
|
3684
|
+
if (anchors.length === 0) return "0".repeat(64);
|
|
3685
|
+
const sorted = [...anchors].sort((a, b) => a.id.localeCompare(b.id));
|
|
3686
|
+
const bytes = new Uint8Array(32);
|
|
3687
|
+
for (const anchor of sorted) {
|
|
3688
|
+
const hash = anchor.provenanceHash.slice(0, 64).padEnd(64, "0");
|
|
3689
|
+
for (let i = 0; i < 32; i++) {
|
|
3690
|
+
const byteHex = hash.slice(i * 2, i * 2 + 2);
|
|
3691
|
+
bytes[i] ^= parseInt(byteHex, 16) || 0;
|
|
3692
|
+
}
|
|
3693
|
+
}
|
|
3694
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3695
|
+
}
|
|
3696
|
+
function computeBounds(anchors) {
|
|
3697
|
+
if (anchors.length === 0) {
|
|
3698
|
+
return {
|
|
3699
|
+
min: { x: 0, y: 0, z: 0 },
|
|
3700
|
+
max: { x: 0, y: 0, z: 0 },
|
|
3701
|
+
center: { x: 0, y: 0, z: 0 },
|
|
3702
|
+
halfSize: 0
|
|
3703
|
+
};
|
|
3704
|
+
}
|
|
3705
|
+
let minX = Infinity, minY = Infinity, minZ = Infinity;
|
|
3706
|
+
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
3707
|
+
for (const a of anchors) {
|
|
3708
|
+
const r = a.scale;
|
|
3709
|
+
minX = Math.min(minX, a.position[0] - r);
|
|
3710
|
+
minY = Math.min(minY, a.position[1] - r);
|
|
3711
|
+
minZ = Math.min(minZ, a.position[2] - r);
|
|
3712
|
+
maxX = Math.max(maxX, a.position[0] + r);
|
|
3713
|
+
maxY = Math.max(maxY, a.position[1] + r);
|
|
3714
|
+
maxZ = Math.max(maxZ, a.position[2] + r);
|
|
3715
|
+
}
|
|
3716
|
+
const cx = (minX + maxX) / 2;
|
|
3717
|
+
const cy = (minY + maxY) / 2;
|
|
3718
|
+
const cz = (minZ + maxZ) / 2;
|
|
3719
|
+
const halfSize = Math.max(
|
|
3720
|
+
(maxX - minX) / 2,
|
|
3721
|
+
(maxY - minY) / 2,
|
|
3722
|
+
(maxZ - minZ) / 2
|
|
3723
|
+
);
|
|
3724
|
+
return {
|
|
3725
|
+
min: { x: minX, y: minY, z: minZ },
|
|
3726
|
+
max: { x: maxX, y: maxY, z: maxZ },
|
|
3727
|
+
center: { x: cx, y: cy, z: cz },
|
|
3728
|
+
halfSize
|
|
3729
|
+
};
|
|
3730
|
+
}
|
|
3731
|
+
function sanitiseId(s) {
|
|
3732
|
+
return s.replace(/[^a-zA-Z0-9_]/g, "_").slice(0, 32);
|
|
3733
|
+
}
|
|
3734
|
+
function spatialPartition(composition, options) {
|
|
3735
|
+
return new SpatialPartitionPass(options).run(composition);
|
|
3736
|
+
}
|
|
3737
|
+
|
|
3385
3738
|
// src/types/effects.ts
|
|
3386
3739
|
function effectCategory(effect) {
|
|
3387
3740
|
return effect.split(":")[0];
|
|
@@ -3546,6 +3899,7 @@ var TRAIT_EFFECTS = {
|
|
|
3546
3899
|
// Audio traits
|
|
3547
3900
|
"@audio": ["audio:play"],
|
|
3548
3901
|
"@spatial_audio": ["audio:spatial"],
|
|
3902
|
+
"@gem_resonance": ["audio:spatial", "state:read"],
|
|
3549
3903
|
"@reverb": ["audio:reverb"],
|
|
3550
3904
|
"@music": ["audio:play", "audio:global"],
|
|
3551
3905
|
// State traits
|
|
@@ -3756,6 +4110,7 @@ var TRAIT_EFFECTS = {
|
|
|
3756
4110
|
"@mitosis": [],
|
|
3757
4111
|
"@mock": [],
|
|
3758
4112
|
"@model_load": [],
|
|
4113
|
+
"@modbus": ["io:network"],
|
|
3759
4114
|
"@motion_reduced": ["io:read", "io:write"],
|
|
3760
4115
|
"@mqtt_pub": ["io:network"],
|
|
3761
4116
|
"@mqtt_sink": ["io:network"],
|
|
@@ -3773,6 +4128,7 @@ var TRAIT_EFFECTS = {
|
|
|
3773
4128
|
"@object_tracking": ["state:read"],
|
|
3774
4129
|
"@occlusion": ["io:read", "io:write"],
|
|
3775
4130
|
"@openxr_hal": [],
|
|
4131
|
+
"@opc_ua": ["io:network"],
|
|
3776
4132
|
"@orbital": [],
|
|
3777
4133
|
"@package_signing": ["authority:own"],
|
|
3778
4134
|
"@pagerduty": [],
|
|
@@ -3965,7 +4321,9 @@ function inferFromTraits(traitNames) {
|
|
|
3965
4321
|
sources.set(e, existing);
|
|
3966
4322
|
}
|
|
3967
4323
|
} else {
|
|
3968
|
-
warnings.push(
|
|
4324
|
+
warnings.push(
|
|
4325
|
+
`Unknown trait '${normalized}': cannot infer effects, so the safety checker assumes pure. Register the trait in TRAIT_EFFECTS or add an explicit @effect declaration before relying on this inference.`
|
|
4326
|
+
);
|
|
3969
4327
|
}
|
|
3970
4328
|
}
|
|
3971
4329
|
return { row: new EffectRow(allEffects), sources, warnings };
|
|
@@ -4256,6 +4614,7 @@ var TRAIT_RESOURCE_COSTS = {
|
|
|
4256
4614
|
// ── Audio ──
|
|
4257
4615
|
"@audio": { audioSources: 1 },
|
|
4258
4616
|
"@spatial_audio": { audioSources: 1 },
|
|
4617
|
+
"@gem_resonance": { audioSources: 1 },
|
|
4259
4618
|
"@environmental_audio": { audioSources: 4, memoryMB: 2 },
|
|
4260
4619
|
"@voice_mesh": { audioSources: 1, networkMsgs: 10 },
|
|
4261
4620
|
"@voice_input": { audioSources: 1, memoryMB: 1 },
|
|
@@ -4268,6 +4627,8 @@ var TRAIT_RESOURCE_COSTS = {
|
|
|
4268
4627
|
"@lobby": { networkMsgs: 5, memoryMB: 2 },
|
|
4269
4628
|
"@mqtt_sink": { networkMsgs: 5 },
|
|
4270
4629
|
"@mqtt_source": { networkMsgs: 5 },
|
|
4630
|
+
"@modbus": { networkMsgs: 5 },
|
|
4631
|
+
"@opc_ua": { networkMsgs: 5 },
|
|
4271
4632
|
"@sync_tier": { networkMsgs: 2 },
|
|
4272
4633
|
"@crdt_room": { networkMsgs: 10, memoryMB: 4 },
|
|
4273
4634
|
"@shareplay": { networkMsgs: 5, memoryMB: 2 },
|
|
@@ -4981,6 +5342,7 @@ function quickSafetyCheck(traits, calls, options = {}) {
|
|
|
4981
5342
|
}
|
|
4982
5343
|
|
|
4983
5344
|
// src/compiler/platform/CrossRealityTraitRegistry.ts
|
|
5345
|
+
init_PlatformConditional();
|
|
4984
5346
|
var CATEGORY_DEFAULT_EMBODIMENT = {
|
|
4985
5347
|
vr: "FullAvatar",
|
|
4986
5348
|
ar: "FloatingAgent",
|
|
@@ -5268,6 +5630,7 @@ function createCrossRealityTraitRegistry() {
|
|
|
5268
5630
|
}
|
|
5269
5631
|
|
|
5270
5632
|
// src/compiler/platform/ModalitySelector.ts
|
|
5633
|
+
init_PlatformConditional();
|
|
5271
5634
|
var EMBODIMENT_TO_TARGET = {
|
|
5272
5635
|
FullAvatar: { primary: "openxr", fallback: "r3f" },
|
|
5273
5636
|
FloatingAgent: { primary: "visionos", fallback: "r3f" },
|
|
@@ -5307,14 +5670,10 @@ function selectModality(platform, options = {}) {
|
|
|
5307
5670
|
reasoning.push(`Embodiment forced to ${embodiment} by caller`);
|
|
5308
5671
|
} else if (platform in PLATFORM_EMBODIMENT_OVERRIDES) {
|
|
5309
5672
|
embodiment = PLATFORM_EMBODIMENT_OVERRIDES[platform];
|
|
5310
|
-
reasoning.push(
|
|
5311
|
-
`Embodiment ${embodiment} from platform-specific override for ${platform}`
|
|
5312
|
-
);
|
|
5673
|
+
reasoning.push(`Embodiment ${embodiment} from platform-specific override for ${platform}`);
|
|
5313
5674
|
} else {
|
|
5314
5675
|
embodiment = CATEGORY_DEFAULT_EMBODIMENT[category];
|
|
5315
|
-
reasoning.push(
|
|
5316
|
-
`Embodiment ${embodiment} from category default for ${category}`
|
|
5317
|
-
);
|
|
5676
|
+
reasoning.push(`Embodiment ${embodiment} from category default for ${category}`);
|
|
5318
5677
|
}
|
|
5319
5678
|
let exportTarget;
|
|
5320
5679
|
let fallbackTarget;
|
|
@@ -5325,16 +5684,12 @@ function selectModality(platform, options = {}) {
|
|
|
5325
5684
|
} else if (platform in PLATFORM_TARGET_OVERRIDES) {
|
|
5326
5685
|
exportTarget = PLATFORM_TARGET_OVERRIDES[platform];
|
|
5327
5686
|
fallbackTarget = EMBODIMENT_TO_TARGET[embodiment]?.fallback ?? null;
|
|
5328
|
-
reasoning.push(
|
|
5329
|
-
`ExportTarget ${exportTarget} from platform-specific override for ${platform}`
|
|
5330
|
-
);
|
|
5687
|
+
reasoning.push(`ExportTarget ${exportTarget} from platform-specific override for ${platform}`);
|
|
5331
5688
|
} else {
|
|
5332
5689
|
const mapping = EMBODIMENT_TO_TARGET[embodiment];
|
|
5333
5690
|
exportTarget = mapping.primary;
|
|
5334
5691
|
fallbackTarget = mapping.fallback;
|
|
5335
|
-
reasoning.push(
|
|
5336
|
-
`ExportTarget ${exportTarget} from embodiment mapping for ${embodiment}`
|
|
5337
|
-
);
|
|
5692
|
+
reasoning.push(`ExportTarget ${exportTarget} from embodiment mapping for ${embodiment}`);
|
|
5338
5693
|
}
|
|
5339
5694
|
const canRenderSpatial = capabilities.gpu3D && capabilities.frameBudgetMs <= 16.6;
|
|
5340
5695
|
reasoning.push(
|
|
@@ -5376,8 +5731,10 @@ function bestCategoryForTraits(requiredCapabilities) {
|
|
|
5376
5731
|
const canSupport = platforms.some((platform) => {
|
|
5377
5732
|
const caps = PLATFORM_CAPABILITIES[platform];
|
|
5378
5733
|
return Object.entries(requiredCapabilities).every(([key, required]) => {
|
|
5379
|
-
if (typeof required === "boolean")
|
|
5380
|
-
|
|
5734
|
+
if (typeof required === "boolean")
|
|
5735
|
+
return !required || caps[key] === true;
|
|
5736
|
+
if (typeof required === "number")
|
|
5737
|
+
return caps[key] <= required;
|
|
5381
5738
|
return true;
|
|
5382
5739
|
});
|
|
5383
5740
|
});
|
|
@@ -5399,7 +5756,7 @@ var CompilerBridge = class {
|
|
|
5399
5756
|
if (this.initialized) return;
|
|
5400
5757
|
try {
|
|
5401
5758
|
const [parserModule, compilerModule] = await Promise.all([
|
|
5402
|
-
import('./
|
|
5759
|
+
import('./HoloScriptPlusParser-F2Z56FJR.js'),
|
|
5403
5760
|
import('./compiler/r3f.js')
|
|
5404
5761
|
]);
|
|
5405
5762
|
this.modules = {
|
|
@@ -5528,6 +5885,16 @@ function getCompilerBridge() {
|
|
|
5528
5885
|
function json(value) {
|
|
5529
5886
|
return JSON.stringify(value, null, 2);
|
|
5530
5887
|
}
|
|
5888
|
+
function unsupportedPipelineStep(kind, type, name) {
|
|
5889
|
+
const typeLabel = type || "unknown";
|
|
5890
|
+
return `[PipelineNodeCompiler] Unsupported pipeline ${kind} type "${typeLabel}" (step: ${name}). PipelineNodeCompiler does not yet emit code for this type.`;
|
|
5891
|
+
}
|
|
5892
|
+
function unsupportedNodeThrow(kind, type, name) {
|
|
5893
|
+
return `(() => { throw new Error(${json(unsupportedPipelineStep(kind, type, name))}); })()`;
|
|
5894
|
+
}
|
|
5895
|
+
function unsupportedPythonRaise(kind, type, name) {
|
|
5896
|
+
return `raise NotImplementedError(${json(unsupportedPipelineStep(kind, type, name))})`;
|
|
5897
|
+
}
|
|
5531
5898
|
function emitSource(source) {
|
|
5532
5899
|
switch (source.type) {
|
|
5533
5900
|
case "rest":
|
|
@@ -5538,15 +5905,29 @@ function emitSource(source) {
|
|
|
5538
5905
|
case "list":
|
|
5539
5906
|
return json(source.items || []);
|
|
5540
5907
|
default:
|
|
5541
|
-
return "
|
|
5908
|
+
return unsupportedNodeThrow("source", source.type, source.name);
|
|
5542
5909
|
}
|
|
5543
5910
|
}
|
|
5544
5911
|
function emitFieldMappingTransform(t) {
|
|
5545
5912
|
const mappings = t.mappings || [];
|
|
5546
|
-
const
|
|
5547
|
-
|
|
5913
|
+
const unwrapMappings = mappings.filter((m) => m.from.endsWith("[]"));
|
|
5914
|
+
const valueMappings = mappings.filter((m) => !m.from.endsWith("[]"));
|
|
5915
|
+
const lines = [];
|
|
5916
|
+
for (const mapping of unwrapMappings) {
|
|
5917
|
+
lines.push(
|
|
5918
|
+
`data = data.flatMap((item) => unwrapPathValues(item, ${json(mapping.from)}).map((value) => ({ ...item, ${json(mapping.to)}: applyTransforms(value, ${json(mapping.transforms || [])}) })));`
|
|
5919
|
+
);
|
|
5920
|
+
}
|
|
5921
|
+
if (valueMappings.length === 0) {
|
|
5922
|
+
return lines.join("\n");
|
|
5923
|
+
}
|
|
5924
|
+
const mapExpr = valueMappings.map(
|
|
5925
|
+
(m) => `${json(m.to)}: applyTransforms(getPathValue(item, ${json(m.from)}), ${json(m.transforms || [])})`
|
|
5926
|
+
).join(",\n ");
|
|
5927
|
+
lines.push(`data = data.map((item) => ({
|
|
5548
5928
|
${mapExpr}
|
|
5549
|
-
}))
|
|
5929
|
+
}));`);
|
|
5930
|
+
return lines.join("\n");
|
|
5550
5931
|
}
|
|
5551
5932
|
function emitTransform(t) {
|
|
5552
5933
|
if ((t.type === "field_mapping" || !t.type) && t.mappings && t.mappings.length > 0) {
|
|
@@ -5578,11 +5959,11 @@ function emitSink(sink) {
|
|
|
5578
5959
|
return `await writeOutput(${json(sink.path || "./pipeline-output.jsonl")}, data, ${json(sink.format || "jsonl")}, ${json(Boolean(sink.append))});`;
|
|
5579
5960
|
case "rest":
|
|
5580
5961
|
case "webhook":
|
|
5581
|
-
return `await
|
|
5962
|
+
return `await postJSON(${json(sink.endpoint || "")}, data, { method: ${json(sink.method || "POST")} });`;
|
|
5582
5963
|
case "mcp":
|
|
5583
5964
|
return `console.warn(${json(`[${sink.name}] mcp sink requires host integration: ${sink.server || ""}/${sink.tool || ""}`)});`;
|
|
5584
5965
|
default:
|
|
5585
|
-
return
|
|
5966
|
+
return `${unsupportedNodeThrow("sink", sink.type, sink.name)};`;
|
|
5586
5967
|
}
|
|
5587
5968
|
}
|
|
5588
5969
|
function emitPythonSource(source) {
|
|
@@ -5595,12 +5976,14 @@ function emitPythonSource(source) {
|
|
|
5595
5976
|
case "list":
|
|
5596
5977
|
return `datasets[${json(source.name)}] = ${json(source.items || [])}`;
|
|
5597
5978
|
default:
|
|
5598
|
-
return
|
|
5979
|
+
return unsupportedPythonRaise("source", source.type, source.name);
|
|
5599
5980
|
}
|
|
5600
5981
|
}
|
|
5601
5982
|
function emitPythonFieldMappingTransform(t) {
|
|
5602
5983
|
const mappings = t.mappings || [];
|
|
5603
|
-
const mappingLines = mappings.map(
|
|
5984
|
+
const mappingLines = mappings.map(
|
|
5985
|
+
(m) => `${json(m.to)}: apply_transforms(item.get(${json(m.from)}), ${json(m.transforms || [])}),`
|
|
5986
|
+
).join("\n ");
|
|
5604
5987
|
return `data = [
|
|
5605
5988
|
{
|
|
5606
5989
|
${mappingLines}
|
|
@@ -5642,7 +6025,7 @@ function emitPythonSink(sink) {
|
|
|
5642
6025
|
case "mcp":
|
|
5643
6026
|
return `print(${json(`[${sink.name}] mcp sink requires host integration: ${sink.server || ""}/${sink.tool || ""}`)})`;
|
|
5644
6027
|
default:
|
|
5645
|
-
return
|
|
6028
|
+
return unsupportedPythonRaise("sink", sink.type, sink.name);
|
|
5646
6029
|
}
|
|
5647
6030
|
}
|
|
5648
6031
|
function compilePipelineToNode(pipeline, options = {}) {
|
|
@@ -5659,18 +6042,55 @@ function compilePipelineToNode(pipeline, options = {}) {
|
|
|
5659
6042
|
*/
|
|
5660
6043
|
|
|
5661
6044
|
import fs from 'node:fs/promises';
|
|
6045
|
+
import path from 'node:path';
|
|
6046
|
+
|
|
6047
|
+
const RUN_DATE = new Date().toISOString().slice(0, 10);
|
|
6048
|
+
|
|
6049
|
+
function resolveTemplate(value, context = {}) {
|
|
6050
|
+
if (typeof value !== 'string') return value;
|
|
6051
|
+
return value
|
|
6052
|
+
.replace(/\\$\\{date\\}/g, RUN_DATE)
|
|
6053
|
+
.replace(/\\$\\{env\\.([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_match, name) => process.env[name] ?? '')
|
|
6054
|
+
.replace(/\\$\\{([A-Za-z_][A-Za-z0-9_.]*)\\}/g, (_match, key) => {
|
|
6055
|
+
const found = key.split('.').reduce((acc, part) => (acc && typeof acc === 'object' ? acc[part] : undefined), context);
|
|
6056
|
+
return found === undefined || found === null ? '' : String(found);
|
|
6057
|
+
});
|
|
6058
|
+
}
|
|
6059
|
+
|
|
6060
|
+
function normalizeOutputPath(rawPath, format) {
|
|
6061
|
+
const resolved = resolveTemplate(rawPath);
|
|
6062
|
+
if (!resolved) return format === 'json' ? './pipeline-output.json' : './pipeline-output.jsonl';
|
|
6063
|
+
if (path.extname(resolved)) return resolved;
|
|
6064
|
+
return path.join(resolved, format === 'json' ? 'pipeline-output.json' : 'pipeline-output.jsonl');
|
|
6065
|
+
}
|
|
5662
6066
|
|
|
5663
6067
|
async function fetchJSON(url, init) {
|
|
5664
|
-
|
|
5665
|
-
|
|
6068
|
+
const resolvedUrl = resolveTemplate(url);
|
|
6069
|
+
if (!resolvedUrl) return [];
|
|
6070
|
+
const res = await fetch(resolvedUrl, init);
|
|
5666
6071
|
if (!res.ok) throw new Error(\`Request failed: \${res.status} \${res.statusText}\`);
|
|
5667
6072
|
const body = await res.json();
|
|
5668
6073
|
return Array.isArray(body) ? body : [body];
|
|
5669
6074
|
}
|
|
5670
6075
|
|
|
6076
|
+
async function postJSON(url, data, init) {
|
|
6077
|
+
const resolvedUrl = resolveTemplate(url, { data });
|
|
6078
|
+
if (!resolvedUrl) {
|
|
6079
|
+
console.warn('[PipelineNodeCompiler] skipping empty webhook/rest sink endpoint');
|
|
6080
|
+
return;
|
|
6081
|
+
}
|
|
6082
|
+
const res = await fetch(resolvedUrl, {
|
|
6083
|
+
...init,
|
|
6084
|
+
headers: { 'content-type': 'application/json', ...(init?.headers || {}) },
|
|
6085
|
+
body: JSON.stringify(data),
|
|
6086
|
+
});
|
|
6087
|
+
if (!res.ok) throw new Error(\`Request failed: \${res.status} \${res.statusText}\`);
|
|
6088
|
+
}
|
|
6089
|
+
|
|
5671
6090
|
async function readJSONArray(filePath) {
|
|
5672
|
-
|
|
5673
|
-
|
|
6091
|
+
const resolvedPath = resolveTemplate(filePath);
|
|
6092
|
+
if (!resolvedPath) return [];
|
|
6093
|
+
const raw = await fs.readFile(resolvedPath, 'utf8');
|
|
5674
6094
|
const parsed = JSON.parse(raw);
|
|
5675
6095
|
return Array.isArray(parsed) ? parsed : [parsed];
|
|
5676
6096
|
}
|
|
@@ -5688,6 +6108,22 @@ function applyTransforms(value, transforms) {
|
|
|
5688
6108
|
return v;
|
|
5689
6109
|
}
|
|
5690
6110
|
|
|
6111
|
+
function getPathValue(item, pathExpr) {
|
|
6112
|
+
const cleanPath = String(pathExpr || '').replace(/\\[\\]$/, '');
|
|
6113
|
+
if (!cleanPath) return item;
|
|
6114
|
+
return cleanPath.split('.').reduce((acc, part) => {
|
|
6115
|
+
if (acc == null || typeof acc !== 'object') return undefined;
|
|
6116
|
+
return acc[part];
|
|
6117
|
+
}, item);
|
|
6118
|
+
}
|
|
6119
|
+
|
|
6120
|
+
function unwrapPathValues(item, pathExpr) {
|
|
6121
|
+
const value = getPathValue(item, pathExpr);
|
|
6122
|
+
if (Array.isArray(value)) return value;
|
|
6123
|
+
if (value == null) return [];
|
|
6124
|
+
return [value];
|
|
6125
|
+
}
|
|
6126
|
+
|
|
5691
6127
|
function evalCondition(item, condition) {
|
|
5692
6128
|
try {
|
|
5693
6129
|
const fn = new Function('item', \`with (item) { return (\${condition}); }\`);
|
|
@@ -5708,17 +6144,20 @@ function validateItem(item, fields) {
|
|
|
5708
6144
|
return true;
|
|
5709
6145
|
}
|
|
5710
6146
|
|
|
5711
|
-
async function writeOutput(
|
|
6147
|
+
async function writeOutput(rawPath, data, format, append) {
|
|
6148
|
+
const outputPath = normalizeOutputPath(rawPath, format);
|
|
6149
|
+
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
6150
|
+
|
|
5712
6151
|
if (format === 'json') {
|
|
5713
6152
|
const text = JSON.stringify(data, null, 2);
|
|
5714
|
-
if (append) await fs.appendFile(
|
|
5715
|
-
else await fs.writeFile(
|
|
6153
|
+
if (append) await fs.appendFile(outputPath, text + '\\n');
|
|
6154
|
+
else await fs.writeFile(outputPath, text);
|
|
5716
6155
|
return;
|
|
5717
6156
|
}
|
|
5718
6157
|
|
|
5719
6158
|
const lines = data.map((d) => JSON.stringify(d)).join('\\n') + '\\n';
|
|
5720
|
-
if (append) await fs.appendFile(
|
|
5721
|
-
else await fs.writeFile(
|
|
6159
|
+
if (append) await fs.appendFile(outputPath, lines);
|
|
6160
|
+
else await fs.writeFile(outputPath, lines);
|
|
5722
6161
|
}
|
|
5723
6162
|
|
|
5724
6163
|
export async function runPipeline() {
|
|
@@ -5940,116 +6379,6 @@ function compilePipelineSource(source, options = {}) {
|
|
|
5940
6379
|
return compilePipelineSourceToNode(source, options.node);
|
|
5941
6380
|
}
|
|
5942
6381
|
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
function findTrait(composition, traitName) {
|
|
5947
|
-
const traits = composition.traits;
|
|
5948
|
-
if (!traits) return null;
|
|
5949
|
-
const found = traits.find((t) => t.name === traitName);
|
|
5950
|
-
return found?.config || null;
|
|
5951
|
-
}
|
|
5952
|
-
var NextJSCompiler = class extends CompilerBase {
|
|
5953
|
-
constructor(options = {}) {
|
|
5954
|
-
super();
|
|
5955
|
-
this.options = options;
|
|
5956
|
-
this.compilerName = "NextJSCompiler";
|
|
5957
|
-
}
|
|
5958
|
-
/**
|
|
5959
|
-
* Compile HoloComposition AST to Next.js App Router Code
|
|
5960
|
-
*
|
|
5961
|
-
* @param composition - HoloScript AST
|
|
5962
|
-
* @param agentToken - JWT or UCAN token proving agent identity
|
|
5963
|
-
* @param outputPath - Optional output file path for scope validation
|
|
5964
|
-
* @param sceneGraph - Optional pre-computed SSG
|
|
5965
|
-
*/
|
|
5966
|
-
async compile(composition, agentToken, outputPath, _sceneGraph) {
|
|
5967
|
-
this.validateCompilerAccess(agentToken, outputPath);
|
|
5968
|
-
return this.buildNextRoute(composition);
|
|
5969
|
-
}
|
|
5970
|
-
validateCompilerAccess(agentToken, outputPath) {
|
|
5971
|
-
if (typeof agentToken === "object" && agentToken !== null) {
|
|
5972
|
-
this.validateCapabilityAccess(agentToken, outputPath);
|
|
5973
|
-
} else {
|
|
5974
|
-
this.validateASTAccess(agentToken);
|
|
5975
|
-
this.validateCodeGeneration(agentToken);
|
|
5976
|
-
if (outputPath) {
|
|
5977
|
-
this.validateOutputPath(agentToken, outputPath);
|
|
5978
|
-
}
|
|
5979
|
-
this.validateSpatialZoneAccess(agentToken);
|
|
5980
|
-
}
|
|
5981
|
-
}
|
|
5982
|
-
buildNextRoute(composition) {
|
|
5983
|
-
const compiler = new Native2DCompiler();
|
|
5984
|
-
const pageTrait = findTrait(composition, "page");
|
|
5985
|
-
const metaTrait = findTrait(composition, "metadata");
|
|
5986
|
-
const route = pageTrait?.route || `/${composition.name.toLowerCase().replace(/\s+/g, "-")}`;
|
|
5987
|
-
const isClient = pageTrait?.client !== false;
|
|
5988
|
-
const slotMap = this.options.slots || {};
|
|
5989
|
-
if (pageTrait?.redirect) {
|
|
5990
|
-
const redirectUrl = pageTrait.redirect;
|
|
5991
|
-
const lines2 = [
|
|
5992
|
-
`// @generated by HoloScript NextJSCompiler \u2014 DO NOT EDIT`,
|
|
5993
|
-
`import { redirect } from 'next/navigation';`,
|
|
5994
|
-
``,
|
|
5995
|
-
`export default function RedirectPage() {`,
|
|
5996
|
-
` redirect(${JSON.stringify(redirectUrl)});`,
|
|
5997
|
-
`}`
|
|
5998
|
-
];
|
|
5999
|
-
if (metaTrait) {
|
|
6000
|
-
const metaEntries = [];
|
|
6001
|
-
if (metaTrait.title) metaEntries.push(` title: ${JSON.stringify(metaTrait.title)},`);
|
|
6002
|
-
if (metaTrait.description) metaEntries.push(` description: ${JSON.stringify(metaTrait.description)},`);
|
|
6003
|
-
lines2.push("");
|
|
6004
|
-
lines2.push(`export const metadata = {`);
|
|
6005
|
-
lines2.push(metaEntries.join("\n"));
|
|
6006
|
-
lines2.push(`};`);
|
|
6007
|
-
}
|
|
6008
|
-
const routePath2 = route.replace(/^\//, "") || "index";
|
|
6009
|
-
return {
|
|
6010
|
-
path: `${routePath2}/page.tsx`,
|
|
6011
|
-
code: lines2.join("\n")
|
|
6012
|
-
};
|
|
6013
|
-
}
|
|
6014
|
-
const compilerOptions = {
|
|
6015
|
-
format: "react",
|
|
6016
|
-
useUIComponents: true,
|
|
6017
|
-
slots: slotMap
|
|
6018
|
-
};
|
|
6019
|
-
const elements = composition.ui?.elements || composition.objects || [];
|
|
6020
|
-
const componentCode = compiler.generateReactComponent(
|
|
6021
|
-
composition.name,
|
|
6022
|
-
elements,
|
|
6023
|
-
composition,
|
|
6024
|
-
compilerOptions
|
|
6025
|
-
);
|
|
6026
|
-
const pageSafeComponentCode = componentCode.replace(
|
|
6027
|
-
/export\s+function\s+([A-Za-z0-9_]+)\s*\(/,
|
|
6028
|
-
"function $1("
|
|
6029
|
-
);
|
|
6030
|
-
const lines = [];
|
|
6031
|
-
if (isClient) {
|
|
6032
|
-
lines.push("'use client';");
|
|
6033
|
-
lines.push("");
|
|
6034
|
-
}
|
|
6035
|
-
lines.push(pageSafeComponentCode);
|
|
6036
|
-
if (metaTrait && !isClient) {
|
|
6037
|
-
const metaEntries = [];
|
|
6038
|
-
if (metaTrait.title) metaEntries.push(` title: ${JSON.stringify(metaTrait.title)},`);
|
|
6039
|
-
if (metaTrait.description) metaEntries.push(` description: ${JSON.stringify(metaTrait.description)},`);
|
|
6040
|
-
lines.push("");
|
|
6041
|
-
lines.push(`export const metadata = {`);
|
|
6042
|
-
lines.push(metaEntries.join("\n"));
|
|
6043
|
-
lines.push(`};`);
|
|
6044
|
-
}
|
|
6045
|
-
const routePath = route.replace(/^\//, "") || "index";
|
|
6046
|
-
return {
|
|
6047
|
-
path: `${routePath}/page.tsx`,
|
|
6048
|
-
code: lines.join("\n")
|
|
6049
|
-
};
|
|
6050
|
-
}
|
|
6051
|
-
};
|
|
6052
|
-
|
|
6053
|
-
export { A2AAgentCardCompiler, A2AAgentCardCompiler_exports, ALL_PLATFORMS, BUILTIN_RESOURCES, CAPABILITY_HIERARCHY, CATEGORY_DEFAULT_EMBODIMENT, CompilerBridge, CrossRealityTraitRegistry, DEFAULT_EMBODIMENT, EFFECT_TO_CAPABILITY, EffectChecker, EffectRow, HANDOFF_PATH_RULES, LinearTypeChecker, MVC_BUDGET_CONSTRAINTS, NIRCompiler, NIRCompiler_exports, Native2DCompiler, Native2DCompiler_exports, NextJSCompiler, PLATFORM_BUDGETS, PLATFORM_CAPABILITIES, PLATFORM_CATEGORIES, PLATFORM_EMBODIMENT_OVERRIDES, ResourceBudgetAnalyzer, TRAIT_EFFECTS, TRAIT_RESOURCE_COSTS, TRAIT_RESOURCE_MAP, TRUST_LEVEL_CAPABILITIES, USDZPipeline, agentBudgetFor, bestCategoryForTraits, buildSafetyReport, checkCapabilities, compilePipelineSource, compilePipelineSourceToNode, compilePipelineSourceToPython, compilePipelineToNode, compilePipelineToPython, createCrossRealityTraitRegistry, createEffectChecker, dangerLevel, deriveRequirements, embodimentFor, expandCapabilities, formatReport, generateCertificate, getCompilerBridge, getCrossRealityTraitRegistry, hasCapability, inferFromBuiltins, inferFromTraits, init_A2AAgentCardCompiler, init_NIRCompiler, init_Native2DCompiler, isPipelineSource, isSafeTraitSet, knownBuiltins, knownTraits, matchesPlatform, parsePipeline, platformCategory, quickSafetyCheck, resetCrossRealityTraitRegistry, resolvePlatforms, runSafetyPass, selectBlock, selectModality, selectModalityForAll };
|
|
6054
|
-
//# sourceMappingURL=chunk-BO2OKHIY.js.map
|
|
6055
|
-
//# sourceMappingURL=chunk-BO2OKHIY.js.map
|
|
6382
|
+
export { A2AAgentCardCompiler, A2AAgentCardCompiler_exports, BUILTIN_RESOURCES, CAPABILITY_HIERARCHY, CATEGORY_DEFAULT_EMBODIMENT, CompilerBridge, CrossRealityTraitRegistry, EFFECTS_BY_CATEGORY, EFFECT_TO_CAPABILITY, EffectChecker, EffectRow, GaussianSplattingCompiler, HANDOFF_PATH_RULES, LinearTypeChecker, MVC_BUDGET_CONSTRAINTS, NIRCompiler, NIRCompiler_exports, PLATFORM_BUDGETS, PLATFORM_EMBODIMENT_OVERRIDES, ResourceBudgetAnalyzer, SHARED_SORT_SHADER_PATH, SpatialPartitionPass, TRAIT_EFFECTS, TRAIT_RESOURCE_COSTS, TRAIT_RESOURCE_MAP, TRUST_LEVEL_CAPABILITIES, ThreeJSCompiler, ThreeJSCompiler_exports, USDZPipeline, bestCategoryForTraits, buildSafetyReport, checkCapabilities, compilePipelineSource, compilePipelineSourceToNode, compilePipelineSourceToPython, compilePipelineToNode, compilePipelineToPython, createCrossRealityTraitRegistry, createEffectChecker, createGaussianSplattingCompiler, dangerLevel, deriveRequirements, detectMultiUserSharedSort, effectCategory, expandCapabilities, formatReport, generateCertificate, getCompilerBridge, getCrossRealityTraitRegistry, inferFromBuiltins, inferFromTraits, init_A2AAgentCardCompiler, init_NIRCompiler, init_ThreeJSCompiler, isSafeTraitSet, knownBuiltins, knownTraits, quickSafetyCheck, resetCrossRealityTraitRegistry, runSafetyPass, selectModality, selectModalityForAll, spatialPartition };
|
|
6383
|
+
//# sourceMappingURL=chunk-QCCBXSCE.js.map
|
|
6384
|
+
//# sourceMappingURL=chunk-QCCBXSCE.js.map
|