framefields 2.2.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/README.md +11 -2
  2. package/dist/audio/index.d.mts +4 -4
  3. package/dist/audio/index.mjs +10 -10
  4. package/dist/{audio-BvYmTu5T.d.mts → audio-BNnEclHU.d.mts} +3 -3
  5. package/dist/{audio-BvYmTu5T.d.mts.map → audio-BNnEclHU.d.mts.map} +1 -1
  6. package/dist/{audio-DMUr01vS.mjs → audio-CS104aUj.mjs} +3 -3
  7. package/dist/{audio-DMUr01vS.mjs.map → audio-CS104aUj.mjs.map} +1 -1
  8. package/dist/{dist-CT___nEU.mjs → dist-BOdxAhOT.mjs} +7 -5
  9. package/dist/dist-BOdxAhOT.mjs.map +1 -0
  10. package/dist/{dist-cjxDXQdx.mjs → dist-jU289ehm.mjs} +209 -31
  11. package/dist/{dist-cjxDXQdx.mjs.map → dist-jU289ehm.mjs.map} +1 -1
  12. package/dist/effects/index.d.mts +5 -5
  13. package/dist/effects/index.mjs +36 -36
  14. package/dist/{effects-C06-AOge.mjs → effects-BzOlVD-w.mjs} +532 -4
  15. package/dist/effects-BzOlVD-w.mjs.map +1 -0
  16. package/dist/fonts/index.d.mts +1 -1
  17. package/dist/fonts/index.mjs +2 -2
  18. package/dist/{fonts-C0UuLQvr.mjs → fonts-BhlV_3Qt.mjs} +2 -2
  19. package/dist/{fonts-C0UuLQvr.mjs.map → fonts-BhlV_3Qt.mjs.map} +1 -1
  20. package/dist/{gpu-Du7GpVFW.mjs → gpu-BA1Wz_mS.mjs} +2 -2
  21. package/dist/{gpu-Du7GpVFW.mjs.map → gpu-BA1Wz_mS.mjs.map} +1 -1
  22. package/dist/{index-B-oUlLoO.d.mts → index-AdrZIWT0.d.mts} +27 -2
  23. package/dist/index-AdrZIWT0.d.mts.map +1 -0
  24. package/dist/{index-BcA8rep0.d.mts → index-B-55dXDu.d.mts} +1 -1
  25. package/dist/{index-BcA8rep0.d.mts.map → index-B-55dXDu.d.mts.map} +1 -1
  26. package/dist/{index-D-Iek5sq.d.mts → index-B3BwLHa6.d.mts} +3 -3
  27. package/dist/{index-D-Iek5sq.d.mts.map → index-B3BwLHa6.d.mts.map} +1 -1
  28. package/dist/{index-CwbszPDG.d.mts → index-BU51pxZO.d.mts} +956 -9
  29. package/dist/index-BU51pxZO.d.mts.map +1 -0
  30. package/dist/{index-XdQPNJnq.d.mts → index-CeRv1KC0.d.mts} +3 -3
  31. package/dist/{index-XdQPNJnq.d.mts.map → index-CeRv1KC0.d.mts.map} +1 -1
  32. package/dist/{index-DXfp_T-3.d.mts → index-Cg2ptXcs.d.mts} +2 -2
  33. package/dist/{index-DXfp_T-3.d.mts.map → index-Cg2ptXcs.d.mts.map} +1 -1
  34. package/dist/{index-CdyE1tst.d.mts → index-QmkcUL3W.d.mts} +2 -2
  35. package/dist/{index-CdyE1tst.d.mts.map → index-QmkcUL3W.d.mts.map} +1 -1
  36. package/dist/index.d.mts +1383 -11
  37. package/dist/index.d.mts.map +1 -1
  38. package/dist/index.mjs +3122 -83
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/preview/index.d.mts +2 -2
  41. package/dist/preview/index.mjs +10 -10
  42. package/dist/{preview-M0TsUzC6.mjs → preview-BVyG76gO.mjs} +2 -2
  43. package/dist/{preview-M0TsUzC6.mjs.map → preview-BVyG76gO.mjs.map} +1 -1
  44. package/dist/preview-engine/audio.mjs +1 -1
  45. package/dist/preview-engine/chunk-2JKXYG6J.mjs +127 -0
  46. package/dist/preview-engine/chunk-7I7PKKDL.mjs +214 -0
  47. package/dist/preview-engine/chunk-BQY4BUMN.mjs +1 -0
  48. package/dist/preview-engine/{chunk-RSMO7NPN.mjs → chunk-BSOJR4JU.mjs} +1 -1
  49. package/dist/preview-engine/chunk-BVA5NGSH.mjs +1 -0
  50. package/dist/preview-engine/{chunk-ZTHWCQ2A.mjs → chunk-FNE22WGA.mjs} +1 -1
  51. package/dist/preview-engine/chunk-GCTVRM7J.mjs +1522 -0
  52. package/dist/preview-engine/chunk-KERW7QJ4.mjs +174 -0
  53. package/dist/preview-engine/{chunk-7B5S5D4N.mjs → chunk-TPAEN6VV.mjs} +1 -1
  54. package/dist/preview-engine/chunk-YQRKT47I.mjs +1 -0
  55. package/dist/preview-engine/crypto-W5UAWSNT.mjs +1 -0
  56. package/dist/preview-engine/effects.mjs +1 -1
  57. package/dist/preview-engine/framefields.mjs +26 -26
  58. package/dist/preview-engine/player.mjs +5 -5
  59. package/dist/preview-engine/rapier-AHBIGHEL.mjs +1 -0
  60. package/dist/preview-engine/rapier-JD7KNQRV.mjs +1 -0
  61. package/dist/preview-engine/renderers-3F5AIDEL.mjs +228 -0
  62. package/dist/preview-engine/renderers-6ODPWZ2R.mjs +96 -0
  63. package/dist/preview-engine/renderers-7NCG6BYS.mjs +94 -0
  64. package/dist/preview-engine/renderers-BGGRPAVV.mjs +363 -0
  65. package/dist/preview-engine/renderers-DN2GF3I7.mjs +82 -0
  66. package/dist/preview-engine/renderers-FGHOLJJK.mjs +44 -0
  67. package/dist/preview-engine/renderers-FK72LKQC.mjs +275 -0
  68. package/dist/preview-engine/renderers-FQWWAETX.mjs +203 -0
  69. package/dist/preview-engine/renderers-HMR2NAD7.mjs +81 -0
  70. package/dist/preview-engine/renderers-HUW2ZMS3.mjs +1 -0
  71. package/dist/preview-engine/renderers-JLFGBYN4.mjs +78 -0
  72. package/dist/preview-engine/renderers-LLUEOW5T.mjs +77 -0
  73. package/dist/preview-engine/renderers-NC64EQDE.mjs +1 -0
  74. package/dist/preview-engine/renderers-PVYP2ONH.mjs +76 -0
  75. package/dist/preview-engine/renderers-TPBPNXWH.mjs +26 -0
  76. package/dist/preview-engine/renderers-UJ4YVJZT.mjs +80 -0
  77. package/dist/preview-engine/renderers-WHBDHTRI.mjs +78 -0
  78. package/dist/preview-engine/renderers-WP67KK5K.mjs +89 -0
  79. package/dist/preview-engine/renderers-YNFKFM7D.mjs +67 -0
  80. package/dist/preview-engine/renderers-ZSENYGIY.mjs +84 -0
  81. package/dist/preview-engine/signals.mjs +1 -1
  82. package/dist/{program-DzknMiY0.mjs → program-CCSfHMfh.mjs} +346 -13
  83. package/dist/program-CCSfHMfh.mjs.map +1 -0
  84. package/dist/renderer/index.d.mts +2 -2
  85. package/dist/renderer/index.mjs +2 -2
  86. package/dist/renderer-1Kv7oA86.mjs +5 -0
  87. package/dist/{renderer-1vhaKMeg.mjs → renderer-1uLtqb74.mjs} +141 -56
  88. package/dist/renderer-1uLtqb74.mjs.map +1 -0
  89. package/dist/{renderer-BerD3T-X.mjs → renderer-4VpA7LfU.mjs} +2 -2
  90. package/dist/{renderer-BerD3T-X.mjs.map → renderer-4VpA7LfU.mjs.map} +1 -1
  91. package/dist/{renderer-BNqwn0gZ.mjs → renderer-8BM6sJUR.mjs} +2 -2
  92. package/dist/{renderer-BNqwn0gZ.mjs.map → renderer-8BM6sJUR.mjs.map} +1 -1
  93. package/dist/renderer-AVHJ33nv.mjs +5 -0
  94. package/dist/{renderer-0gY4IQhM.mjs → renderer-AtLlZMQ9.mjs} +2 -2
  95. package/dist/{renderer-0gY4IQhM.mjs.map → renderer-AtLlZMQ9.mjs.map} +1 -1
  96. package/dist/renderer-B8dJGf8R.mjs +6 -0
  97. package/dist/{renderer-57ATc_mQ.mjs → renderer-B93zd3sx.mjs} +2 -2
  98. package/dist/{renderer-57ATc_mQ.mjs.map → renderer-B93zd3sx.mjs.map} +1 -1
  99. package/dist/renderer-BARst3ZD.mjs +3 -0
  100. package/dist/{renderer-CJB9nU1x.mjs → renderer-BD7Lmb8h.mjs} +3 -3
  101. package/dist/{renderer-CJB9nU1x.mjs.map → renderer-BD7Lmb8h.mjs.map} +1 -1
  102. package/dist/renderer-BEA6nknY.mjs +5 -0
  103. package/dist/renderer-BFRI5alp.mjs +222 -0
  104. package/dist/renderer-BFRI5alp.mjs.map +1 -0
  105. package/dist/{renderer-BiwIh_w4.mjs → renderer-BG5sbTXt.mjs} +3 -3
  106. package/dist/{renderer-BiwIh_w4.mjs.map → renderer-BG5sbTXt.mjs.map} +1 -1
  107. package/dist/{renderer-DtgMsjyL.mjs → renderer-BI4OMlEx.mjs} +2 -2
  108. package/dist/{renderer-DtgMsjyL.mjs.map → renderer-BI4OMlEx.mjs.map} +1 -1
  109. package/dist/renderer-BOfi06L2.mjs +5 -0
  110. package/dist/renderer-BOhvtAGL.mjs +5 -0
  111. package/dist/renderer-BQT3GI9g.mjs +5 -0
  112. package/dist/{renderer-DJfFc-XW.mjs → renderer-BRwp1kV-.mjs} +3 -3
  113. package/dist/{renderer-DJfFc-XW.mjs.map → renderer-BRwp1kV-.mjs.map} +1 -1
  114. package/dist/{renderer-u8ynJtAC.mjs → renderer-BVUTOGHs.mjs} +2 -2
  115. package/dist/{renderer-u8ynJtAC.mjs.map → renderer-BVUTOGHs.mjs.map} +1 -1
  116. package/dist/renderer-BXmStgeT.mjs +5 -0
  117. package/dist/renderer-Bajxo7Nt.mjs +5 -0
  118. package/dist/{renderer-BHskWZNG.mjs → renderer-Bel1UHA5.mjs} +2 -2
  119. package/dist/{renderer-AF884a7T.mjs → renderer-BetA_iVd.mjs} +3 -3
  120. package/dist/{renderer-AF884a7T.mjs.map → renderer-BetA_iVd.mjs.map} +1 -1
  121. package/dist/{renderer-DpW_LxLO.mjs → renderer-BmDpyiII.mjs} +3 -3
  122. package/dist/{renderer-DpW_LxLO.mjs.map → renderer-BmDpyiII.mjs.map} +1 -1
  123. package/dist/{renderer-BteUC_7n.mjs → renderer-BonWt8jF.mjs} +3 -3
  124. package/dist/{renderer-BteUC_7n.mjs.map → renderer-BonWt8jF.mjs.map} +1 -1
  125. package/dist/{renderer-BC8XOVl5.mjs → renderer-BpEsZG3t.mjs} +3 -3
  126. package/dist/{renderer-BC8XOVl5.mjs.map → renderer-BpEsZG3t.mjs.map} +1 -1
  127. package/dist/{renderer-aArb4RwJ.mjs → renderer-BvBIHi6N.mjs} +2 -2
  128. package/dist/{renderer-aArb4RwJ.mjs.map → renderer-BvBIHi6N.mjs.map} +1 -1
  129. package/dist/{renderer-Db3JIF1K.mjs → renderer-BvvuGfZk.mjs} +3 -3
  130. package/dist/{renderer-Db3JIF1K.mjs.map → renderer-BvvuGfZk.mjs.map} +1 -1
  131. package/dist/renderer-BzRR0KMm.mjs +5 -0
  132. package/dist/{renderer-DEuIwr-t.mjs → renderer-Bzl0s07U.mjs} +2 -2
  133. package/dist/{renderer-DEuIwr-t.mjs.map → renderer-Bzl0s07U.mjs.map} +1 -1
  134. package/dist/renderer-C39GD6jP.mjs +331 -0
  135. package/dist/renderer-C39GD6jP.mjs.map +1 -0
  136. package/dist/renderer-C3Gjy2iE.mjs +5 -0
  137. package/dist/{renderer-Br6KyRO_.mjs → renderer-C3lPwajT.mjs} +3 -3
  138. package/dist/{renderer-Br6KyRO_.mjs.map → renderer-C3lPwajT.mjs.map} +1 -1
  139. package/dist/renderer-C5hQgkz-.mjs +5 -0
  140. package/dist/{renderer-CebB0v1y.mjs → renderer-C6cF5seJ.mjs} +2 -2
  141. package/dist/{renderer-CebB0v1y.mjs.map → renderer-C6cF5seJ.mjs.map} +1 -1
  142. package/dist/renderer-C8GZ0pCV.mjs +191 -0
  143. package/dist/renderer-C8GZ0pCV.mjs.map +1 -0
  144. package/dist/{renderer-CuVPo-wP.mjs → renderer-CFe9pZFN.mjs} +2 -2
  145. package/dist/{renderer-CuVPo-wP.mjs.map → renderer-CFe9pZFN.mjs.map} +1 -1
  146. package/dist/renderer-CLF-MiOA.mjs +5 -0
  147. package/dist/renderer-CLa43fCd.mjs +5 -0
  148. package/dist/{renderer-Bvx56GR6.mjs → renderer-CLdwOhST.mjs} +2 -2
  149. package/dist/{renderer-Bvx56GR6.mjs.map → renderer-CLdwOhST.mjs.map} +1 -1
  150. package/dist/renderer-CMK1d6w_.mjs +5 -0
  151. package/dist/{renderer-CursFKUf.mjs → renderer-CMdtUn5o.mjs} +2 -2
  152. package/dist/{renderer-CursFKUf.mjs.map → renderer-CMdtUn5o.mjs.map} +1 -1
  153. package/dist/{renderer-DXqIslFk.mjs → renderer-CNYfB5cC.mjs} +2 -2
  154. package/dist/{renderer-DXqIslFk.mjs.map → renderer-CNYfB5cC.mjs.map} +1 -1
  155. package/dist/renderer-CPEQOe3u.mjs +5 -0
  156. package/dist/{renderer-BbdZ0YHR.mjs → renderer-CWx3Kg79.mjs} +3 -3
  157. package/dist/{renderer-BbdZ0YHR.mjs.map → renderer-CWx3Kg79.mjs.map} +1 -1
  158. package/dist/{renderer-CWBHVCvA.mjs → renderer-CdOy3EBJ.mjs} +2 -2
  159. package/dist/{renderer-CWBHVCvA.mjs.map → renderer-CdOy3EBJ.mjs.map} +1 -1
  160. package/dist/{renderer-DupsdRIw.mjs → renderer-Celrh689.mjs} +3 -3
  161. package/dist/{renderer-DupsdRIw.mjs.map → renderer-Celrh689.mjs.map} +1 -1
  162. package/dist/renderer-CemfjOM9.mjs +5 -0
  163. package/dist/{renderer-jYxN4mHn.mjs → renderer-ChloaI6P.mjs} +3 -3
  164. package/dist/{renderer-jYxN4mHn.mjs.map → renderer-ChloaI6P.mjs.map} +1 -1
  165. package/dist/{renderer-DqdhsSwS.mjs → renderer-CiMpdh0s.mjs} +2 -2
  166. package/dist/{renderer-DqdhsSwS.mjs.map → renderer-CiMpdh0s.mjs.map} +1 -1
  167. package/dist/renderer-CkcrScs9.mjs +5 -0
  168. package/dist/{renderer-CMT4QcpV.mjs → renderer-Cn6VlWHZ.mjs} +3 -3
  169. package/dist/{renderer-CMT4QcpV.mjs.map → renderer-Cn6VlWHZ.mjs.map} +1 -1
  170. package/dist/renderer-CqewgazK.mjs +224 -0
  171. package/dist/renderer-CqewgazK.mjs.map +1 -0
  172. package/dist/{renderer-C6md3msE.mjs → renderer-Cu5k5D9N.mjs} +2 -2
  173. package/dist/{renderer-C6md3msE.mjs.map → renderer-Cu5k5D9N.mjs.map} +1 -1
  174. package/dist/{renderer-id8TbKBY.mjs → renderer-CuphUktB.mjs} +2 -2
  175. package/dist/{renderer-id8TbKBY.mjs.map → renderer-CuphUktB.mjs.map} +1 -1
  176. package/dist/renderer-CwrLihY6.mjs +5 -0
  177. package/dist/{renderer-BzDjy1_x.mjs → renderer-D1Jt-c3F.mjs} +2 -2
  178. package/dist/{renderer-BzDjy1_x.mjs.map → renderer-D1Jt-c3F.mjs.map} +1 -1
  179. package/dist/{renderer-Beg7FLt2.mjs → renderer-D1wd0FhZ.mjs} +75 -27
  180. package/dist/renderer-D1wd0FhZ.mjs.map +1 -0
  181. package/dist/{renderer-jqByPgkD.mjs → renderer-D26S5hUh.mjs} +2 -2
  182. package/dist/{renderer-jqByPgkD.mjs.map → renderer-D26S5hUh.mjs.map} +1 -1
  183. package/dist/renderer-D4S6i2MC.mjs +5 -0
  184. package/dist/{renderer-BmGPTWwV.mjs → renderer-D7ss6fLB.mjs} +3 -3
  185. package/dist/{renderer-BmGPTWwV.mjs.map → renderer-D7ss6fLB.mjs.map} +1 -1
  186. package/dist/renderer-DB8F0XoP.mjs +5 -0
  187. package/dist/{renderer-PKQNH21k.mjs → renderer-DCGLXnYW.mjs} +2 -2
  188. package/dist/{renderer-CrABA3lB.mjs → renderer-DCYabwlC.mjs} +2 -2
  189. package/dist/{renderer-CrABA3lB.mjs.map → renderer-DCYabwlC.mjs.map} +1 -1
  190. package/dist/renderer-DGpVLJOn.mjs +5 -0
  191. package/dist/renderer-DGxibeSa.mjs +5 -0
  192. package/dist/renderer-DJQm3bAW.mjs +5 -0
  193. package/dist/{renderer-DD8napek.mjs → renderer-DMZ5aLU1.mjs} +2 -2
  194. package/dist/{renderer-DD8napek.mjs.map → renderer-DMZ5aLU1.mjs.map} +1 -1
  195. package/dist/renderer-DMftVSfX.mjs +5 -0
  196. package/dist/renderer-DNpovOd8.mjs +5 -0
  197. package/dist/renderer-DO5r7ZV-.mjs +658 -0
  198. package/dist/renderer-DO5r7ZV-.mjs.map +1 -0
  199. package/dist/{renderer-DZXbgVMK.mjs → renderer-DOWekunR.mjs} +3 -3
  200. package/dist/{renderer-DZXbgVMK.mjs.map → renderer-DOWekunR.mjs.map} +1 -1
  201. package/dist/{renderer-Cce2fgpX.mjs → renderer-DPWeKe_x.mjs} +3 -3
  202. package/dist/{renderer-Cce2fgpX.mjs.map → renderer-DPWeKe_x.mjs.map} +1 -1
  203. package/dist/{renderer-CE7fwGgw.mjs → renderer-DQtk282o.mjs} +29 -8
  204. package/dist/renderer-DQtk282o.mjs.map +1 -0
  205. package/dist/renderer-DSHlvKQk.mjs +5 -0
  206. package/dist/renderer-DUBb7D17.mjs +219 -0
  207. package/dist/renderer-DUBb7D17.mjs.map +1 -0
  208. package/dist/renderer-DYtrdR2p.mjs +5 -0
  209. package/dist/{renderer-Bn2eQE-t.mjs → renderer-DaCsT-XU.mjs} +3 -3
  210. package/dist/{renderer-Bn2eQE-t.mjs.map → renderer-DaCsT-XU.mjs.map} +1 -1
  211. package/dist/{renderer-D1Cm21eq.mjs → renderer-DcAfp1Er.mjs} +2 -2
  212. package/dist/{renderer-D1Cm21eq.mjs.map → renderer-DcAfp1Er.mjs.map} +1 -1
  213. package/dist/{renderer-C8uKdelk.mjs → renderer-DdlaBsk_.mjs} +2 -2
  214. package/dist/{renderer-C8uKdelk.mjs.map → renderer-DdlaBsk_.mjs.map} +1 -1
  215. package/dist/renderer-DerDxKK3.mjs +220 -0
  216. package/dist/renderer-DerDxKK3.mjs.map +1 -0
  217. package/dist/{renderer-CeyAgJnw.mjs → renderer-DfkWYUTX.mjs} +2 -2
  218. package/dist/{renderer-DHGTzype.mjs → renderer-Dh-OF6aH.mjs} +2 -2
  219. package/dist/{renderer-DHGTzype.mjs.map → renderer-Dh-OF6aH.mjs.map} +1 -1
  220. package/dist/renderer-Dk-THZHp.mjs +222 -0
  221. package/dist/renderer-Dk-THZHp.mjs.map +1 -0
  222. package/dist/{renderer-BT-_EoXw.d.mts → renderer-DlESyfg7.d.mts} +2 -2
  223. package/dist/{renderer-BT-_EoXw.d.mts.map → renderer-DlESyfg7.d.mts.map} +1 -1
  224. package/dist/renderer-DpWRj6zF.mjs +203 -0
  225. package/dist/renderer-DpWRj6zF.mjs.map +1 -0
  226. package/dist/renderer-DpwlN4LH.mjs +233 -0
  227. package/dist/renderer-DpwlN4LH.mjs.map +1 -0
  228. package/dist/{renderer-DvFaC_-7.mjs → renderer-Dq4aO7az.mjs} +2 -2
  229. package/dist/{renderer-DvFaC_-7.mjs.map → renderer-Dq4aO7az.mjs.map} +1 -1
  230. package/dist/renderer-DuSImLUz.mjs +5 -0
  231. package/dist/{renderer-BeIUgp1r.mjs → renderer-DukD7S3w.mjs} +2 -2
  232. package/dist/{renderer-BeIUgp1r.mjs.map → renderer-DukD7S3w.mjs.map} +1 -1
  233. package/dist/{renderer-EemDpvv3.mjs → renderer-FXUCKps6.mjs} +3 -3
  234. package/dist/{renderer-EemDpvv3.mjs.map → renderer-FXUCKps6.mjs.map} +1 -1
  235. package/dist/renderer-FbyMYKXe.mjs +5 -0
  236. package/dist/renderer-HMl2V4iM.mjs +541 -0
  237. package/dist/renderer-HMl2V4iM.mjs.map +1 -0
  238. package/dist/renderer-LM_XIKl1.mjs +203 -0
  239. package/dist/renderer-LM_XIKl1.mjs.map +1 -0
  240. package/dist/renderer-NMFv7Auz.mjs +5 -0
  241. package/dist/{renderer-YbaCzPcG.mjs → renderer-O1b-oYJE.mjs} +2 -2
  242. package/dist/renderer-P3vpdUnb.mjs +5 -0
  243. package/dist/renderer-PknbdJyL.mjs +208 -0
  244. package/dist/renderer-PknbdJyL.mjs.map +1 -0
  245. package/dist/renderer-QTOm26Lg.mjs +5 -0
  246. package/dist/renderer-YJ3Yukou.mjs +215 -0
  247. package/dist/renderer-YJ3Yukou.mjs.map +1 -0
  248. package/dist/{renderer-p_C_T9Kn.mjs → renderer-YdLL2o6d.mjs} +2 -2
  249. package/dist/{renderer-p_C_T9Kn.mjs.map → renderer-YdLL2o6d.mjs.map} +1 -1
  250. package/dist/renderer-ahzhMa5q.mjs +5 -0
  251. package/dist/{renderer-D-vRKssW.mjs → renderer-c-bwxMde.mjs} +2 -2
  252. package/dist/{renderer-D-vRKssW.mjs.map → renderer-c-bwxMde.mjs.map} +1 -1
  253. package/dist/renderer-dThfTNge.mjs +5 -0
  254. package/dist/renderer-dUkOBfGB.mjs +308 -0
  255. package/dist/renderer-dUkOBfGB.mjs.map +1 -0
  256. package/dist/renderer-dgAS_k7B.mjs +5 -0
  257. package/dist/renderer-g-ui08Lh.mjs +204 -0
  258. package/dist/renderer-g-ui08Lh.mjs.map +1 -0
  259. package/dist/renderer-kSs8VtY7.mjs +223 -0
  260. package/dist/renderer-kSs8VtY7.mjs.map +1 -0
  261. package/dist/{renderer-KnCcN_Nz.mjs → renderer-pPiQwFYh.mjs} +2 -2
  262. package/dist/{renderer-KnCcN_Nz.mjs.map → renderer-pPiQwFYh.mjs.map} +1 -1
  263. package/dist/{renderer-D8thCpS7.mjs → renderer-wL-ly4fT.mjs} +3 -3
  264. package/dist/{renderer-D8thCpS7.mjs.map → renderer-wL-ly4fT.mjs.map} +1 -1
  265. package/dist/{renderers-CP8CFWDs-BA-4l6By.mjs → renderers-CP8CFWDs-CVHwMTiz.mjs} +2 -2
  266. package/dist/{renderers-CP8CFWDs-BA-4l6By.mjs.map → renderers-CP8CFWDs-CVHwMTiz.mjs.map} +1 -1
  267. package/dist/signals/index.d.mts +5 -5
  268. package/dist/signals/index.mjs +4 -4
  269. package/package.json +58 -55
  270. package/dist/dist-CT___nEU.mjs.map +0 -1
  271. package/dist/effects-C06-AOge.mjs.map +0 -1
  272. package/dist/index-B-oUlLoO.d.mts.map +0 -1
  273. package/dist/index-CwbszPDG.d.mts.map +0 -1
  274. package/dist/preview-engine/chunk-G4K6TLNA.mjs +0 -1
  275. package/dist/preview-engine/chunk-HVCAOHNI.mjs +0 -1
  276. package/dist/preview-engine/chunk-KBO6EX3M.mjs +0 -1448
  277. package/dist/preview-engine/chunk-N4LHIPHZ.mjs +0 -340
  278. package/dist/preview-engine/chunk-NECOKNHA.mjs +0 -174
  279. package/dist/preview-engine/renderers-T4JMJXWL.mjs +0 -1
  280. package/dist/preview-engine/renderers-VFV5QWO3.mjs +0 -1
  281. package/dist/preview-engine/renderers-VUL4HBX3.mjs +0 -228
  282. package/dist/program-DzknMiY0.mjs.map +0 -1
  283. package/dist/renderer--IDyGdqT.mjs +0 -5
  284. package/dist/renderer-17K4tjid.mjs +0 -5
  285. package/dist/renderer-1vhaKMeg.mjs.map +0 -1
  286. package/dist/renderer-Ab9Ttn_m.mjs +0 -5
  287. package/dist/renderer-B-roDBBo.mjs +0 -5
  288. package/dist/renderer-B03uwoUX.mjs +0 -5
  289. package/dist/renderer-B3BI_7YJ.mjs +0 -5
  290. package/dist/renderer-BGD4lQ74.mjs +0 -5
  291. package/dist/renderer-BHXhYfeC.mjs +0 -5
  292. package/dist/renderer-BRsTIMFa.mjs +0 -5
  293. package/dist/renderer-Beg7FLt2.mjs.map +0 -1
  294. package/dist/renderer-BjMTtYZw.mjs +0 -5
  295. package/dist/renderer-BoCh3Yts.mjs +0 -5
  296. package/dist/renderer-BqPbR8c4.mjs +0 -5
  297. package/dist/renderer-Bxa4SDm9.mjs +0 -3
  298. package/dist/renderer-C4Da2I1-.mjs +0 -5
  299. package/dist/renderer-C93X6dgl.mjs +0 -5
  300. package/dist/renderer-CE7fwGgw.mjs.map +0 -1
  301. package/dist/renderer-CMAwFfGx.mjs +0 -6
  302. package/dist/renderer-CRXeSuX2.mjs +0 -5
  303. package/dist/renderer-CSp6WYBN.mjs +0 -5
  304. package/dist/renderer-CUXX7HTL.mjs +0 -5
  305. package/dist/renderer-CUgThpka.mjs +0 -5
  306. package/dist/renderer-CeVtufiT.mjs +0 -5
  307. package/dist/renderer-CespkZUk.mjs +0 -5
  308. package/dist/renderer-D1l47xhL.mjs +0 -5
  309. package/dist/renderer-DDuG18J8.mjs +0 -5
  310. package/dist/renderer-DFhrFSMn.mjs +0 -5
  311. package/dist/renderer-DO48vQ7Y.mjs +0 -5
  312. package/dist/renderer-DTC39B_n.mjs +0 -5
  313. package/dist/renderer-DbyU3hNF.mjs +0 -5
  314. package/dist/renderer-DftVpmfu.mjs +0 -5
  315. package/dist/renderer-Dj5jm63K.mjs +0 -5
  316. package/dist/renderer-Dju57ZaF.mjs +0 -5
  317. package/dist/renderer-Dn8TQCw7.mjs +0 -5
  318. package/dist/renderer-ETF46K0D.mjs +0 -5
  319. package/dist/renderer-azYzWGC3.mjs +0 -5
  320. package/dist/renderer-dxNoRW59.mjs +0 -5
  321. package/dist/renderer-fdfelx_I.mjs +0 -5
  322. package/dist/renderer-snwEKwMw.mjs +0 -5
package/dist/index.mjs CHANGED
@@ -1,59 +1,59 @@
1
1
  import "./chunk-GBe2k3y8.mjs";
2
2
  import { $ as TimelineTransformSchema, $t as serializeSignalData, A as MIME_TYPES, At as gradientStopsToOklab, B as OutputItemSchema, Bt as parseCssColor, C as FileDataSchema, Ct as generateId, D as HandleTypeVal, Dt as getLeafMediaType, E as Gradient, Et as getFingerprint, F as ModerationUnrefundableError, Ft as isVirtualMediaData, G as SignalGateDataSchema, Gt as reportRenderDiagnostic, H as Signal, Ht as programmaticSignal, I as MultiOutputGenericSchema, It as limitGradientStops, J as SingleOutputGenericSchema, Jt as resolveNumber, K as SignalMathDataSchema, Kt as resolveBoolean, L as NodeMetadataSchema, Lt as mixColors, M as MediaOperationSchema, Mt as isCssGradient, N as MediaSourceSchema, Nt as isEqual, O as JsonValueSchema, Ot as getMediaType, P as ModerationError, Pt as isSignal, Q as TimelineSegmentSchema, Qt as sampleColorStops, R as NodeResultSchema, Rt as normalizeColorStops, S as FileAssetSchema, St as frameSignal, T as GlobalCompositeOperation, Tt as getFileDataMetadata, U as SignalChannelMetaSchema, Ut as progressSignal, V as ProgrammaticSignal, Vt as parseCssGradient, W as SignalDataSchema, Wt as registerSignalDependency, X as TEXT_LAYER_DEFAULTS, Xt as resolveString, Y as SourceOperationSchema, Yt as resolveParam, Z as TextOperationSchema, Zt as rgbToOklab, _ as DataTypeVal, _t as deserializeSignalData, a as BaseVideoLayerPropsSchema, an as timeSignal, at as VideoStylePropsSchema, b as ExportResultSchema, bt as formatHex, c as COMPOSITOR_DEFAULTS, ct as VirtualMediaDataSchema, d as ConfigSchemaRegistry, dt as computeVideoCropRenderProps, en as signal, et as TransitionSchema, f as DATA_TYPE_EXTENSIONS, ft as computed, g as DataType, gt as dataTypeColors, h as DEFAULT_MEDIA_DIMENSION, ht as createVirtualMedia, i as BaseMediaOperationPropsSchema, in as takeRenderDiagnostics, it as VideoSpatialPropsSchema, j as MediaMetadataSchema, jt as hasOnlySingleSource, k as MAX_GRADIENT_STOPS, kt as getRenderFingerprint, l as Color, lt as appendOperation, m as DEFAULT_FPS, mt as createOutputItemSchema, n as AnyOutputUnionSchema, nn as sineSignal, nt as VideoAnimationSchema, o as CAPTION_LAYER_DEFAULTS, on as updateClockSignals, ot as VideoTextPropsSchema, p as DEFAULT_DURATION_MS, pt as cosineSignal, q as SignalStatsSchema, qt as resolveMediaMimeType, r as AudioExtractorSignalDataSchema, rn as stampResult, rt as VideoLayerTypeSchema, s as COMPOSITE_OPERATIONS, st as VideoTimingPropsSchema, t as AnimationTypeSchema, tn as signalBuilder, tt as TransitionTypeSchema, u as ConfigHandleSchema, ut as checkNodeResultCache, v as DataTypes, vt as extractSvgDimensions, w as GeneratorSignalDataSchema, wt as getActiveMediaMetadata, x as ExtendedLayerSchema, xt as frameArraySignal, y as Effect$1, yt as findSourceAsset, z as NodeVisualConfigSchema, zt as oklabToRgb } from "./dist-fjKpBYkc.mjs";
3
- import { $t as TextWigglySelectorSchema, An as samplePathChainGeometry, At as KineticMarqueeConfigSchema, B as loadOBJ, Bt as Spatial3DPropertiesSchema, Cn as generateArcLengthLUT, Ct as CubicBezierSegmentSchema, Dn as parseSvgPathToCubicBeziers, Dt as ExtendedGlyphPropertiesSchema, En as getShuffledOrder, Et as ExpressionSelectorSchema, Ft as SelectorModeSchema, G as parseFBX, Gt as TextCursorStyleSchema, Ht as TextAnchorConfigSchema, I as inputStore, It as SelectorShapeSchema, Jt as TextPathSourceSchema, K as parseMTL, Kt as TextPathBuilder, Lt as SelectorUnitsSchema, Mn as waveToCubicBeziers, Mt as LongShadowConfigSchema, N as getPrimitiveGeometry, Nt as ParticleDissolveConfigSchema, On as sampleAudioSpectrumScale, Ot as GlyphAnchorGroupingSchema, Pt as SelectorBasedOnSchema, Q as shaderStore, Qt as TextSignalSelectorSchema, R as loadFBX, Sn as evaluateVolumetricFormation, St as ChromaticGlitchConfigSchema, Tn as getScramblePool, Tt as EnhancedTextNodeSchema, U as mediaDecoderCache, Ut as TextAnimatorBuilder, V as lutStore, Vt as SpringPhysicsSchema, Wt as TextCursorConfigSchema, Xt as TextScrambleConfigSchema, Yt as TextRangeSelectorSchema, Zt as TextSelectorSchema, _n as evaluateMarqueeOffset, _t as AnchorGroupingSchema, a as GlassPipeline, an as VolumetricFormationModeSchema, at as ENVIRONMENT_PRESETS, b as describeGpu, bn as evaluateSpringProgress, c as Renderer2D, cn as computeAnchorPivotOffset, ct as MAX_LIGHTS, dn as deterministicWigglyNoise, dt as Vector3Math, en as TypewriterAnimatorSchema, f as ShadowPipeline, fn as distanceToCurveParameter, ft as parseColorToRgb, gn as evaluateExpressionSelector, gt as AdvancedTextAnimatorSchema, h as SlugPipeline, hn as evaluateCubicBezierDerivative, ht as AdvancedTextAnimatorBuilder, i as EffectPipeline, in as VolumetricFormationConfigSchema, it as Camera3D, j as generateExtrudedTextGeometry, jn as signalRegistry, jt as LineSpacingDynamicsSchema, k as ensureDevice, kn as sampleCurveGeometry, kt as GlyphAnchorPointSchema, l as Renderer3D, ln as computeLineLeadingDisplacement, lt as Matrix4Math, mn as evaluateCubicBezier, mt as AETextAnimatorSchema, n as AudioLatentTrackCache, nn as VariableFontAxesSchema, o as MotionBlurPipeline, on as buildPathLUT, ot as LIGHT_UNIFORM_SIZE_BYTES, p as SlugFontCache, pn as ellipseToCubicBeziers, pt as resolveEnvironment, q as parseOBJ, qt as TextPathOptionsSchema, r as AudioMeshDeformPipeline, rn as Vec2Schema, st as Light3D, t as AudioLatentEngine, tn as TypingCadenceSchema, tt as textureCache, u as SSAOPipeline, un as computeRangeSelectorWeight, ut as Path3D, vn as evaluateSelectorCombination, vt as AnchorPresetSchema, wn as generatePathSegments, wt as DynamicStrokePropertiesSchema, xn as evaluateTypewriterState, xt as AudioSpectrumTypographySchema, yn as evaluateSkewMatrix, yt as AnimatableGlyphPropsSchema, z as loadModel3D, zt as SkewPropertiesSchema } from "./dist-cjxDXQdx.mjs";
4
- import "./renderers-CP8CFWDs-BA-4l6By.mjs";
3
+ import { $t as TextSelectorSchema, A as ensureDevice, An as sampleAudioSpectrumScale, At as GlyphAnchorGroupingSchema, B as loadModel3D, Cn as evaluateTypewriterState, Ct as AudioSpectrumTypographySchema, Dn as getScramblePool, Dt as EnhancedTextNodeSchema, En as generatePathSegments, Et as DynamicStrokePropertiesSchema, Ft as ParticleDissolveConfigSchema, G as parseColor, Gt as TextAnimatorBuilder, H as lutStore, Ht as Spatial3DPropertiesSchema, It as SelectorBasedOnSchema, J as parseOBJ, Jt as TextPathBuilder, K as parseFBX, Kt as TextCursorConfigSchema, L as inputStore, Lt as SelectorModeSchema, M as generateExtrudedTextGeometry, Mn as samplePathChainGeometry, Mt as KineticMarqueeConfigSchema, Nn as signalRegistry, Nt as LineSpacingDynamicsSchema, On as getShuffledOrder, Ot as ExpressionSelectorSchema, P as getPrimitiveGeometry, Pn as waveToCubicBeziers, Pt as LongShadowConfigSchema, Qt as TextScrambleConfigSchema, Rt as SelectorShapeSchema, Sn as evaluateSpringProgress, Tn as generateArcLengthLUT, Tt as CubicBezierSegmentSchema, Ut as SpringPhysicsSchema, V as loadOBJ, Vt as SkewPropertiesSchema, W as mediaDecoderCache, Wt as TextAnchorConfigSchema, Xt as TextPathSourceSchema, Y as parseSvgPathToSegments, Yt as TextPathOptionsSchema, Zt as TextRangeSelectorSchema, _ as buildShapeSvgPath, _n as evaluateCubicBezierDerivative, _t as AdvancedTextAnimatorBuilder, a as GlassPipeline, an as Vec2Schema, bn as evaluateSelectorCombination, bt as AnchorPresetSchema, c as Renderer2D, cn as buildPathLUT, ct as LIGHT_UNIFORM_SIZE_BYTES, dn as computeLineLeadingDisplacement, dt as Matrix4Math, en as TextSignalSelectorSchema, et as shaderStore, f as ShadowPipeline, fn as computeRangeSelectorWeight, ft as Path3D, gn as evaluateCubicBezier, gt as AETextAnimatorSchema, h as SlugPipeline, hn as ellipseToCubicBeziers, ht as resolveEnvironment, i as EffectPipeline, in as VariableFontAxesSchema, jn as sampleCurveGeometry, jt as GlyphAnchorPointSchema, kn as parseSvgPathToCubicBeziers, kt as ExtendedGlyphPropertiesSchema, l as Renderer3D, lt as Light3D, mn as distanceToCurveParameter, mt as parseColorToRgb, n as AudioLatentTrackCache, nn as TypewriterAnimatorSchema, o as MotionBlurPipeline, on as VolumetricFormationConfigSchema, ot as Camera3D, p as SlugFontCache, pn as deterministicWigglyNoise, pt as Vector3Math, q as parseMTL, qt as TextCursorStyleSchema, r as AudioMeshDeformPipeline, rn as TypingCadenceSchema, rt as textureCache, sn as VolumetricFormationModeSchema, st as ENVIRONMENT_PRESETS, t as AudioLatentEngine, tn as TextWigglySelectorSchema, u as SSAOPipeline, un as computeAnchorPivotOffset, ut as MAX_LIGHTS, vn as evaluateExpressionSelector, vt as AdvancedTextAnimatorSchema, wn as evaluateVolumetricFormation, wt as ChromaticGlitchConfigSchema, x as describeGpu, xn as evaluateSkewMatrix, xt as AnimatableGlyphPropsSchema, yn as evaluateMarqueeOffset, yt as AnchorGroupingSchema, z as loadFBX, zt as SelectorUnitsSchema } from "./dist-jU289ehm.mjs";
4
+ import "./renderers-CP8CFWDs-CVHwMTiz.mjs";
5
5
  import "./signals-DGRs6ddH.mjs";
6
- import "./renderer-BmGPTWwV.mjs";
6
+ import "./renderer-D7ss6fLB.mjs";
7
7
  import "./renderer-BajIOuZH.mjs";
8
- import { _ as spring, c as computeStrokeRect, d as measureSpring, f as measureText, g as requiresIsolation, h as preloadFont, i as mixAudioTracks, l as interpolate, m as preloadCompositionFonts, o as Easing, p as measureTextAsync, s as bezier, u as mapBlendModeToSkia, v as springCalculation } from "./dist-CT___nEU.mjs";
9
- import { t as AudioSignal } from "./audio-DMUr01vS.mjs";
10
- import { t as FontManager } from "./fonts-C0UuLQvr.mjs";
11
- import "./renderer-CWBHVCvA.mjs";
12
- import "./renderer-CebB0v1y.mjs";
13
- import "./renderer-DtgMsjyL.mjs";
14
- import "./renderer-DvFaC_-7.mjs";
15
- import "./renderer-Bvx56GR6.mjs";
16
- import "./renderer-u8ynJtAC.mjs";
8
+ import { _ as spring, c as computeStrokeRect, d as measureSpring, f as measureText, g as requiresIsolation, h as preloadFont, i as mixAudioTracks, l as interpolate, m as preloadCompositionFonts, o as Easing, p as measureTextAsync, s as bezier, u as mapBlendModeToSkia, v as springCalculation } from "./dist-BOdxAhOT.mjs";
9
+ import { t as AudioSignal } from "./audio-CS104aUj.mjs";
10
+ import { t as FontManager } from "./fonts-BhlV_3Qt.mjs";
11
+ import "./renderer-CdOy3EBJ.mjs";
12
+ import "./renderer-C6cF5seJ.mjs";
13
+ import "./renderer-BI4OMlEx.mjs";
14
+ import "./renderer-Dq4aO7az.mjs";
15
+ import "./renderer-CLdwOhST.mjs";
16
+ import "./renderer-BVUTOGHs.mjs";
17
17
  import "./renderer-B-BcgA6d.mjs";
18
- import "./renderer-D1Cm21eq.mjs";
18
+ import "./renderer-DcAfp1Er.mjs";
19
19
  import { i as softLimit, n as mixSfxInto, r as renderSfx, t as encodeStereoWav } from "./audio-DJeVoE8b.mjs";
20
20
  import { i as OpticalFlowComputePipeline, n as ControlNetMultiplexer, o as TemporalDeflickerPipeline, r as DepthNormalsComputePipeline, s as TensorPipeline, t as CannyComputePipeline } from "./dist-0QGroRYZ.mjs";
21
- import { a as PoseSkeletonRenderer, c as TemporalObjectTracker, d as VisionRunner, f as analyzeSequence, h as COCO_CLASSES, i as COCO17_KEYPOINT_NAMES, l as VisionBundle, m as pinNodeToObject, n as COCO17_BONES, o as SegmentationTexturePool, p as pinNodeToLandmark, r as COCO17_KEYPOINTS, s as SpatialLandmarkTransformer, u as VisionNode } from "./renderer-CE7fwGgw.mjs";
22
- import { A as applyStaggerToChildren, B as hoistMattes, C as ShapeNodeSchema, D as TextSpanMarkSchema, E as TextNodeSchema, F as computeLayout, H as lintComposition, I as computeLayoutSync, L as computeStaggerDelay, M as collectNodeOps, N as compositorToProgram, O as TextSpanSchema, P as computeCarrierContinuity, R as evaluateAnimationAtFrame, S as Sequence, T as TextAnimatorSchema, U as mergeAnimationTracks, _ as MediaNodeSchema, a as CarrierHandoffConfigSchema, b as SceneDefinitionSchema, c as EnvironmentFogSchema, d as LayerAnimation, f as LayoutNodeSchema, g as MatteModeSchema, h as MaterialTypeSchema, i as CameraNodeSchema, j as calculateSequenceTimeline, k as ToneMappingSchema, l as EnvironmentPresetSchema, m as LightTypeSchema, n as BoxNodeSchema, o as ColorStopSchema, p as LightNodeSchema, r as CameraAnimation, s as CompositorProgramSchema, t as BloomConfigSchema, u as FlexNodeSchema, v as Model3DNodeSchema, w as TextAnimator, x as SceneTransitionTypeSchema, y as Scene, z as evaluateTrackAtFrame } from "./program-DzknMiY0.mjs";
23
- import "./renderer-CJB9nU1x.mjs";
24
- import "./renderer-BeIUgp1r.mjs";
25
- import "./renderer-DpW_LxLO.mjs";
26
- import "./renderer-id8TbKBY.mjs";
27
- import "./renderer-DEuIwr-t.mjs";
28
- import "./renderer-DqdhsSwS.mjs";
29
- import "./renderer-0gY4IQhM.mjs";
30
- import "./renderer-EemDpvv3.mjs";
31
- import "./renderer-BbdZ0YHR.mjs";
32
- import "./renderer-CursFKUf.mjs";
33
- import "./renderer-D8thCpS7.mjs";
34
- import "./renderer-Br6KyRO_.mjs";
35
- import "./renderer-jqByPgkD.mjs";
36
- import "./renderer-C8uKdelk.mjs";
37
- import "./renderer-p_C_T9Kn.mjs";
38
- import "./renderer-BiwIh_w4.mjs";
39
- import "./renderer-BzDjy1_x.mjs";
40
- import "./renderer-Bn2eQE-t.mjs";
41
- import "./renderer-CrABA3lB.mjs";
42
- import "./renderer-D-vRKssW.mjs";
43
- import "./renderer-aArb4RwJ.mjs";
44
- import "./renderer-DD8napek.mjs";
45
- import "./renderer-DHGTzype.mjs";
46
- import "./renderer-Db3JIF1K.mjs";
47
- import "./renderer-Cce2fgpX.mjs";
48
- import "./renderer-BteUC_7n.mjs";
49
- import "./renderer-C6md3msE.mjs";
50
- import "./renderer-57ATc_mQ.mjs";
51
- import "./renderer-BNqwn0gZ.mjs";
52
- import "./renderer-BerD3T-X.mjs";
53
- import "./renderer-DXqIslFk.mjs";
54
- import { $ as StereoPanning, A as AudioReverb, B as KenBurns, C as effectFactories, D as AudioFade, E as AudioDelay, F as ColorKey, G as NoiseGenerator, H as Liquify, I as CornerPin, J as ProceduralVFX, K as Paint, L as DisplacementMap, M as ChannelMerger, N as ChannelSplitter, O as AudioNoiseGate, P as ColorBalance, Q as Rotate, R as ExtractLUT, S as Vision, T as AudioCompressor, U as MaskMath, V as LayerStyle, W as MeshWarp, X as RefractionCaustics3D, Y as RefineEdge, Z as ResizerScaler, _ as SelectiveColor, a as CustomEffect, b as TileOffset, c as GradientMap, d as Levels, et as Vignette, f as Modulate, g as SSAO, h as Relight3D, i as Curves, j as CameraParallax3D, k as AudioParametricEq, l as HalftoneScreen, m as PBRGlass, n as AudioSignalExtractor, o as DepthOfField, p as MotionBlur, q as PatchHeal, r as Crop, s as FilmGrain, t as ApplyLUT, tt as effectMeta, u as HighPass, v as ShadowsHighlights, w as Blur, x as UnsharpMask, y as TemporalDeflicker, z as Flip } from "./effects-C06-AOge.mjs";
55
- import { a as HeadlessMediaRenderer, c as renderSemaphore, i as resetRenderCaches, n as renderFrameGrid, o as HeadlessWebGPURenderer, r as resolveSamplePoints, s as formatQaReport, t as computeGridLayout } from "./renderer-1vhaKMeg.mjs";
56
- import { t as startPreview } from "./preview-M0TsUzC6.mjs";
21
+ import { _ as COCO_CLASSES, a as COCO17_KEYPOINT_NAMES, c as SpatialLandmarkTransformer, d as VisionNode, f as VisionRunner, g as pinNodeToObject, h as pinNodeToLandmark, i as COCO17_KEYPOINTS, l as TemporalObjectTracker, m as mergeSubjectMask, n as CLIP_SUBJECT, o as PoseSkeletonRenderer, p as analyzeSequence, r as COCO17_BONES, s as SegmentationTexturePool, u as VisionBundle } from "./renderer-DQtk282o.mjs";
22
+ import { A as applyStaggerToChildren, B as evaluateTrackAtFrame, C as ShapeNodeSchema, D as TextSpanMarkSchema, E as TextNodeSchema, F as computeLayout, I as computeLayoutSync, L as computeStaggerDelay, M as collectNodeOps, N as compositorToProgram, O as TextSpanSchema, P as computeCarrierContinuity, R as evaluateAnimationAtFrame, S as Sequence, T as TextAnimatorSchema, U as lintComposition, V as hoistMattes, W as mergeAnimationTracks, _ as MediaNodeSchema, a as CarrierHandoffConfigSchema, b as SceneDefinitionSchema, c as EnvironmentFogSchema, d as LayerAnimation, f as LayoutNodeSchema, g as MatteModeSchema, h as MaterialTypeSchema, i as CameraNodeSchema, j as calculateSequenceTimeline, k as ToneMappingSchema, l as EnvironmentPresetSchema, m as LightTypeSchema, n as BoxNodeSchema, o as ColorStopSchema, p as LightNodeSchema, r as CameraAnimation, s as CompositorProgramSchema, t as BloomConfigSchema, u as FlexNodeSchema, v as Model3DNodeSchema, w as TextAnimator, x as SceneTransitionTypeSchema, y as Scene } from "./program-CCSfHMfh.mjs";
23
+ import "./renderer-BD7Lmb8h.mjs";
24
+ import "./renderer-DukD7S3w.mjs";
25
+ import "./renderer-BmDpyiII.mjs";
26
+ import "./renderer-CuphUktB.mjs";
27
+ import "./renderer-Bzl0s07U.mjs";
28
+ import "./renderer-CiMpdh0s.mjs";
29
+ import "./renderer-AtLlZMQ9.mjs";
30
+ import "./renderer-FXUCKps6.mjs";
31
+ import "./renderer-CWx3Kg79.mjs";
32
+ import "./renderer-CMdtUn5o.mjs";
33
+ import "./renderer-wL-ly4fT.mjs";
34
+ import "./renderer-C3lPwajT.mjs";
35
+ import "./renderer-D26S5hUh.mjs";
36
+ import "./renderer-DdlaBsk_.mjs";
37
+ import "./renderer-YdLL2o6d.mjs";
38
+ import "./renderer-BG5sbTXt.mjs";
39
+ import "./renderer-D1Jt-c3F.mjs";
40
+ import "./renderer-DaCsT-XU.mjs";
41
+ import "./renderer-DCYabwlC.mjs";
42
+ import "./renderer-c-bwxMde.mjs";
43
+ import "./renderer-BvBIHi6N.mjs";
44
+ import "./renderer-DMZ5aLU1.mjs";
45
+ import "./renderer-Dh-OF6aH.mjs";
46
+ import "./renderer-BvvuGfZk.mjs";
47
+ import "./renderer-DPWeKe_x.mjs";
48
+ import "./renderer-BonWt8jF.mjs";
49
+ import "./renderer-Cu5k5D9N.mjs";
50
+ import "./renderer-B93zd3sx.mjs";
51
+ import "./renderer-8BM6sJUR.mjs";
52
+ import "./renderer-4VpA7LfU.mjs";
53
+ import "./renderer-CNYfB5cC.mjs";
54
+ import { $ as NoiseGenerator, A as AudioParametricEq, B as Datamosh, C as effectFactories, D as AudioDelay, E as AudioCompressor, F as ChannelSplitter, G as Gooey, H as Dither, I as ColorBalance, J as KenBurns, K as Iridescence, L as ColorKey, M as CRT, N as CameraParallax3D, O as AudioFade, P as ChannelMerger, Q as MeshWarp, R as Contour, S as Vision, T as Ascii, U as ExtractLUT, V as DisplacementMap, W as Flip, X as Liquify, Y as LayerStyle, Z as MaskMath, _ as SelectiveColor, a as CustomEffect, at as Posterize, b as TileOffset, c as GradientMap, ct as RefineEdge, d as Levels, dt as Rotate, et as OpArt, f as Modulate, ft as StereoPanning, g as SSAO, gt as effectMeta, h as Relight3D, ht as Vignette, i as Curves, it as Pixelate, j as AudioReverb, k as AudioNoiseGate, l as HalftoneScreen, lt as RefractionCaustics3D, m as PBRGlass, mt as Trails, n as AudioSignalExtractor, nt as Painterly, o as DepthOfField, ot as ProceduralVFX, p as MotionBlur, pt as Toon, q as Kaleidoscope, r as Crop, rt as PatchHeal, s as FilmGrain, st as RGBSplit, t as ApplyLUT, tt as Paint, u as HighPass, ut as ResizerScaler, v as ShadowsHighlights, w as Blur, x as UnsharpMask, y as TemporalDeflicker, z as CornerPin } from "./effects-BzOlVD-w.mjs";
55
+ import { a as HeadlessMediaRenderer, c as renderSemaphore, i as resetRenderCaches, n as renderFrameGrid, o as HeadlessWebGPURenderer, r as resolveSamplePoints, s as formatQaReport, t as computeGridLayout } from "./renderer-1uLtqb74.mjs";
56
+ import { t as startPreview } from "./preview-BVyG76gO.mjs";
57
57
  import path from "node:path";
58
58
  import fs from "node:fs/promises";
59
59
  import { format } from "d3-format";
@@ -261,8 +261,8 @@ function parseMarkup(markup) {
261
261
  } else if (tagName === "accent") style.fill = "#6366f1";
262
262
  else if (tagName === "color") style.fill = attrs.value ?? attrs.hex ?? attrs.fill;
263
263
  else if (tagName === "size") {
264
- const num = parseFloat(attrs.value ?? attrs.px ?? attrs.pt ?? "0");
265
- if (num > 0) style.fontSize = num;
264
+ const num$2 = parseFloat(attrs.value ?? attrs.px ?? attrs.pt ?? "0");
265
+ if (num$2 > 0) style.fontSize = num$2;
266
266
  } else if (tagName === "mark") {
267
267
  style.mark = {
268
268
  background: attrs.bg ?? attrs.background ?? "#6366f133",
@@ -536,9 +536,9 @@ function buildChart(options, props, defaultFontFamily) {
536
536
  }
537
537
  const yValues = [0];
538
538
  series.forEach((s, i) => {
539
- const range = stackRanges.get(i);
539
+ const range$1 = stackRanges.get(i);
540
540
  if (typeOf(s) === "candlestick") for (const c of s.data) yValues.push(c.high, c.low);
541
- else if (range) for (const [a, b] of range) yValues.push(a, b);
541
+ else if (range$1) for (const [a, b] of range$1) yValues.push(a, b);
542
542
  else for (const p of points[i]) yValues.push(p.y);
543
543
  });
544
544
  if (series.every((s) => typeOf(s) === "candlestick" || typeOf(s) === "scatter" || typeOf(s) === "line")) yValues.shift();
@@ -685,14 +685,14 @@ function buildChart(options, props, defaultFontFamily) {
685
685
  const color$1 = colorOf(s, si);
686
686
  const kind = typeOf(s);
687
687
  const pts = points[si];
688
- const range = stackRanges.get(si);
688
+ const range$1 = stackRanges.get(si);
689
689
  if (kind === "bar" && band) {
690
690
  const groupSize = stacked ? 1 : barSeries.length;
691
691
  const groupIdx = stacked ? 0 : barSeries.indexOf(si);
692
692
  const bw = band.bandwidth() / groupSize;
693
693
  const gap = groupSize > 1 ? Math.min(4, bw * .12) : 0;
694
694
  pts.forEach((p, i) => {
695
- const [lo$1, hi$1] = range ? range[i] : [0, p.y];
695
+ const [lo$1, hi$1] = range$1 ? range$1[i] : [0, p.y];
696
696
  const top = plot.y + y(Math.max(lo$1, hi$1));
697
697
  const bottom = plot.y + y(Math.min(lo$1, hi$1));
698
698
  const h = Math.max(0, bottom - top);
@@ -795,8 +795,8 @@ function buildChart(options, props, defaultFontFamily) {
795
795
  const m = Math.ceil(sw * 2 + (s.pointRadius ?? 0) + 2);
796
796
  const xy = pts.map((p, i) => ({
797
797
  x: xPos(p.x) + m,
798
- top: (range ? y(range[i][1]) : y(p.y)) + m,
799
- base: (range ? y(range[i][0]) : y(Math.max(y.domain()[0], Math.min(0, y.domain()[1])))) + m
798
+ top: (range$1 ? y(range$1[i][1]) : y(p.y)) + m,
799
+ base: (range$1 ? y(range$1[i][0]) : y(Math.max(y.domain()[0], Math.min(0, y.domain()[1])))) + m
800
800
  }));
801
801
  const curve = curveOf(s.curve);
802
802
  const frame = {
@@ -843,16 +843,16 @@ function buildChart(options, props, defaultFontFamily) {
843
843
  }));
844
844
  children.push(node);
845
845
  }
846
- if ((s.pointRadius ?? 0) > 0) dots(si, pts, color$1, s.pointRadius ?? 0, delay + timing.duration * .5, range);
846
+ if ((s.pointRadius ?? 0) > 0) dots(si, pts, color$1, s.pointRadius ?? 0, delay + timing.duration * .5, range$1);
847
847
  return;
848
848
  }
849
- if (kind === "scatter") dots(si, pts, color$1, s.pointRadius ?? 6, rank * (timing.duration / 3), range);
849
+ if (kind === "scatter") dots(si, pts, color$1, s.pointRadius ?? 6, rank * (timing.duration / 3), range$1);
850
850
  });
851
851
  if (showLegend) legendRow(legendItems);
852
- function dots(si, pts, color$1, r, baseDelay, range) {
852
+ function dots(si, pts, color$1, r, baseDelay, range$1) {
853
853
  const step = staggerStep(pts.length);
854
854
  pts.forEach((p, i) => {
855
- const py = range ? y(range[i][1]) : y(p.y);
855
+ const py = range$1 ? y(range$1[i][1]) : y(p.y);
856
856
  const node = Layer.shape("circle", {
857
857
  id: `${id}-point-${si}-${i}`,
858
858
  position: "absolute",
@@ -983,6 +983,1168 @@ function translatePath(d, dx, dy) {
983
983
  return out.join("");
984
984
  }
985
985
 
986
+ //#endregion
987
+ //#region src/clip-vision.ts
988
+ /** Frames looked back over to bridge a gap where the person is lost. */
989
+ const HOLD = 24;
990
+ const CACHE_VERSION = 1;
991
+ /**
992
+ * Vision results for one clip, computed per frame on demand and shared by
993
+ * everything that reads the clip: physics, layout, signals. Unlike the
994
+ * render-time `withVision`, which analyses a layer's previous rendered frame,
995
+ * this analyses the clip's own frames, so a result exists before its frame
996
+ * renders. The composition analyses what each frame needs just before
997
+ * drawing it (and a live physics world before stepping), so preview and
998
+ * export fill the cache as they play; nothing has to be analysed up front.
999
+ *
1000
+ * Results depend only on the clip and settings, so they persist on disk in
1001
+ * Node: a second run, or a render after a preview, reuses them. A matte-mode
1002
+ * `withVision` layer of the same clip reuses them too (`keepSubjects`).
1003
+ */
1004
+ var ClipVision = class {
1005
+ source;
1006
+ fps;
1007
+ startFrame;
1008
+ trimStartSec;
1009
+ smoothing;
1010
+ /** @internal */
1011
+ options;
1012
+ results = /* @__PURE__ */ new Map();
1013
+ sourceWidth = 0;
1014
+ sourceHeight = 0;
1015
+ cellW = 0;
1016
+ cellH = 0;
1017
+ cell;
1018
+ queue = Promise.resolve();
1019
+ runner;
1020
+ cacheLoaded;
1021
+ unsaved = 0;
1022
+ unsavedSubjects = 0;
1023
+ blurred = /* @__PURE__ */ new Map();
1024
+ smoothed = /* @__PURE__ */ new Map();
1025
+ personView;
1026
+ /** Full-resolution subject masks for render-time mattes (see `keepSubjects`). */
1027
+ subjects = /* @__PURE__ */ new Map();
1028
+ wantSubjects = false;
1029
+ subjectsLoaded;
1030
+ /** @internal Use `comp.vision(source, options)`. */
1031
+ constructor(source, fps, options = {}) {
1032
+ this.source = source;
1033
+ this.options = options;
1034
+ this.fps = options.fps ?? fps;
1035
+ this.startFrame = Math.round(options.startFrame ?? 0);
1036
+ this.trimStartSec = options.trimStartSec ?? 0;
1037
+ this.smoothing = Math.max(0, Math.round(options.smoothing ?? 2));
1038
+ this.cell = Math.max(1, Math.round(options.maskCell ?? 8));
1039
+ }
1040
+ /** The tracked person in source pixels; `.place()` maps it into the composition. */
1041
+ get person() {
1042
+ this.personView ??= new PersonTrack(this);
1043
+ return this.personView;
1044
+ }
1045
+ /**
1046
+ * Analyses what reading composition frame `frame` needs (it and a few
1047
+ * neighbours for smoothing). Pass a second frame to analyse a whole range.
1048
+ * Calls queue, so the clip is decoded once, in order.
1049
+ */
1050
+ ready(frame, toFrame = frame) {
1051
+ const [from, to] = this.window(frame, toFrame);
1052
+ this.queue = this.queue.then(() => this.compute(from, to));
1053
+ return this.queue;
1054
+ }
1055
+ /** True when composition frame `frame` can be read synchronously. */
1056
+ isReady(frame) {
1057
+ const [from, to] = this.window(frame, frame);
1058
+ for (let c = from; c <= to; c++) if (!this.results.has(c)) return false;
1059
+ return true;
1060
+ }
1061
+ /**
1062
+ * @internal Also keep each frame's full-resolution subject mask, merged
1063
+ * like the Vision effect's matte, so a matte layer of this clip reuses it
1064
+ * instead of segmenting the frame again (framefields links them).
1065
+ */
1066
+ keepSubjects() {
1067
+ this.wantSubjects = true;
1068
+ }
1069
+ /**
1070
+ * @internal The subject at a source frame of the clip (`frame` at `fps`),
1071
+ * for a render-time matte: undefined until that frame is analysed with
1072
+ * subjects kept, null when it holds no subject.
1073
+ */
1074
+ subject(frame, fps) {
1075
+ const c = frame * this.fps / fps;
1076
+ if (Math.abs(c - Math.round(c)) > 1e-6) return void 0;
1077
+ const s = this.subjects.get(Math.round(c));
1078
+ if (s === void 0) return s;
1079
+ if (s === null || !this.sourceWidth) return null;
1080
+ const width = this.sourceWidth;
1081
+ const height = this.sourceHeight;
1082
+ return {
1083
+ category: s.category,
1084
+ mask: decodeRuns(s, width * height),
1085
+ width,
1086
+ height,
1087
+ area: s.area,
1088
+ coverage: s.area / (width * height),
1089
+ detectionIndex: -1
1090
+ };
1091
+ }
1092
+ /** Composition frame → clip frame (fractional). */
1093
+ clipFrame(frame) {
1094
+ return frame - this.startFrame + this.trimStartSec * this.fps;
1095
+ }
1096
+ window(frame, toFrame) {
1097
+ const a = Math.floor(this.clipFrame(Math.min(frame, toFrame)));
1098
+ const b = Math.ceil(this.clipFrame(Math.max(frame, toFrame)));
1099
+ return [Math.max(0, a - HOLD - this.smoothing), Math.max(0, b + this.smoothing)];
1100
+ }
1101
+ analysed(c) {
1102
+ return this.results.has(c) && (!this.wantSubjects || this.subjects.has(c));
1103
+ }
1104
+ async compute(from, to) {
1105
+ this.cacheLoaded ??= this.loadCache();
1106
+ await this.cacheLoaded;
1107
+ if (this.wantSubjects) {
1108
+ this.subjectsLoaded ??= this.loadSubjects();
1109
+ await this.subjectsLoaded;
1110
+ }
1111
+ let missing = false;
1112
+ for (let c = from; c <= to; c++) if (!this.analysed(c)) missing = true;
1113
+ if (!missing) return;
1114
+ const wantPose = this.options.pose ?? true;
1115
+ const wantMask = this.options.mask ?? true;
1116
+ this.runner ??= VisionRunner.create({
1117
+ modelsDir: this.options.modelsDir,
1118
+ baseUrl: this.options.baseUrl,
1119
+ ...this.options.confidence !== void 0 && { confidence: this.options.confidence },
1120
+ ...this.options.variant !== void 0 && { variant: this.options.variant }
1121
+ });
1122
+ const decoder = mediaDecoderCache.getVideo(this.source, true, "clip-vision");
1123
+ for (let c = from; c <= to; c++) {
1124
+ if (this.analysed(c)) continue;
1125
+ const image = await decodedPixels(await decoder.getFrame(c / this.fps));
1126
+ if (!image) {
1127
+ this.results.set(c, {
1128
+ kp: null,
1129
+ mask: null
1130
+ });
1131
+ if (this.wantSubjects) this.subjects.set(c, null);
1132
+ continue;
1133
+ }
1134
+ if (!this.sourceWidth) this.setSize(image.width, image.height);
1135
+ const known = this.results.get(c);
1136
+ let kp = known?.kp ?? null;
1137
+ let mask = known?.mask ?? null;
1138
+ if (wantPose && !known) {
1139
+ const person = (await this.runner.pose(image)).people[0];
1140
+ if (person) {
1141
+ kp = new Float32Array(51);
1142
+ for (const [k, p] of person.keypoints.entries()) kp.set([
1143
+ p.x,
1144
+ p.y,
1145
+ p.visibility
1146
+ ], k * 3);
1147
+ }
1148
+ }
1149
+ const seg = wantMask && !known || this.wantSubjects ? await this.runner.segment(image) : void 0;
1150
+ if (seg && this.wantSubjects) {
1151
+ const subject = mergeSubjectMask(seg.masks);
1152
+ this.subjects.set(c, subject ? {
1153
+ category: subject.category,
1154
+ area: subject.area,
1155
+ ...encodeRuns(subject.mask)
1156
+ } : null);
1157
+ this.unsavedSubjects++;
1158
+ }
1159
+ if (seg && wantMask && !known) {
1160
+ const silhouette = personSilhouette(seg);
1161
+ if (silhouette) {
1162
+ mask = new Uint8Array(this.cellW * this.cellH);
1163
+ downsampleMean(silhouette, image.width, image.height, this.cell, mask, this.cellW, this.cellH);
1164
+ }
1165
+ }
1166
+ this.results.set(c, {
1167
+ kp,
1168
+ mask
1169
+ });
1170
+ if (!known) this.unsaved++;
1171
+ if (this.unsaved >= 24) await this.saveCache();
1172
+ if (this.unsavedSubjects >= 24) await this.saveSubjects();
1173
+ }
1174
+ if (this.unsaved > 0) await this.saveCache();
1175
+ if (this.unsavedSubjects > 0) await this.saveSubjects();
1176
+ }
1177
+ setSize(width, height) {
1178
+ this.sourceWidth = width;
1179
+ this.sourceHeight = height;
1180
+ this.cellW = Math.ceil(width / this.cell);
1181
+ this.cellH = Math.ceil(height / this.cell);
1182
+ }
1183
+ /** @internal */
1184
+ size() {
1185
+ return {
1186
+ width: this.sourceWidth,
1187
+ height: this.sourceHeight
1188
+ };
1189
+ }
1190
+ /** @internal Raw result for a clip frame, or throws when it was never analysed. */
1191
+ result(c) {
1192
+ return this.results.get(Math.max(0, c));
1193
+ }
1194
+ /** @internal Confidence-weighted keypoint over the smoothing window, in source px. */
1195
+ keypoint(k, c) {
1196
+ c = Math.max(0, c);
1197
+ const key = `${k}:${c}`;
1198
+ const hit = this.smoothed.get(key);
1199
+ if (hit) return hit;
1200
+ const avg = (center) => {
1201
+ let sx = 0;
1202
+ let sy = 0;
1203
+ let sv = 0;
1204
+ let sw = 0;
1205
+ for (let g = center - this.smoothing; g <= center + this.smoothing; g++) {
1206
+ const r = this.mustHave(g < 0 ? 0 : g);
1207
+ if (!r.kp) continue;
1208
+ const v = r.kp[k * 3 + 2];
1209
+ const w = (this.smoothing + 1 - Math.abs(g - center)) * v * v;
1210
+ sx += r.kp[k * 3] * w;
1211
+ sy += r.kp[k * 3 + 1] * w;
1212
+ sv += v * w;
1213
+ sw += w;
1214
+ }
1215
+ return sw > 1e-6 ? [
1216
+ sx / sw,
1217
+ sy / sw,
1218
+ sv / sw
1219
+ ] : null;
1220
+ };
1221
+ let out = null;
1222
+ for (let d = 0; d <= HOLD && !out; d++) if (c - d >= 0) out = avg(c - d);
1223
+ out ??= [
1224
+ this.sourceWidth / 2,
1225
+ this.sourceHeight / 2,
1226
+ 0
1227
+ ];
1228
+ this.smoothed.set(key, out);
1229
+ return out;
1230
+ }
1231
+ /** @internal Softened silhouette grid for a clip frame (null: no person). */
1232
+ blurredMask(c) {
1233
+ c = Math.max(0, c);
1234
+ if (this.blurred.has(c)) return this.blurred.get(c) ?? null;
1235
+ const r = this.mustHave(c);
1236
+ const grid = r.mask ? boxBlur(r.mask, this.cellW, this.cellH, 2) : null;
1237
+ this.blurred.set(c, grid);
1238
+ return grid;
1239
+ }
1240
+ /** @internal */
1241
+ grid() {
1242
+ return {
1243
+ cell: this.cell,
1244
+ width: this.cellW,
1245
+ height: this.cellH
1246
+ };
1247
+ }
1248
+ mustHave(c) {
1249
+ const r = this.results.get(c);
1250
+ if (r) return r;
1251
+ throw new Error(`ClipVision "${this.source}": frame ${c} is not analysed yet. Read it while rendering (the composition prepares each frame), in a live physics world, or after \`await clip.ready(frame)\`.`);
1252
+ }
1253
+ cacheFile;
1254
+ async cachePath() {
1255
+ if (this.cacheFile !== void 0) return this.cacheFile;
1256
+ this.cacheFile = null;
1257
+ if (this.options.cacheDir === false || typeof process === "undefined" || !process.versions?.node) return null;
1258
+ try {
1259
+ const [fs$1, path$1, os, crypto] = await Promise.all([
1260
+ import("node:fs"),
1261
+ import("node:path"),
1262
+ import("node:os"),
1263
+ import("node:crypto")
1264
+ ]);
1265
+ const stat = fs$1.statSync(this.source);
1266
+ const dir = this.options.cacheDir ?? process.env.FRAMEFIELDS_VISION_CACHE_DIR ?? path$1.join(os.homedir(), ".cache", "framefields", "vision");
1267
+ const o = this.options;
1268
+ const key = JSON.stringify([
1269
+ CACHE_VERSION,
1270
+ path$1.resolve(this.source),
1271
+ stat.size,
1272
+ stat.mtimeMs,
1273
+ this.fps,
1274
+ o.pose ?? true,
1275
+ o.mask ?? true,
1276
+ this.cell,
1277
+ o.variant ?? "s",
1278
+ o.confidence ?? null
1279
+ ]);
1280
+ const hash = crypto.createHash("sha256").update(key).digest("hex").slice(0, 24);
1281
+ fs$1.mkdirSync(dir, { recursive: true });
1282
+ this.cacheFile = path$1.join(dir, `${path$1.basename(this.source)}.${hash}.json`);
1283
+ } catch {
1284
+ this.cacheFile = null;
1285
+ }
1286
+ return this.cacheFile;
1287
+ }
1288
+ async loadCache() {
1289
+ const file = await this.cachePath();
1290
+ if (!file) return;
1291
+ try {
1292
+ const fs$1 = await import("node:fs");
1293
+ if (!fs$1.existsSync(file)) return;
1294
+ const json = JSON.parse(fs$1.readFileSync(file, "utf8"));
1295
+ if (json.cell !== this.cell) return;
1296
+ this.setSize(json.width, json.height);
1297
+ for (const [c, r] of Object.entries(json.frames)) this.results.set(Number(c), {
1298
+ kp: r.kp ? Float32Array.from(r.kp) : null,
1299
+ mask: r.mask ? new Uint8Array(Buffer.from(r.mask, "base64")) : null
1300
+ });
1301
+ } catch {}
1302
+ }
1303
+ async saveCache() {
1304
+ this.unsaved = 0;
1305
+ const file = await this.cachePath();
1306
+ if (!file || !this.sourceWidth) return;
1307
+ const frames = {};
1308
+ for (const [c, r] of this.results) frames[c] = {
1309
+ kp: r.kp ? Array.from(r.kp, (v) => Math.round(v * 100) / 100) : null,
1310
+ mask: r.mask ? Buffer.from(r.mask).toString("base64") : null
1311
+ };
1312
+ const fs$1 = await import("node:fs");
1313
+ const tmp = `${file}.${process.pid}.tmp`;
1314
+ fs$1.writeFileSync(tmp, JSON.stringify({
1315
+ width: this.sourceWidth,
1316
+ height: this.sourceHeight,
1317
+ cell: this.cell,
1318
+ frames
1319
+ }));
1320
+ fs$1.renameSync(tmp, file);
1321
+ }
1322
+ /** Subjects live beside the results: large, and only matte layers read them. */
1323
+ async subjectsPath() {
1324
+ const file = await this.cachePath();
1325
+ return file ? file.replace(/\.json$/, ".subjects.json") : null;
1326
+ }
1327
+ async loadSubjects() {
1328
+ const file = await this.subjectsPath();
1329
+ if (!file) return;
1330
+ try {
1331
+ const fs$1 = await import("node:fs");
1332
+ if (!fs$1.existsSync(file)) return;
1333
+ const json = JSON.parse(fs$1.readFileSync(file, "utf8"));
1334
+ if (this.sourceWidth && json.width !== this.sourceWidth) return;
1335
+ if (!this.sourceWidth) this.setSize(json.width, json.height);
1336
+ for (const [c, s] of Object.entries(json.frames)) {
1337
+ const lengths = Buffer.from(s?.lengths ?? "", "base64");
1338
+ this.subjects.set(Number(c), s && {
1339
+ category: s.category,
1340
+ area: s.area,
1341
+ values: new Uint8Array(Buffer.from(s.values, "base64")),
1342
+ lengths: new Uint32Array(lengths.buffer.slice(lengths.byteOffset, lengths.byteOffset + lengths.byteLength))
1343
+ });
1344
+ }
1345
+ } catch {}
1346
+ }
1347
+ async saveSubjects() {
1348
+ this.unsavedSubjects = 0;
1349
+ const file = await this.subjectsPath();
1350
+ if (!file || !this.sourceWidth) return;
1351
+ const frames = {};
1352
+ for (const [c, s] of this.subjects) frames[c] = s && {
1353
+ category: s.category,
1354
+ area: s.area,
1355
+ values: Buffer.from(s.values).toString("base64"),
1356
+ lengths: Buffer.from(s.lengths.buffer, s.lengths.byteOffset, s.lengths.byteLength).toString("base64")
1357
+ };
1358
+ const fs$1 = await import("node:fs");
1359
+ const tmp = `${file}.${process.pid}.tmp`;
1360
+ fs$1.writeFileSync(tmp, JSON.stringify({
1361
+ width: this.sourceWidth,
1362
+ height: this.sourceHeight,
1363
+ frames
1364
+ }));
1365
+ fs$1.renameSync(tmp, file);
1366
+ }
1367
+ };
1368
+ /**
1369
+ * The person in a {@link ClipVision}: pose keypoints and silhouette at any
1370
+ * composition frame, in source pixels or, after `place()`, composition
1371
+ * pixels. Reads are synchronous; the frame must be analysed (it is while
1372
+ * rendering, inside a live physics world, or after `await clip.ready(frame)`).
1373
+ */
1374
+ var PersonTrack = class PersonTrack {
1375
+ /** @internal */
1376
+ constructor(clip, t, placement) {
1377
+ this.clip = clip;
1378
+ this.t = t;
1379
+ this.placement = placement;
1380
+ }
1381
+ /** The same person in composition pixels for a clip laid out at `placement`. */
1382
+ place(placement) {
1383
+ return new PersonTrack(this.clip, void 0, placement);
1384
+ }
1385
+ transform() {
1386
+ if (this.t) return this.t;
1387
+ const p = this.placement;
1388
+ const { width: sw, height: sh } = this.clip.size();
1389
+ if (!p || !sw) return {
1390
+ sx: 1,
1391
+ sy: 1,
1392
+ ox: 0,
1393
+ oy: 0
1394
+ };
1395
+ let sx = p.width / sw;
1396
+ let sy = p.height / sh;
1397
+ if (p.fit !== "fill") {
1398
+ const s = p.fit === "contain" ? Math.min(sx, sy) : Math.max(sx, sy);
1399
+ sx = s;
1400
+ sy = s;
1401
+ }
1402
+ return {
1403
+ sx,
1404
+ sy,
1405
+ ox: (p.x ?? 0) + (p.width - sw * sx) / 2,
1406
+ oy: (p.y ?? 0) + (p.height - sh * sy) / 2
1407
+ };
1408
+ }
1409
+ /** A keypoint at a composition frame (fractional frames interpolate). */
1410
+ point(name, frame) {
1411
+ const k = keypointIndex(name);
1412
+ const c = this.clip.clipFrame(frame);
1413
+ const c0 = Math.floor(c);
1414
+ const u = c - c0;
1415
+ const a = this.clip.keypoint(k, c0);
1416
+ const b = u > 0 ? this.clip.keypoint(k, c0 + 1) : a;
1417
+ const t = this.transform();
1418
+ return {
1419
+ x: (a[0] + (b[0] - a[0]) * u) * t.sx + t.ox,
1420
+ y: (a[1] + (b[1] - a[1]) * u) * t.sy + t.oy,
1421
+ visibility: a[2] + (b[2] - a[2]) * u
1422
+ };
1423
+ }
1424
+ /** Signals for a keypoint, for `.signal("x", …)`; read while rendering. */
1425
+ signals(name) {
1426
+ const read = (axis) => Signal.builder({
1427
+ type: "custom",
1428
+ fn: (ctx) => this.point(name, ctx.frame)[axis]
1429
+ });
1430
+ return {
1431
+ x: read("x"),
1432
+ y: read("y"),
1433
+ visibility: read("visibility")
1434
+ };
1435
+ }
1436
+ /**
1437
+ * @internal The softened silhouette grid at a composition frame and how
1438
+ * placed px map onto it (`cell = (px − origin) / scale − 0.5`), for GPU
1439
+ * consumers such as particles. Null when no person was found.
1440
+ */
1441
+ silhouetteGrid(frame) {
1442
+ const grid = this.clip.blurredMask(Math.round(this.clip.clipFrame(frame)));
1443
+ if (!grid) return null;
1444
+ const { cell, width, height } = this.clip.grid();
1445
+ const t = this.transform();
1446
+ return {
1447
+ data: grid,
1448
+ width,
1449
+ height,
1450
+ originX: t.ox,
1451
+ originY: t.oy,
1452
+ scaleX: cell * t.sx,
1453
+ scaleY: cell * t.sy
1454
+ };
1455
+ }
1456
+ /**
1457
+ * The silhouette near a point at a composition frame: `alpha` 0–1 (softened
1458
+ * over a few cells; inside > 0.5) and its gradient `gx`, `gy` per px,
1459
+ * pointing into the body. Push things out with `-gradient`.
1460
+ */
1461
+ sample(frame, x, y) {
1462
+ const grid = this.clip.blurredMask(Math.round(this.clip.clipFrame(frame)));
1463
+ if (!grid) return {
1464
+ alpha: 0,
1465
+ gx: 0,
1466
+ gy: 0
1467
+ };
1468
+ const { cell, width: w, height: h } = this.clip.grid();
1469
+ const t = this.transform();
1470
+ const cx = (x - t.ox) / t.sx / cell - .5;
1471
+ const cy = (y - t.oy) / t.sy / cell - .5;
1472
+ const read = (gx, gy) => gx < 0 || gy < 0 || gx >= w || gy >= h ? 0 : grid[gy * w + gx];
1473
+ const bil = (px, py) => {
1474
+ const x0 = Math.floor(px);
1475
+ const y0 = Math.floor(py);
1476
+ const ux = px - x0;
1477
+ const uy = py - y0;
1478
+ const a = read(x0, y0) + (read(x0 + 1, y0) - read(x0, y0)) * ux;
1479
+ return a + (read(x0, y0 + 1) + (read(x0 + 1, y0 + 1) - read(x0, y0 + 1)) * ux - a) * uy;
1480
+ };
1481
+ return {
1482
+ alpha: bil(cx, cy),
1483
+ gx: (bil(cx + 1, cy) - bil(cx - 1, cy)) / (2 * cell * t.sx),
1484
+ gy: (bil(cx, cy + 1) - bil(cx, cy - 1)) / (2 * cell * t.sy)
1485
+ };
1486
+ }
1487
+ };
1488
+ function keypointIndex(name) {
1489
+ const i = COCO17_KEYPOINT_NAMES.indexOf(name);
1490
+ if (i < 0) throw new Error(`Unknown keypoint "${name}". Use one of ${COCO17_KEYPOINT_NAMES.join(", ")}.`);
1491
+ return i;
1492
+ }
1493
+ /** RGBA pixels of a decoded frame (headless buffer, or a canvas in the browser). */
1494
+ async function decodedPixels(frame) {
1495
+ if (!frame || frame.width <= 0) return null;
1496
+ if (frame.buffer) return {
1497
+ data: frame.buffer,
1498
+ width: frame.width,
1499
+ height: frame.height
1500
+ };
1501
+ const ctx = frame.canvas?.getContext("2d");
1502
+ if (!ctx) return null;
1503
+ return {
1504
+ data: ctx.getImageData(0, 0, frame.width, frame.height).data,
1505
+ width: frame.width,
1506
+ height: frame.height
1507
+ };
1508
+ }
1509
+ /**
1510
+ * The largest person's mask, plus instances that overlap it and are no more
1511
+ * than twice its size (a flowing dress often comes back as "kite").
1512
+ */
1513
+ function personSilhouette(seg) {
1514
+ const people = seg.masks.filter((m) => m.category === "person");
1515
+ if (people.length === 0) return void 0;
1516
+ const person = people.reduce((a, b) => b.area > a.area ? b : a);
1517
+ const box = seg.detections[person.detectionIndex]?.boundingBox;
1518
+ const out = new Uint8Array(person.mask);
1519
+ if (!box) return out;
1520
+ for (const m of seg.masks) {
1521
+ if (m === person || m.area > person.area * 2) continue;
1522
+ const b = seg.detections[m.detectionIndex]?.boundingBox;
1523
+ if (!b) continue;
1524
+ if (Math.max(0, Math.min(box.originX + box.width, b.originX + b.width) - Math.max(box.originX, b.originX)) * Math.max(0, Math.min(box.originY + box.height, b.originY + b.height) - Math.max(box.originY, b.originY)) < .3 * b.width * b.height) continue;
1525
+ for (let i = 0; i < out.length; i++) if (m.mask[i] > out[i]) out[i] = m.mask[i];
1526
+ }
1527
+ return out;
1528
+ }
1529
+ function downsampleMean(src, w, h, cell, dst, mw, mh) {
1530
+ for (let my = 0; my < mh; my++) for (let mx = 0; mx < mw; mx++) {
1531
+ let sum = 0;
1532
+ let n = 0;
1533
+ for (let y = my * cell; y < Math.min(h, (my + 1) * cell); y++) for (let x = mx * cell; x < Math.min(w, (mx + 1) * cell); x++) {
1534
+ sum += src[y * w + x];
1535
+ n++;
1536
+ }
1537
+ dst[my * mw + mx] = n ? Math.round(sum / n) : 0;
1538
+ }
1539
+ }
1540
+ /** A mask as (value, run length) pairs: long flat runs with soft edges. */
1541
+ function encodeRuns(mask) {
1542
+ let runs = 0;
1543
+ for (let i = 1; i <= mask.length; i++) if (i === mask.length || mask[i] !== mask[i - 1]) runs++;
1544
+ const values = new Uint8Array(runs);
1545
+ const lengths = new Uint32Array(runs);
1546
+ let r = 0;
1547
+ let start = 0;
1548
+ for (let i = 1; i <= mask.length; i++) if (i === mask.length || mask[i] !== mask[start]) {
1549
+ values[r] = mask[start];
1550
+ lengths[r++] = i - start;
1551
+ start = i;
1552
+ }
1553
+ return {
1554
+ values,
1555
+ lengths
1556
+ };
1557
+ }
1558
+ function decodeRuns(runs, size$1) {
1559
+ const out = new Uint8Array(size$1);
1560
+ let at = 0;
1561
+ for (let r = 0; r < runs.values.length; r++) {
1562
+ const end = Math.min(size$1, at + runs.lengths[r]);
1563
+ if (runs.values[r] !== 0) out.fill(runs.values[r], at, end);
1564
+ at = end;
1565
+ }
1566
+ return out;
1567
+ }
1568
+ /** Separable box blur to 0–1, so gradients reach a little past the edge. */
1569
+ function boxBlur(src, w, h, r) {
1570
+ const tmp = new Float32Array(w * h);
1571
+ const dst = new Float32Array(w * h);
1572
+ for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
1573
+ let s = 0;
1574
+ let n = 0;
1575
+ for (let k = -r; k <= r; k++) {
1576
+ const xx = x + k;
1577
+ if (xx >= 0 && xx < w) {
1578
+ s += src[y * w + xx];
1579
+ n++;
1580
+ }
1581
+ }
1582
+ tmp[y * w + x] = s / n / 255;
1583
+ }
1584
+ for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
1585
+ let s = 0;
1586
+ let n = 0;
1587
+ for (let k = -r; k <= r; k++) {
1588
+ const yy = y + k;
1589
+ if (yy >= 0 && yy < h) {
1590
+ s += tmp[yy * w + x];
1591
+ n++;
1592
+ }
1593
+ }
1594
+ dst[y * w + x] = s / n;
1595
+ }
1596
+ return dst;
1597
+ }
1598
+
1599
+ //#endregion
1600
+ //#region src/physics/core.ts
1601
+ const CHANNEL_TOLERANCE_SCALE = {
1602
+ rotation: .2,
1603
+ rotateX: .2,
1604
+ rotateY: .2,
1605
+ rotateZ: .2
1606
+ };
1607
+ function sampleDriver(driver, frame, fps) {
1608
+ if (typeof driver === "number") return driver;
1609
+ if (typeof driver === "function") return driver(frame);
1610
+ const time = frame / fps;
1611
+ return driver.get({
1612
+ frame,
1613
+ fps,
1614
+ time,
1615
+ duration: 0,
1616
+ durationMs: 0,
1617
+ progress: 0,
1618
+ deltaTime: 1 / fps
1619
+ });
1620
+ }
1621
+ /** Shortest-path angle continuation so rotation never jumps by 360. */
1622
+ function unwrapDegrees(previous, next) {
1623
+ let d = next - previous;
1624
+ d -= Math.round(d / 360) * 360;
1625
+ return previous + d;
1626
+ }
1627
+ /**
1628
+ * Ramer–Douglas–Peucker over one channel: the fewest linear keyframes that
1629
+ * stay within `tolerance` of every simulated frame.
1630
+ */
1631
+ function simplifyKeys(values, tolerance) {
1632
+ const n = values.length;
1633
+ if (n === 0) return [];
1634
+ const keep = new Uint8Array(n);
1635
+ keep[0] = 1;
1636
+ keep[n - 1] = 1;
1637
+ const stack$1 = [[0, n - 1]];
1638
+ while (stack$1.length > 0) {
1639
+ const [a, b] = stack$1.pop();
1640
+ let worst = -1;
1641
+ let worstErr = tolerance;
1642
+ for (let i = a + 1; i < b; i++) {
1643
+ const t = (i - a) / (b - a);
1644
+ const lerp = values[a] + (values[b] - values[a]) * t;
1645
+ const err = Math.abs(values[i] - lerp);
1646
+ if (err > worstErr) {
1647
+ worstErr = err;
1648
+ worst = i;
1649
+ }
1650
+ }
1651
+ if (worst >= 0) {
1652
+ keep[worst] = 1;
1653
+ stack$1.push([a, worst], [worst, b]);
1654
+ }
1655
+ }
1656
+ const keys = [];
1657
+ for (let i = 0; i < n; i++) if (keep[i]) keys.push([
1658
+ i,
1659
+ round4(values[i]),
1660
+ "none"
1661
+ ]);
1662
+ if (keys.length === 2 && keys[0][1] === keys[1][1]) keys.pop();
1663
+ return keys;
1664
+ }
1665
+ function round4(v) {
1666
+ return Math.round(v * 1e4) / 1e4;
1667
+ }
1668
+ /**
1669
+ * Per-frame recordings of one body, indexed by composition frame. Arrays are
1670
+ * filled when the world simulates; reading a signal before that simulates.
1671
+ */
1672
+ var Recording = class {
1673
+ channels = /* @__PURE__ */ new Map();
1674
+ signals = /* @__PURE__ */ new Map();
1675
+ constructor(length, fps, ensure) {
1676
+ this.length = length;
1677
+ this.fps = fps;
1678
+ this.ensure = ensure;
1679
+ }
1680
+ channel(name) {
1681
+ let arr = this.channels.get(name);
1682
+ if (!arr) {
1683
+ arr = new Float32Array(this.length);
1684
+ this.channels.set(name, arr);
1685
+ }
1686
+ return arr;
1687
+ }
1688
+ /**
1689
+ * A per-frame signal over a channel. Creating it does nothing; the first
1690
+ * value read runs the simulation (offline worlds), so signals can be bound
1691
+ * while bodies are still being added.
1692
+ */
1693
+ signal(name) {
1694
+ let sig = this.signals.get(name);
1695
+ if (!sig) {
1696
+ const arr = this.channel(name);
1697
+ const fps = this.fps;
1698
+ sig = Signal.builder({
1699
+ type: "custom",
1700
+ fn: (ctx) => {
1701
+ this.ensure();
1702
+ const f = ctx.fps && ctx.fps !== fps ? ctx.frame / ctx.fps * fps : ctx.frame;
1703
+ return arr[Math.max(0, Math.min(arr.length - 1, Math.round(f)))];
1704
+ }
1705
+ });
1706
+ this.signals.set(name, sig);
1707
+ }
1708
+ return sig;
1709
+ }
1710
+ };
1711
+ /**
1712
+ * Stepping, recording, impacts and output shared by `PhysicsWorld2D` and
1713
+ * `PhysicsWorld3D`. V is a vector in backend units (meters).
1714
+ */
1715
+ var WorldCore = class {
1716
+ fps;
1717
+ frames;
1718
+ startFrame;
1719
+ pixelsPerMeter;
1720
+ substeps;
1721
+ impactDecay;
1722
+ impactReference;
1723
+ bodies = [];
1724
+ forces = [];
1725
+ impulses = [];
1726
+ fields = [];
1727
+ worldRecording;
1728
+ allCollisions = [];
1729
+ /** No more bodies, joints or forces: the world has started (or finished). */
1730
+ locked = false;
1731
+ liveMode = false;
1732
+ stepper;
1733
+ chain = Promise.resolve();
1734
+ constructor(sim, gravity, options) {
1735
+ this.sim = sim;
1736
+ this.gravity = gravity;
1737
+ if (!(options.fps > 0)) throw new Error("Physics: `fps` must be > 0.");
1738
+ if (!(options.frames >= 1) || !Number.isInteger(options.frames)) throw new Error("Physics: `frames` must be a positive integer.");
1739
+ this.fps = options.fps;
1740
+ this.frames = options.frames;
1741
+ this.startFrame = Math.max(0, Math.round(options.startFrame ?? 0));
1742
+ this.pixelsPerMeter = options.pixelsPerMeter ?? 100;
1743
+ this.substeps = Math.max(1, Math.round(options.substeps ?? 4));
1744
+ this.impactDecay = Math.max(.5, options.impactDecay ?? 8);
1745
+ this.impactReference = options.impactReference ?? 1500;
1746
+ this.worldRecording = this.newRecording();
1747
+ }
1748
+ /** First contacts so far (all of them once simulated), in frame order. */
1749
+ get collisions() {
1750
+ this.ensureSimulated();
1751
+ return this.allCollisions;
1752
+ }
1753
+ /** Loudest impact envelope of any body each frame: camera shake, flashes, hit sounds. */
1754
+ get impact() {
1755
+ return this.worldRecording.signal("impact");
1756
+ }
1757
+ /** Runs the whole simulation now (once) and binds every body's layer per its `output`. */
1758
+ simulate() {
1759
+ if (this.liveMode) throw new Error("Physics: this world is live; it steps as frames render.");
1760
+ this.ensureSimulated();
1761
+ return this;
1762
+ }
1763
+ /** Like {@link simulate}, but writes keyframes for every body whose `output` was left at its default. */
1764
+ bakeKeyframes(options = {}) {
1765
+ if (this.locked) throw new Error("Physics: bakeKeyframes() must come before simulate(), live() or reading any body signal.");
1766
+ this.bakeDefault = options;
1767
+ this.ensureSimulated();
1768
+ return this;
1769
+ }
1770
+ /**
1771
+ * Steps the world as the composition renders instead of all at once: before
1772
+ * each frame draws, the world advances to it, after the composition's
1773
+ * vision clips (`comp.vision`) and any `inputs` have that frame ready. Use
1774
+ * it when bodies follow a performer, so nothing is analysed up front and a
1775
+ * preview starts at once. Frames already simulated are kept, so scrubbing
1776
+ * back costs nothing; jumping ahead simulates the frames in between.
1777
+ * Signals only; `bakeKeyframes()` needs the whole run up front.
1778
+ */
1779
+ live(comp, options = {}) {
1780
+ if (this.locked) throw new Error("Physics: live() must come before simulate() or reading any body signal.");
1781
+ this.locked = true;
1782
+ this.liveMode = true;
1783
+ const prepare = async (frame) => {
1784
+ await comp.prepareVision?.(frame);
1785
+ for (const input of options.inputs ?? []) await input.ready(frame);
1786
+ };
1787
+ this.prepareInputs = prepare;
1788
+ for (const body of this.bodies) this.bind(body);
1789
+ comp.onPrepareFrame((ctx) => this.advanceTo(ctx.frame));
1790
+ return this;
1791
+ }
1792
+ /**
1793
+ * Live worlds: simulates up to composition frame `frame` (no-op when it
1794
+ * already has). Calls queue, so frames are stepped once, in order.
1795
+ */
1796
+ advanceTo(frame) {
1797
+ this.chain = this.chain.then(async () => {
1798
+ const target = Math.min(this.frames - 1, Math.round(frame) - this.startFrame);
1799
+ if (!this.stepper) {
1800
+ await this.prepareInputs?.(this.startFrame);
1801
+ this.stepper = this.begin();
1802
+ }
1803
+ const st = this.stepper;
1804
+ while (st.current < target) {
1805
+ const next = st.current + 1;
1806
+ await this.prepareInputs?.(this.startFrame + next);
1807
+ this.stepFrame(st, next);
1808
+ }
1809
+ if (st.current === this.frames - 1 && !st.freed) {
1810
+ st.freed = true;
1811
+ this.sim.free();
1812
+ }
1813
+ });
1814
+ return this.chain;
1815
+ }
1816
+ prepareInputs;
1817
+ bakeDefault;
1818
+ newRecording() {
1819
+ return new Recording(this.startFrame + this.frames, this.fps, () => this.ensureSimulated());
1820
+ }
1821
+ assertOpen() {
1822
+ if (this.locked) throw new Error("Physics: the world has already started; add every body, joint and force before simulate(), live() or reading signals.");
1823
+ }
1824
+ addBody(body) {
1825
+ this.assertOpen();
1826
+ this.bodies.push(body);
1827
+ return body;
1828
+ }
1829
+ addForce(body, accel) {
1830
+ this.assertOpen();
1831
+ this.forces.push({
1832
+ body,
1833
+ accel
1834
+ });
1835
+ }
1836
+ addField(accel, targets) {
1837
+ this.assertOpen();
1838
+ this.fields.push({
1839
+ accel,
1840
+ ...targets && { targets: new Set(targets) }
1841
+ });
1842
+ }
1843
+ addImpulse(body, frame, dv) {
1844
+ this.assertOpen();
1845
+ this.impulses.push({
1846
+ body,
1847
+ frame: Math.round(frame),
1848
+ dv
1849
+ });
1850
+ }
1851
+ ensureSimulated() {
1852
+ if (this.locked) return;
1853
+ this.locked = true;
1854
+ const st = this.begin();
1855
+ for (let f = 1; f < this.frames; f++) this.stepFrame(st, f);
1856
+ st.freed = true;
1857
+ this.sim.free();
1858
+ for (const body of this.bodies) this.bind(body);
1859
+ }
1860
+ /** Records frame 0 and sets every channel to it, so frames not simulated yet hold the start pose. */
1861
+ begin() {
1862
+ const { startFrame } = this;
1863
+ const bodies = this.bodies;
1864
+ const bySim = /* @__PURE__ */ new Map();
1865
+ for (const b of bodies) bySim.set(b.sim, b);
1866
+ for (const b of bodies) if (b.startFrame > 0) b.sim.setEnabled(false);
1867
+ const kinematicFrom = /* @__PURE__ */ new Map();
1868
+ for (const b of bodies) {
1869
+ b.record(startFrame, -1);
1870
+ b.recording.channel("impact");
1871
+ const t = b.kinematicTarget?.(startFrame);
1872
+ if (t) kinematicFrom.set(b, t);
1873
+ }
1874
+ this.worldRecording.channel("impact");
1875
+ for (const rec of [...bodies.map((b) => b.recording), this.worldRecording]) for (const arr of rec.channels.values()) arr.fill(arr[startFrame]);
1876
+ return {
1877
+ current: 0,
1878
+ freed: false,
1879
+ bySim,
1880
+ kinematicFrom,
1881
+ level: new Map(bodies.map((b) => [b, 0]))
1882
+ };
1883
+ }
1884
+ stepFrame(st, f) {
1885
+ const { fps, startFrame, substeps } = this;
1886
+ const dt = 1 / (fps * substeps);
1887
+ const bodies = this.bodies;
1888
+ const frame = startFrame + f;
1889
+ const dims = this.gravity.length;
1890
+ const prevVel = /* @__PURE__ */ new Map();
1891
+ for (const b of bodies) {
1892
+ if (b.startFrame > 0 && f === b.startFrame + 1) b.sim.setEnabled(true);
1893
+ prevVel.set(b, b.sim.velocity());
1894
+ }
1895
+ const isActive = (b) => b.type === "dynamic" && f > b.startFrame;
1896
+ const expected = /* @__PURE__ */ new Map();
1897
+ for (const b of bodies) expected.set(b, this.gravity.map((g) => isActive(b) ? g * b.gravityScale / fps : 0));
1898
+ for (const imp of this.impulses) {
1899
+ if (imp.frame !== f) continue;
1900
+ const body = imp.body;
1901
+ if (!isActive(body)) continue;
1902
+ const m = body.sim.mass();
1903
+ body.sim.applyImpulse(imp.dv.map((v) => v * m));
1904
+ const e = expected.get(body);
1905
+ for (let i = 0; i < dims; i++) e[i] += imp.dv[i];
1906
+ }
1907
+ const frameForces = this.forces.filter((fe) => isActive(fe.body)).map((fe) => {
1908
+ const body = fe.body;
1909
+ const a = fe.accel(frame);
1910
+ const e = expected.get(body);
1911
+ for (let i = 0; i < dims; i++) e[i] += a[i] / fps;
1912
+ return {
1913
+ body,
1914
+ a
1915
+ };
1916
+ });
1917
+ const kinematicTo = /* @__PURE__ */ new Map();
1918
+ for (const b of bodies) {
1919
+ const t = b.kinematicTarget?.(frame);
1920
+ if (t) kinematicTo.set(b, t);
1921
+ }
1922
+ const started = /* @__PURE__ */ new Set();
1923
+ const pairs = [];
1924
+ for (let s = 1; s <= substeps; s++) {
1925
+ for (const { body, a } of frameForces) {
1926
+ const m = body.sim.mass();
1927
+ body.sim.applyImpulse(a.map((v) => v * m * dt));
1928
+ }
1929
+ for (const field of this.fields) for (const b of bodies) {
1930
+ if (!isActive(b) || field.targets && !field.targets.has(b)) continue;
1931
+ const a = field.accel(b, frame);
1932
+ if (!a) continue;
1933
+ const m = b.sim.mass();
1934
+ b.sim.applyImpulse(a.map((v) => v * m * dt));
1935
+ const e = expected.get(b);
1936
+ for (let i = 0; i < dims; i++) e[i] += a[i] * dt;
1937
+ }
1938
+ for (const [b, to] of kinematicTo) {
1939
+ const from = st.kinematicFrom.get(b) ?? to;
1940
+ const k = s / substeps;
1941
+ b.sim.setKinematicTarget(lerpVec(from.position, to.position, k), this.lerpRotation(from.rotation, to.rotation, k));
1942
+ }
1943
+ this.sim.step(dt);
1944
+ for (const [sa, sb] of this.sim.drainCollisionStarts()) {
1945
+ const a = st.bySim.get(sa);
1946
+ const b = st.bySim.get(sb);
1947
+ if (!a || !b) continue;
1948
+ const key = `${bodies.indexOf(a)}:${bodies.indexOf(b)}`;
1949
+ if (started.has(key)) continue;
1950
+ started.add(key);
1951
+ pairs.push([a, b]);
1952
+ }
1953
+ }
1954
+ st.kinematicFrom = kinematicTo;
1955
+ for (const b of bodies) b.record(frame, frame - 1);
1956
+ const raw = /* @__PURE__ */ new Map();
1957
+ if (pairs.length > 0) {
1958
+ const ppm = this.pixelsPerMeter;
1959
+ const hit = (b) => {
1960
+ if (b.type !== "dynamic") return 0;
1961
+ const v = b.sim.velocity();
1962
+ const v0 = prevVel.get(b);
1963
+ const e = expected.get(b);
1964
+ let sq = 0;
1965
+ for (let i = 0; i < dims; i++) {
1966
+ const d = v[i] - (v0[i] + e[i]);
1967
+ sq += d * d;
1968
+ }
1969
+ return Math.sqrt(sq) * ppm;
1970
+ };
1971
+ for (const [a, b] of pairs) {
1972
+ const speed = Math.max(hit(a), hit(b));
1973
+ for (const [self, other] of [[a, b], [b, a]]) {
1974
+ raw.set(self, Math.max(raw.get(self) ?? 0, speed));
1975
+ const c = {
1976
+ frame,
1977
+ with: other,
1978
+ speed
1979
+ };
1980
+ self.collisions.push(c);
1981
+ if (self === a) this.allCollisions.push({
1982
+ ...c,
1983
+ body: a
1984
+ });
1985
+ }
1986
+ }
1987
+ }
1988
+ const decay = Math.exp(-1 / this.impactDecay);
1989
+ let loudest = 0;
1990
+ for (const b of bodies) {
1991
+ const level = Math.max((raw.get(b) ?? 0) / this.impactReference, (st.level.get(b) ?? 0) * decay);
1992
+ st.level.set(b, level);
1993
+ b.recording.channel("impact")[frame] = level;
1994
+ if (level > loudest) loudest = level;
1995
+ }
1996
+ this.worldRecording.channel("impact")[frame] = loudest;
1997
+ st.current = f;
1998
+ }
1999
+ bind(body) {
2000
+ const layer = body.layer;
2001
+ const output = body.output ?? (this.bakeDefault ? "keyframes" : "signals");
2002
+ if (typeof layer?.animate !== "function" || output === "none") return;
2003
+ if (body.type === "fixed") return;
2004
+ const channels = body.boundChannels();
2005
+ if (output === "keyframes" && this.liveMode) throw new Error("Physics: live worlds bind signals; drop `output: \"keyframes\"` or use simulate().");
2006
+ if (output === "signals") {
2007
+ const anim$1 = LayerAnimation.create();
2008
+ for (const [prop, channel] of channels) anim$1.signal(prop, body.recording.signal(channel));
2009
+ layer.animate(anim$1);
2010
+ return;
2011
+ }
2012
+ const tolerance = this.bakeDefault?.tolerance ?? .25;
2013
+ const anim = LayerAnimation.create();
2014
+ for (const [prop, channel] of channels) {
2015
+ const local = body.recording.channel(channel).subarray(this.startFrame);
2016
+ const scale = CHANNEL_TOLERANCE_SCALE[prop] ?? 1;
2017
+ anim.keys(prop, simplifyKeys(local, tolerance * scale));
2018
+ }
2019
+ layer.animate(anim);
2020
+ }
2021
+ };
2022
+ function lerpVec(a, b, t) {
2023
+ return a.map((v, i) => v + (b[i] - v) * t);
2024
+ }
2025
+
2026
+ //#endregion
2027
+ //#region src/particles.ts
2028
+ const range = (r, fallback) => r === void 0 ? fallback : typeof r === "number" ? [r, r] : r;
2029
+ /**
2030
+ * A GPU particle system: tens of thousands of particles simulated in a
2031
+ * compute shader and drawn in one call. Used through `Layer.particles()`.
2032
+ * It steps as the composition renders (snapshots make scrubbing back
2033
+ * cheap), and its drivers are read every frame.
2034
+ */
2035
+ var Particles = class extends Effect$1 {
2036
+ op = "Particles";
2037
+ particleStatic;
2038
+ particleState;
2039
+ options;
2040
+ constructor(options) {
2041
+ super({});
2042
+ this.options = options;
2043
+ const e = options.emitter ?? {};
2044
+ const staticPos = (d) => typeof d === "number" ? d : void 0;
2045
+ const width = options.width;
2046
+ const height = options.height;
2047
+ const colors = (Array.isArray(options.color) ? options.color : [options.color ?? "#ffffff"]).map((c) => {
2048
+ const p = parseColor(c);
2049
+ return [
2050
+ p.r,
2051
+ p.g,
2052
+ p.b,
2053
+ p.a
2054
+ ];
2055
+ });
2056
+ this.particleStatic = {
2057
+ max: Math.max(1, Math.round(options.max ?? 2e4)),
2058
+ seed: Math.round(options.seed ?? 1) >>> 0,
2059
+ layer: {
2060
+ x: options.x ?? 0,
2061
+ y: options.y ?? 0,
2062
+ width,
2063
+ height
2064
+ },
2065
+ emitter: {
2066
+ shape: e.shape ?? "rect",
2067
+ x: staticPos(e.x) ?? (e.shape === "circle" || e.shape === "ring" || e.shape === "point" ? width / 2 : 0),
2068
+ y: staticPos(e.y) ?? (e.shape === "circle" || e.shape === "ring" || e.shape === "point" ? height / 2 : 0),
2069
+ width: e.width ?? width,
2070
+ height: e.height ?? (e.shape === "line" ? 0 : height),
2071
+ radius: e.radius ?? Math.min(width, height) / 4,
2072
+ radial: e.radial ?? false
2073
+ },
2074
+ lifetime: range(options.lifetime, [2, 4]),
2075
+ speed: range(options.speed, [40, 160]),
2076
+ direction: options.direction ?? -90,
2077
+ spread: options.spread ?? 360,
2078
+ bounds: options.bounds ?? "none",
2079
+ floor: options.floor ?? null,
2080
+ bounce: options.bounce ?? .3,
2081
+ size: range(options.size, [6, 0]),
2082
+ sizeJitter: options.sizeJitter ?? .5,
2083
+ fade: options.fade ?? [.1, .3],
2084
+ shape: options.shape ?? "circle",
2085
+ stretch: options.stretch ?? .04,
2086
+ blend: options.blend ?? "normal",
2087
+ colors: colors.slice(0, 8),
2088
+ colorBySpeed: options.colorBySpeed ?? null,
2089
+ opacity: options.opacity ?? 1,
2090
+ substeps: options.substeps ?? 2,
2091
+ prewarm: options.prewarm ?? 0
2092
+ };
2093
+ }
2094
+ particleFrame(frame, fps) {
2095
+ const o = this.options;
2096
+ const read = (d, fallback) => d === void 0 ? fallback : sampleDriver(d, frame, fps);
2097
+ const layerFrame = frame - (o.startFrame ?? 0);
2098
+ const burst = (o.emitter?.bursts ?? []).filter((b) => Math.round(b.frame) === layerFrame).reduce((n, b) => n + b.count, 0);
2099
+ const g = o.gravity;
2100
+ const gravity = Array.isArray(g) ? [read(g[0], 0), read(g[1], 0)] : [0, read(g, 0)];
2101
+ let push = null;
2102
+ if (o.push) push = {
2103
+ strength: read(o.push.strength, 6e3),
2104
+ sweep: read(o.push.sweep, 6e4),
2105
+ mask: o.push.person.silhouetteGrid(frame),
2106
+ previous: o.push.person.silhouetteGrid(Math.max(0, frame - 1))
2107
+ };
2108
+ const ex = o.emitter?.x;
2109
+ const ey = o.emitter?.y;
2110
+ const moving = ex !== void 0 && typeof ex !== "number" || ey !== void 0 && typeof ey !== "number";
2111
+ const at = (f) => ({
2112
+ x: ex === void 0 ? this.particleStatic.emitter.x : sampleDriver(ex, f, fps),
2113
+ y: ey === void 0 ? this.particleStatic.emitter.y : sampleDriver(ey, f, fps)
2114
+ });
2115
+ let emitter;
2116
+ if (moving) {
2117
+ const now = at(frame);
2118
+ const before = at(Math.max(0, frame - 1));
2119
+ emitter = {
2120
+ x: now.x,
2121
+ y: now.y,
2122
+ previousX: before.x,
2123
+ previousY: before.y
2124
+ };
2125
+ }
2126
+ return {
2127
+ ...emitter && { emitter },
2128
+ rate: read(o.emitter?.rate, 1e3),
2129
+ burst,
2130
+ gravity,
2131
+ drag: read(o.drag, .4),
2132
+ noise: {
2133
+ strength: read(o.noise?.strength, 0),
2134
+ scale: o.noise?.scale ?? 300,
2135
+ speed: o.noise?.speed ?? .3
2136
+ },
2137
+ attractors: (o.attractors ?? []).map((a) => ({
2138
+ x: read(a.x, 0),
2139
+ y: read(a.y, 0),
2140
+ strength: read(a.strength, 0),
2141
+ radius: a.radius ?? 200
2142
+ })),
2143
+ push
2144
+ };
2145
+ }
2146
+ };
2147
+
986
2148
  //#endregion
987
2149
  //#region src/shapes3d.ts
988
2150
  const MATERIAL_KEYS = [
@@ -1954,25 +3116,1755 @@ const Lighting = {
1954
3116
  };
1955
3117
 
1956
3118
  //#endregion
1957
- //#region src/index.ts
1958
- function decorateTrackSignals(track, source) {
1959
- if (!track) return track;
1960
- if (source && !track.source) Object.defineProperty(track, "source", {
1961
- value: source,
1962
- enumerable: true,
1963
- writable: true,
1964
- configurable: true
1965
- });
1966
- if (typeof track.section !== "function") Object.defineProperty(track, "section", {
1967
- value: (sourceOrOptions, options) => {
1968
- if (typeof sourceOrOptions === "object" && sourceOrOptions !== null && !("kind" in sourceOrOptions) && !("inputHandleId" in sourceOrOptions) && !("src" in sourceOrOptions)) {
1969
- const resolvedSource$1 = sourceOrOptions.source ?? track.source ?? source;
1970
- return Layer.section(resolvedSource$1, track, sourceOrOptions);
3119
+ //#region src/physics/backend.ts
3120
+ const RAPIER_2D = "@dimforge/rapier2d-deterministic-compat";
3121
+ const RAPIER_3D = "@dimforge/rapier3d-deterministic-compat";
3122
+ async function loadRapier(specifier, load) {
3123
+ let mod;
3124
+ try {
3125
+ mod = await load();
3126
+ } catch (error) {
3127
+ throw new Error(`Physics needs the optional dependency "${specifier}". Install it with \`npm i ${specifier}\`.`, { cause: error });
3128
+ }
3129
+ const rapier = mod.default ?? mod;
3130
+ await rapier.init();
3131
+ return rapier;
3132
+ }
3133
+ let rapier2d;
3134
+ let rapier3d;
3135
+ /** Loads and initializes Rapier once per process; 2D and 3D are separate modules. */
3136
+ async function rapierBackend(dims) {
3137
+ if (dims === 2) {
3138
+ rapier2d ??= loadRapier(RAPIER_2D, () => import("@dimforge/rapier2d-deterministic-compat"));
3139
+ const R$1 = await rapier2d;
3140
+ return {
3141
+ createWorld2D: (gravity) => new RapierWorld2D(R$1, gravity),
3142
+ createWorld3D: () => {
3143
+ throw new Error("This backend was loaded for 2D.");
1971
3144
  }
1972
- const resolvedSource = sourceOrOptions ?? track.source ?? source;
1973
- return Layer.section(resolvedSource, track, options);
3145
+ };
3146
+ }
3147
+ rapier3d ??= loadRapier(RAPIER_3D, () => import("@dimforge/rapier3d-deterministic-compat"));
3148
+ const R = await rapier3d;
3149
+ return {
3150
+ createWorld2D: () => {
3151
+ throw new Error("This backend was loaded for 3D.");
1974
3152
  },
1975
- enumerable: false,
3153
+ createWorld3D: (gravity) => new RapierWorld3D(R, gravity)
3154
+ };
3155
+ }
3156
+ var RapierWorld2D = class {
3157
+ world;
3158
+ events;
3159
+ byCollider = /* @__PURE__ */ new Map();
3160
+ started = [];
3161
+ constructor(R, gravity) {
3162
+ this.R = R;
3163
+ this.world = new R.World({
3164
+ x: gravity[0],
3165
+ y: gravity[1]
3166
+ });
3167
+ this.events = new R.EventQueue(true);
3168
+ }
3169
+ addBody(spec$1) {
3170
+ const R = this.R;
3171
+ const desc = bodyDesc(R, spec$1.type).setTranslation(spec$1.position[0], spec$1.position[1]).setRotation(spec$1.angle).setLinvel(spec$1.velocity[0], spec$1.velocity[1]).setAngvel(spec$1.angularVelocity).setLinearDamping(spec$1.linearDamping).setAngularDamping(spec$1.angularDamping).setGravityScale(spec$1.gravityScale).setCcdEnabled(spec$1.ccd).setEnabled(spec$1.enabled);
3172
+ if (spec$1.lockRotation) desc.lockRotations();
3173
+ const body = this.world.createRigidBody(desc);
3174
+ const collider = this.world.createCollider(shapeDesc2D(R, spec$1.shape).setDensity(spec$1.density).setFriction(spec$1.friction).setRestitution(spec$1.restitution).setActiveEvents(R.ActiveEvents.COLLISION_EVENTS).setSensor(spec$1.sensor ?? false), body);
3175
+ const sim = {
3176
+ raw: body,
3177
+ position: () => {
3178
+ const t = body.translation();
3179
+ return [t.x, t.y];
3180
+ },
3181
+ rotation: () => body.rotation(),
3182
+ velocity: () => {
3183
+ const v = body.linvel();
3184
+ return [v.x, v.y];
3185
+ },
3186
+ angularVelocity: () => body.angvel(),
3187
+ sleeping: () => body.isSleeping(),
3188
+ mass: () => body.mass(),
3189
+ setEnabled: (on) => body.setEnabled(on),
3190
+ applyImpulse: ([x, y]) => body.applyImpulse({
3191
+ x,
3192
+ y
3193
+ }, true),
3194
+ setKinematicTarget: ([x, y], angle) => {
3195
+ body.setNextKinematicTranslation({
3196
+ x,
3197
+ y
3198
+ });
3199
+ body.setNextKinematicRotation(angle);
3200
+ }
3201
+ };
3202
+ this.byCollider.set(collider.handle, sim);
3203
+ return sim;
3204
+ }
3205
+ addJoint(a, b, spec$1) {
3206
+ const R = this.R;
3207
+ const a1 = {
3208
+ x: spec$1.anchorA[0],
3209
+ y: spec$1.anchorA[1]
3210
+ };
3211
+ const a2 = {
3212
+ x: spec$1.anchorB[0],
3213
+ y: spec$1.anchorB[1]
3214
+ };
3215
+ let data;
3216
+ switch (spec$1.type) {
3217
+ case "revolute":
3218
+ case "spherical":
3219
+ data = R.JointData.revolute(a1, a2);
3220
+ break;
3221
+ case "fixed":
3222
+ data = R.JointData.fixed(a1, 0, a2, 0);
3223
+ break;
3224
+ case "rope":
3225
+ data = R.JointData.rope(spec$1.length, a1, a2);
3226
+ break;
3227
+ case "spring":
3228
+ data = R.JointData.spring(spec$1.restLength, spec$1.stiffness, spec$1.damping, a1, a2);
3229
+ break;
3230
+ }
3231
+ this.world.createImpulseJoint(data, rawBody(a), rawBody(b), true).setContactsEnabled(false);
3232
+ }
3233
+ step(dt) {
3234
+ this.world.timestep = dt;
3235
+ this.world.step(this.events);
3236
+ this.events.drainCollisionEvents((h1, h2, started) => {
3237
+ if (!started) return;
3238
+ const a = this.byCollider.get(h1);
3239
+ const b = this.byCollider.get(h2);
3240
+ if (a && b) this.started.push([a, b]);
3241
+ });
3242
+ }
3243
+ drainCollisionStarts() {
3244
+ return this.started.splice(0);
3245
+ }
3246
+ free() {
3247
+ this.events.free();
3248
+ this.world.free();
3249
+ }
3250
+ };
3251
+ var RapierWorld3D = class {
3252
+ world;
3253
+ events;
3254
+ byCollider = /* @__PURE__ */ new Map();
3255
+ started = [];
3256
+ constructor(R, gravity) {
3257
+ this.R = R;
3258
+ this.world = new R.World({
3259
+ x: gravity[0],
3260
+ y: gravity[1],
3261
+ z: gravity[2]
3262
+ });
3263
+ this.events = new R.EventQueue(true);
3264
+ }
3265
+ addBody(spec$1) {
3266
+ const R = this.R;
3267
+ const [qx, qy, qz, qw] = spec$1.rotation;
3268
+ const desc = bodyDesc(R, spec$1.type).setTranslation(spec$1.position[0], spec$1.position[1], spec$1.position[2]).setRotation({
3269
+ x: qx,
3270
+ y: qy,
3271
+ z: qz,
3272
+ w: qw
3273
+ }).setLinvel(spec$1.velocity[0], spec$1.velocity[1], spec$1.velocity[2]).setAngvel(vec3(spec$1.lockRotation ? [
3274
+ 0,
3275
+ 0,
3276
+ 0
3277
+ ] : spec$1.angularVelocity.map((w, i) => spec$1.enabledRotations && !spec$1.enabledRotations[i] ? 0 : w))).setLinearDamping(spec$1.linearDamping).setAngularDamping(spec$1.angularDamping).setGravityScale(spec$1.gravityScale).setCcdEnabled(spec$1.ccd).setEnabled(spec$1.enabled);
3278
+ if (spec$1.lockRotation) desc.lockRotations();
3279
+ else if (spec$1.enabledRotations) desc.enabledRotations(...spec$1.enabledRotations);
3280
+ const body = this.world.createRigidBody(desc);
3281
+ const shape = shapeDesc3D(R, spec$1.shape);
3282
+ const collider = this.world.createCollider(shape.setDensity(spec$1.density).setFriction(spec$1.friction).setRestitution(spec$1.restitution).setActiveEvents(R.ActiveEvents.COLLISION_EVENTS).setSensor(spec$1.sensor ?? false), body);
3283
+ const sim = {
3284
+ raw: body,
3285
+ position: () => {
3286
+ const t = body.translation();
3287
+ return [
3288
+ t.x,
3289
+ t.y,
3290
+ t.z
3291
+ ];
3292
+ },
3293
+ rotation: () => {
3294
+ const q = body.rotation();
3295
+ return [
3296
+ q.x,
3297
+ q.y,
3298
+ q.z,
3299
+ q.w
3300
+ ];
3301
+ },
3302
+ velocity: () => {
3303
+ const v = body.linvel();
3304
+ return [
3305
+ v.x,
3306
+ v.y,
3307
+ v.z
3308
+ ];
3309
+ },
3310
+ angularVelocity: () => {
3311
+ const w = body.angvel();
3312
+ return [
3313
+ w.x,
3314
+ w.y,
3315
+ w.z
3316
+ ];
3317
+ },
3318
+ sleeping: () => body.isSleeping(),
3319
+ mass: () => body.mass(),
3320
+ setEnabled: (on) => body.setEnabled(on),
3321
+ applyImpulse: (v) => body.applyImpulse(vec3(v), true),
3322
+ setKinematicTarget: (p, [x, y, z, w]) => {
3323
+ body.setNextKinematicTranslation(vec3(p));
3324
+ body.setNextKinematicRotation({
3325
+ x,
3326
+ y,
3327
+ z,
3328
+ w
3329
+ });
3330
+ }
3331
+ };
3332
+ this.byCollider.set(collider.handle, sim);
3333
+ return sim;
3334
+ }
3335
+ addJoint(a, b, spec$1) {
3336
+ const R = this.R;
3337
+ const a1 = vec3(spec$1.anchorA);
3338
+ const a2 = vec3(spec$1.anchorB);
3339
+ let data;
3340
+ switch (spec$1.type) {
3341
+ case "revolute":
3342
+ data = R.JointData.revolute(a1, a2, vec3(spec$1.axis ?? [
3343
+ 0,
3344
+ 0,
3345
+ 1
3346
+ ]));
3347
+ break;
3348
+ case "spherical":
3349
+ data = R.JointData.spherical(a1, a2);
3350
+ break;
3351
+ case "fixed": {
3352
+ const identity = {
3353
+ x: 0,
3354
+ y: 0,
3355
+ z: 0,
3356
+ w: 1
3357
+ };
3358
+ data = R.JointData.fixed(a1, identity, a2, identity);
3359
+ break;
3360
+ }
3361
+ case "rope":
3362
+ data = R.JointData.rope(spec$1.length, a1, a2);
3363
+ break;
3364
+ case "spring":
3365
+ data = R.JointData.spring(spec$1.restLength, spec$1.stiffness, spec$1.damping, a1, a2);
3366
+ break;
3367
+ }
3368
+ this.world.createImpulseJoint(data, rawBody(a), rawBody(b), true).setContactsEnabled(false);
3369
+ }
3370
+ step(dt) {
3371
+ this.world.timestep = dt;
3372
+ this.world.step(this.events);
3373
+ this.events.drainCollisionEvents((h1, h2, started) => {
3374
+ if (!started) return;
3375
+ const a = this.byCollider.get(h1);
3376
+ const b = this.byCollider.get(h2);
3377
+ if (a && b) this.started.push([a, b]);
3378
+ });
3379
+ }
3380
+ drainCollisionStarts() {
3381
+ return this.started.splice(0);
3382
+ }
3383
+ free() {
3384
+ this.events.free();
3385
+ this.world.free();
3386
+ }
3387
+ };
3388
+ function vec3([x, y, z]) {
3389
+ return {
3390
+ x,
3391
+ y,
3392
+ z
3393
+ };
3394
+ }
3395
+ function rawBody(body) {
3396
+ return body.raw;
3397
+ }
3398
+ function bodyDesc(R, type) {
3399
+ const D = R.RigidBodyDesc;
3400
+ return type === "fixed" ? D.fixed() : type === "kinematic" ? D.kinematicPositionBased() : D.dynamic();
3401
+ }
3402
+ function shapeDesc2D(R, shape) {
3403
+ switch (shape.kind) {
3404
+ case "ball": return R.ColliderDesc.ball(shape.radius);
3405
+ case "box": {
3406
+ const r = Math.min(shape.radius ?? 0, shape.hx / 2, shape.hy / 2);
3407
+ return r > 0 ? R.ColliderDesc.roundCuboid(shape.hx - r, shape.hy - r, r) : R.ColliderDesc.cuboid(shape.hx, shape.hy);
3408
+ }
3409
+ case "hull": {
3410
+ const desc = R.ColliderDesc.convexHull(new Float32Array(shape.points));
3411
+ if (!desc) throw new Error("Physics: could not build a convex hull for this shape.");
3412
+ return desc;
3413
+ }
3414
+ }
3415
+ }
3416
+ function shapeDesc3D(R, shape) {
3417
+ switch (shape.kind) {
3418
+ case "ball": return R.ColliderDesc.ball(shape.radius);
3419
+ case "box": {
3420
+ const r = Math.min(shape.radius ?? 0, shape.hx / 2, shape.hy / 2, shape.hz / 2);
3421
+ return r > 0 ? R.ColliderDesc.roundCuboid(shape.hx - r, shape.hy - r, shape.hz - r, r) : R.ColliderDesc.cuboid(shape.hx, shape.hy, shape.hz);
3422
+ }
3423
+ case "cylinder": return R.ColliderDesc.cylinder(shape.halfHeight, shape.radius);
3424
+ case "hull": {
3425
+ const desc = R.ColliderDesc.convexHull(new Float32Array(shape.points));
3426
+ if (!desc) throw new Error("Physics: could not build a convex hull for this shape.");
3427
+ return desc;
3428
+ }
3429
+ }
3430
+ }
3431
+
3432
+ //#endregion
3433
+ //#region src/physics/world2d.ts
3434
+ /**
3435
+ * A simulated body. Its signals hold one value per composition frame; bind
3436
+ * them to any prop or effect uniform (`.signal("opacity", body.impact)`).
3437
+ * Reading a signal runs the simulation if it has not run yet.
3438
+ */
3439
+ var PhysicsBody2D = class {
3440
+ collisions = [];
3441
+ /** @internal */ recording;
3442
+ /** @internal */ sim;
3443
+ /** @internal */
3444
+ constructor(world, sim, type, layer, frame, options, recording) {
3445
+ this.world = world;
3446
+ this.type = type;
3447
+ this.layer = layer;
3448
+ this.frame = frame;
3449
+ this.options = options;
3450
+ this.sim = sim;
3451
+ this.recording = recording;
3452
+ }
3453
+ get startFrame() {
3454
+ return Math.max(0, Math.round(this.options.startFrame ?? 0));
3455
+ }
3456
+ get gravityScale() {
3457
+ return this.options.gravityScale ?? 1;
3458
+ }
3459
+ get output() {
3460
+ return this.options.output;
3461
+ }
3462
+ /** The layer's `x` (top-left) every frame. */
3463
+ get x() {
3464
+ return this.recording.signal("x");
3465
+ }
3466
+ /** The layer's `y` (top-left) every frame. */
3467
+ get y() {
3468
+ return this.recording.signal("y");
3469
+ }
3470
+ /** Degrees, clockwise, continuous (no jump at 360). */
3471
+ get rotation() {
3472
+ return this.recording.signal("rotation");
3473
+ }
3474
+ /** Body center, px. */
3475
+ get centerX() {
3476
+ return this.recording.signal("centerX");
3477
+ }
3478
+ get centerY() {
3479
+ return this.recording.signal("centerY");
3480
+ }
3481
+ /** px/s. */
3482
+ get vx() {
3483
+ return this.recording.signal("vx");
3484
+ }
3485
+ get vy() {
3486
+ return this.recording.signal("vy");
3487
+ }
3488
+ /** px/s. */
3489
+ get speed() {
3490
+ return this.recording.signal("speed");
3491
+ }
3492
+ /** Degrees per second. */
3493
+ get angularVelocity() {
3494
+ return this.recording.signal("angularVelocity");
3495
+ }
3496
+ /**
3497
+ * Hit envelope: jumps on each new contact (1 ≈ a 1500 px/s velocity
3498
+ * change, see `impactReference`) and decays over `impactDecay` frames.
3499
+ */
3500
+ get impact() {
3501
+ return this.recording.signal("impact");
3502
+ }
3503
+ /** 1 while the body is at rest, else 0. */
3504
+ get sleeping() {
3505
+ return this.recording.signal("sleeping");
3506
+ }
3507
+ /** @internal */
3508
+ kinematicTarget(frame) {
3509
+ const follow = this.options.follow;
3510
+ if (this.type !== "kinematic" || !follow) return void 0;
3511
+ const f = this.frame;
3512
+ const fps = this.world.fps;
3513
+ const x = follow.x === void 0 ? void 0 : sampleDriver(follow.x, frame, fps);
3514
+ const y = follow.y === void 0 ? void 0 : sampleDriver(follow.y, frame, fps);
3515
+ const rotation = follow.rotation === void 0 ? f.rotation : sampleDriver(follow.rotation, frame, fps);
3516
+ const start = this.initialLayerXY();
3517
+ const center = layerToCenter(x ?? start[0], y ?? start[1], rotation, f);
3518
+ const ppm = this.world.pixelsPerMeter;
3519
+ return {
3520
+ position: [center[0] / ppm, center[1] / ppm],
3521
+ rotation: rotation * Math.PI / 180
3522
+ };
3523
+ }
3524
+ initialLayerXY() {
3525
+ const l = this.layer;
3526
+ return [Number(l?.x ?? 0), Number(l?.y ?? 0)];
3527
+ }
3528
+ /** @internal */
3529
+ record(index, previous) {
3530
+ const ppm = this.world.pixelsPerMeter;
3531
+ const [mx, my] = this.sim.position();
3532
+ const cx = mx * ppm;
3533
+ const cy = my * ppm;
3534
+ const rec = this.recording;
3535
+ const rotation = rec.channel("rotation");
3536
+ const deg = this.sim.rotation() * 180 / Math.PI;
3537
+ rotation[index] = previous < 0 ? unwrapDegrees(this.frame.rotation, deg) : unwrapDegrees(rotation[previous], deg);
3538
+ const [x, y] = centerToLayer(cx, cy, rotation[index], this.frame);
3539
+ rec.channel("x")[index] = x;
3540
+ rec.channel("y")[index] = y;
3541
+ rec.channel("centerX")[index] = cx;
3542
+ rec.channel("centerY")[index] = cy;
3543
+ const [vx, vy] = this.sim.velocity();
3544
+ rec.channel("vx")[index] = vx * ppm;
3545
+ rec.channel("vy")[index] = vy * ppm;
3546
+ rec.channel("speed")[index] = Math.hypot(vx, vy) * ppm;
3547
+ rec.channel("angularVelocity")[index] = this.sim.angularVelocity() * 180 / Math.PI;
3548
+ rec.channel("sleeping")[index] = this.sim.sleeping() ? 1 : 0;
3549
+ }
3550
+ /** @internal */
3551
+ boundChannels() {
3552
+ const out = [["x", "x"], ["y", "y"]];
3553
+ if (!this.options.lockRotation) out.push(["rotation", "rotation"]);
3554
+ return out;
3555
+ }
3556
+ /** @internal World-space point (px) → this body's local frame (meters), at the start pose. */
3557
+ localAnchor(point) {
3558
+ if (!point) return [0, 0];
3559
+ const ppm = this.world.pixelsPerMeter;
3560
+ const [px, py] = this.sim.position();
3561
+ const a = -this.sim.rotation();
3562
+ const dx = point[0] / ppm - px;
3563
+ const dy = point[1] / ppm - py;
3564
+ return [dx * Math.cos(a) - dy * Math.sin(a), dx * Math.sin(a) + dy * Math.cos(a)];
3565
+ }
3566
+ /** @internal Start-pose center in px. */
3567
+ center() {
3568
+ const ppm = this.world.pixelsPerMeter;
3569
+ const [x, y] = this.sim.position();
3570
+ return [x * ppm, y * ppm];
3571
+ }
3572
+ };
3573
+ /**
3574
+ * A deterministic 2D rigid-body world (Rapier) in layer pixels. Build it,
3575
+ * add bodies from layers, then `simulate()`: each body's layer is bound to
3576
+ * its simulated `x` / `y` / `rotation`, and every body exposes signals
3577
+ * (`impact`, `speed`, …) for driving anything else. The simulation runs
3578
+ * once while the composition is built, so frames render in any order and
3579
+ * identically on every machine.
3580
+ */
3581
+ var PhysicsWorld2D = class extends WorldCore {
3582
+ /** @internal */
3583
+ constructor(backend, options) {
3584
+ const ppm = options.pixelsPerMeter ?? 100;
3585
+ const g = options.gravity ?? 2400;
3586
+ const gravity = typeof g === "number" ? [0, g / ppm] : [g[0] / ppm, g[1] / ppm];
3587
+ const sim = backend.createWorld2D(gravity);
3588
+ super(sim, gravity, options);
3589
+ }
3590
+ /**
3591
+ * Adds a body for a layer (absolutely positioned: `x`, `y`, and a size)
3592
+ * or for a plain rectangle. The layer's current pose is the start pose.
3593
+ */
3594
+ body(target, options = {}) {
3595
+ this.assertOpen();
3596
+ const layer = typeof target.kind === "string" ? target : void 0;
3597
+ const geom = layerGeometry(target, options);
3598
+ const ppm = this.pixelsPerMeter;
3599
+ const type = options.type ?? "dynamic";
3600
+ const [cx, cy] = layerToCenter(geom.x, geom.y, geom.rotation, geom);
3601
+ const v = options.velocity ?? [0, 0];
3602
+ const spec$1 = {
3603
+ type,
3604
+ position: [cx / ppm, cy / ppm],
3605
+ angle: geom.rotation * Math.PI / 180,
3606
+ velocity: [v[0] / ppm, v[1] / ppm],
3607
+ angularVelocity: (options.angularVelocity ?? 0) * Math.PI / 180,
3608
+ linearDamping: options.linearDamping ?? 0,
3609
+ angularDamping: options.angularDamping ?? 0,
3610
+ gravityScale: options.gravityScale ?? 1,
3611
+ lockRotation: options.lockRotation ?? false,
3612
+ ccd: options.ccd ?? false,
3613
+ enabled: true,
3614
+ sensor: options.sensor ?? false,
3615
+ density: options.density ?? 1,
3616
+ friction: options.friction ?? .6,
3617
+ restitution: options.restitution ?? .3,
3618
+ shape: scaleShape$1(geom.shape, 1 / ppm)
3619
+ };
3620
+ const simBody = this.sim.addBody(spec$1);
3621
+ const body = new PhysicsBody2D(this, simBody, type, layer, geom, options, this.newRecording());
3622
+ return this.addBody(body);
3623
+ }
3624
+ /** A fixed, very wide floor whose top edge sits at `y`. */
3625
+ ground(options) {
3626
+ const t = 2e3;
3627
+ const w = 1e6;
3628
+ return this.body({
3629
+ x: -w / 2,
3630
+ y: options.y,
3631
+ width: w,
3632
+ height: t
3633
+ }, {
3634
+ type: "fixed",
3635
+ friction: options.friction,
3636
+ restitution: options.restitution ?? .2
3637
+ });
3638
+ }
3639
+ /** Fixed floor, left and right walls (and optionally a ceiling) around a box, e.g. the canvas. */
3640
+ walls(options) {
3641
+ const { width: W, height: H } = options;
3642
+ const x = options.x ?? 0;
3643
+ const y = options.y ?? 0;
3644
+ const t = options.thickness ?? 400;
3645
+ const mat = {
3646
+ type: "fixed",
3647
+ friction: options.friction,
3648
+ restitution: options.restitution ?? .2
3649
+ };
3650
+ const tall = H * 4 + t;
3651
+ const result = {
3652
+ floor: this.body({
3653
+ x: x - t,
3654
+ y: y + H,
3655
+ width: W + 2 * t,
3656
+ height: t
3657
+ }, mat),
3658
+ left: this.body({
3659
+ x: x - t,
3660
+ y: y + H - tall,
3661
+ width: t,
3662
+ height: tall
3663
+ }, mat),
3664
+ right: this.body({
3665
+ x: x + W,
3666
+ y: y + H - tall,
3667
+ width: t,
3668
+ height: tall
3669
+ }, mat),
3670
+ ceiling: void 0
3671
+ };
3672
+ if (options.ceiling) result.ceiling = this.body({
3673
+ x: x - t,
3674
+ y: y - t,
3675
+ width: W + 2 * t,
3676
+ height: t
3677
+ }, mat);
3678
+ return result;
3679
+ }
3680
+ /** Pins a body to the world at a point (default its center); it can still swing around it. */
3681
+ pin(body, at) {
3682
+ const point = at ?? body.center();
3683
+ const anchor = this.anchorBody(point);
3684
+ this.joint(body, anchor, {
3685
+ type: "revolute",
3686
+ anchorA: body.localAnchor(point),
3687
+ anchorB: [0, 0]
3688
+ });
3689
+ return this;
3690
+ }
3691
+ /** Joins two bodies at a world point so they swing around it (a hinge). */
3692
+ hinge(a, b, at) {
3693
+ this.joint(a, b, {
3694
+ type: "revolute",
3695
+ anchorA: a.localAnchor(at),
3696
+ anchorB: b.localAnchor(at)
3697
+ });
3698
+ return this;
3699
+ }
3700
+ /** Glues two bodies together rigidly. */
3701
+ weld(a, b) {
3702
+ const at = a.center();
3703
+ this.joint(a, b, {
3704
+ type: "fixed",
3705
+ anchorA: [0, 0],
3706
+ anchorB: b.localAnchor(at)
3707
+ });
3708
+ return this;
3709
+ }
3710
+ /** A damped spring between two bodies, or from a body to a world point. */
3711
+ spring(a, b, options = {}) {
3712
+ const { other, pa, pb } = this.endpoints(a, b, options.anchorA, options.anchorB);
3713
+ const ppm = this.pixelsPerMeter;
3714
+ const length = (options.length ?? Math.hypot(pb[0] - pa[0], pb[1] - pa[1])) / ppm;
3715
+ const mass = effectiveMass(a, other);
3716
+ const w = 2 * Math.PI * (options.frequency ?? 2);
3717
+ this.joint(a, other, {
3718
+ type: "spring",
3719
+ anchorA: a.localAnchor(pa),
3720
+ anchorB: other.localAnchor(pb),
3721
+ restLength: length,
3722
+ stiffness: mass * w * w,
3723
+ damping: 2 * (options.dampingRatio ?? .2) * mass * w
3724
+ });
3725
+ return this;
3726
+ }
3727
+ /** A rope: never longer than `length`, slack when closer. */
3728
+ rope(a, b, options = {}) {
3729
+ const { other, pa, pb } = this.endpoints(a, b, options.anchorA, options.anchorB);
3730
+ const length = options.length ?? Math.hypot(pb[0] - pa[0], pb[1] - pa[1]);
3731
+ this.joint(a, other, {
3732
+ type: "rope",
3733
+ anchorA: a.localAnchor(pa),
3734
+ anchorB: other.localAnchor(pb),
3735
+ length: length / this.pixelsPerMeter
3736
+ });
3737
+ return this;
3738
+ }
3739
+ /** A steady push, px/s² (mass-independent): wind, magnets, audio. Drivers are read every frame. */
3740
+ force(body, accel) {
3741
+ const ppm = this.pixelsPerMeter;
3742
+ this.addForce(body, (frame) => [accel.x === void 0 ? 0 : sampleDriver(accel.x, frame, this.fps) / ppm, accel.y === void 0 ? 0 : sampleDriver(accel.y, frame, this.fps) / ppm]);
3743
+ return this;
3744
+ }
3745
+ /**
3746
+ * A force field: called for every awake dynamic body (or just `bodies`)
3747
+ * each solver step with its center and velocity in px, px/s; returns an
3748
+ * acceleration `[ax, ay]` px/s² (or nothing). Wind, vortices, magnets,
3749
+ * flow fields, a dancer's silhouette pushing particles.
3750
+ */
3751
+ field(accel, options = {}) {
3752
+ const ppm = this.pixelsPerMeter;
3753
+ this.addField((body, frame) => {
3754
+ const [x, y] = body.sim.position();
3755
+ const [vx, vy] = body.sim.velocity();
3756
+ const a = accel({
3757
+ x: x * ppm,
3758
+ y: y * ppm,
3759
+ vx: vx * ppm,
3760
+ vy: vy * ppm,
3761
+ frame,
3762
+ body
3763
+ });
3764
+ return a ? [a[0] / ppm, a[1] / ppm] : null;
3765
+ }, options.bodies);
3766
+ return this;
3767
+ }
3768
+ /** An instant kick at a simulation frame: adds `[vx, vy]` px/s to the body's velocity. */
3769
+ impulse(body, frame, velocity) {
3770
+ const ppm = this.pixelsPerMeter;
3771
+ this.addImpulse(body, frame, [velocity[0] / ppm, velocity[1] / ppm]);
3772
+ return this;
3773
+ }
3774
+ lerpRotation(a, b, t) {
3775
+ return a + (b - a) * t;
3776
+ }
3777
+ joint(a, b, spec$1) {
3778
+ this.assertOpen();
3779
+ this.sim.addJoint(a.sim, b.sim, spec$1);
3780
+ }
3781
+ anchorBody(point) {
3782
+ return this.body({
3783
+ x: point[0] - .5,
3784
+ y: point[1] - .5,
3785
+ width: 1,
3786
+ height: 1
3787
+ }, {
3788
+ type: "fixed",
3789
+ output: "none",
3790
+ sensor: true
3791
+ });
3792
+ }
3793
+ endpoints(a, b, anchorA, anchorB) {
3794
+ const pa = anchorA ?? a.center();
3795
+ if (Array.isArray(b)) {
3796
+ const pb = anchorB ?? b;
3797
+ return {
3798
+ other: this.anchorBody(pb),
3799
+ pa,
3800
+ pb
3801
+ };
3802
+ }
3803
+ return {
3804
+ other: b,
3805
+ pa,
3806
+ pb: anchorB ?? b.center()
3807
+ };
3808
+ }
3809
+ };
3810
+ function effectiveMass(a, b) {
3811
+ const ma = a.type === "dynamic" ? a.sim.mass() : 0;
3812
+ const mb = b.type === "dynamic" ? b.sim.mass() : 0;
3813
+ if (ma > 0 && mb > 0) return ma * mb / (ma + mb);
3814
+ return Math.max(ma, mb, .001);
3815
+ }
3816
+ function num$1(v, fallback) {
3817
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
3818
+ }
3819
+ function layerGeometry(layer, options) {
3820
+ const id = typeof layer.id === "string" ? ` "${layer.id}"` : "";
3821
+ if (typeof layer.x !== "number" || typeof layer.y !== "number") throw new Error(`Physics: layer${id} needs numeric \`x\` and \`y\` (absolute position) to become a body.`);
3822
+ let width = options.size?.[0] ?? (typeof layer.width === "number" ? layer.width : void 0);
3823
+ let height = options.size?.[1] ?? (typeof layer.height === "number" ? layer.height : void 0);
3824
+ if ((width === void 0 || height === void 0) && layer.kind === "text") {
3825
+ const m = FontManager.measure(String(layer.text ?? ""), {
3826
+ fontFamily: String(layer.fontFamily ?? "Inter"),
3827
+ fontSize: num$1(layer.fontSize, 48),
3828
+ fontWeight: layer.fontWeight,
3829
+ letterSpacing: num$1(layer.letterSpacing, 0),
3830
+ lineHeight: typeof layer.lineHeight === "number" ? layer.lineHeight : void 0
3831
+ });
3832
+ width ??= m.width;
3833
+ height ??= m.height;
3834
+ }
3835
+ if (width === void 0 || height === void 0 || width <= 0 || height <= 0) throw new Error(`Physics: layer${id} needs a numeric \`width\` and \`height\` (or the \`size\` option) to become a body.`);
3836
+ const scale = num$1(layer.scale, 1);
3837
+ return {
3838
+ x: layer.x,
3839
+ y: layer.y,
3840
+ width,
3841
+ height,
3842
+ scale,
3843
+ anchorX: num$1(layer.anchorX, .5),
3844
+ anchorY: num$1(layer.anchorY, .5),
3845
+ rotation: num$1(layer.rotation, 0),
3846
+ shape: scaleShape$1(colliderShape(layer, width, height, options.shape ?? "auto"), scale)
3847
+ };
3848
+ }
3849
+ function colliderShape(layer, w, h, mode) {
3850
+ const shapeType = layer.kind === "shape" ? String(layer.shapeType ?? "rect") : "rect";
3851
+ const radius = num$1(layer.borderRadius, num$1(layer.cornerRadius, 0));
3852
+ const box = {
3853
+ kind: "box",
3854
+ hx: w / 2,
3855
+ hy: h / 2,
3856
+ radius
3857
+ };
3858
+ if (mode === "box") return box;
3859
+ if (mode === "circle" || mode === "auto" && shapeType === "circle") return {
3860
+ kind: "ball",
3861
+ radius: Math.min(w, h) / 2
3862
+ };
3863
+ if (mode === "auto" && shapeType === "rect") return box;
3864
+ if (mode === "hull" || mode === "auto") {
3865
+ const points = outlinePoints(layer, shapeType, w, h);
3866
+ return points.length >= 6 ? {
3867
+ kind: "hull",
3868
+ points
3869
+ } : box;
3870
+ }
3871
+ return box;
3872
+ }
3873
+ /** The shape's outline as flat points around the box center, px. */
3874
+ function outlinePoints(layer, shapeType, w, h) {
3875
+ const d = shapeType === "path" ? String(layer.d ?? "") : buildShapeSvgPath({
3876
+ shapeType,
3877
+ width: w,
3878
+ height: h,
3879
+ cornerRadius: num$1(layer.cornerRadius, num$1(layer.borderRadius, 0)),
3880
+ polygonSides: layer.polygonSides,
3881
+ starPoints: layer.starPoints,
3882
+ starInnerRadiusRatio: layer.starInnerRadiusRatio,
3883
+ arrowHeadWidth: layer.arrowHeadWidth,
3884
+ arrowHeadLength: layer.arrowHeadLength,
3885
+ arrowShaftWidth: layer.arrowShaftWidth
3886
+ });
3887
+ const out = [];
3888
+ for (const seg of parseSvgPathToSegments(d)) out.push(seg.p0.x - w / 2, seg.p0.y - h / 2, seg.p1.x - w / 2, seg.p1.y - h / 2);
3889
+ return out;
3890
+ }
3891
+ function scaleShape$1(shape, s) {
3892
+ switch (shape.kind) {
3893
+ case "ball": return {
3894
+ kind: "ball",
3895
+ radius: shape.radius * s
3896
+ };
3897
+ case "box": return {
3898
+ kind: "box",
3899
+ hx: shape.hx * s,
3900
+ hy: shape.hy * s,
3901
+ radius: (shape.radius ?? 0) * s
3902
+ };
3903
+ case "hull": return {
3904
+ kind: "hull",
3905
+ points: shape.points.map((v) => v * s)
3906
+ };
3907
+ }
3908
+ }
3909
+ /**
3910
+ * Layers rotate and scale around their pivot (`anchorX/Y` of the unscaled
3911
+ * box); bodies rotate around their center. These convert between the two.
3912
+ */
3913
+ function pivotOffset(rotationDeg, f) {
3914
+ const a = rotationDeg * Math.PI / 180;
3915
+ const dx = (.5 - f.anchorX) * f.width * f.scale;
3916
+ const dy = (.5 - f.anchorY) * f.height * f.scale;
3917
+ return [dx * Math.cos(a) - dy * Math.sin(a), dx * Math.sin(a) + dy * Math.cos(a)];
3918
+ }
3919
+ function layerToCenter(x, y, rotationDeg, f) {
3920
+ const [ox, oy] = pivotOffset(rotationDeg, f);
3921
+ return [x + f.anchorX * f.width + ox, y + f.anchorY * f.height + oy];
3922
+ }
3923
+ function centerToLayer(cx, cy, rotationDeg, f) {
3924
+ const [ox, oy] = pivotOffset(rotationDeg, f);
3925
+ return [cx - ox - f.anchorX * f.width, cy - oy - f.anchorY * f.height];
3926
+ }
3927
+
3928
+ //#endregion
3929
+ //#region src/physics/world3d.ts
3930
+ const DEG = Math.PI / 180;
3931
+ /** Quaternion of the renderer's Euler order: R = Rz · Ry · Rx (degrees). */
3932
+ function quatFromEuler(rx, ry, rz) {
3933
+ const half = (d) => d * DEG / 2;
3934
+ const qx = [
3935
+ Math.sin(half(rx)),
3936
+ 0,
3937
+ 0,
3938
+ Math.cos(half(rx))
3939
+ ];
3940
+ const qy = [
3941
+ 0,
3942
+ Math.sin(half(ry)),
3943
+ 0,
3944
+ Math.cos(half(ry))
3945
+ ];
3946
+ return quatMul(quatMul([
3947
+ 0,
3948
+ 0,
3949
+ Math.sin(half(rz)),
3950
+ Math.cos(half(rz))
3951
+ ], qy), qx);
3952
+ }
3953
+ function quatMul(a, b) {
3954
+ const [ax, ay, az, aw] = a;
3955
+ const [bx, by, bz, bw] = b;
3956
+ return [
3957
+ aw * bx + ax * bw + ay * bz - az * by,
3958
+ aw * by - ax * bz + ay * bw + az * bx,
3959
+ aw * bz + ax * by - ay * bx + az * bw,
3960
+ aw * bw - ax * bx - ay * by - az * bz
3961
+ ];
3962
+ }
3963
+ /**
3964
+ * Euler angles (degrees, R = Rz · Ry · Rx) for a quaternion, choosing of the
3965
+ * two equivalent solutions the one closest to `previous` and unwrapping each
3966
+ * angle, so rotations stay continuous frame to frame.
3967
+ */
3968
+ function eulerFromQuat(q, previous) {
3969
+ const [x, y, z, w] = q;
3970
+ const r00 = 1 - 2 * (y * y + z * z);
3971
+ const r10 = 2 * (x * y + w * z);
3972
+ const r20 = 2 * (x * z - w * y);
3973
+ const r21 = 2 * (y * z + w * x);
3974
+ const r22 = 1 - 2 * (x * x + y * y);
3975
+ const r01 = 2 * (x * y - w * z);
3976
+ const r11 = 1 - 2 * (x * x + z * z);
3977
+ const sy = Math.max(-1, Math.min(1, -r20));
3978
+ let a;
3979
+ if (Math.abs(sy) > .999999) {
3980
+ const ay = Math.asin(sy);
3981
+ const keepX = previous ? previous[0] * DEG : 0;
3982
+ a = [
3983
+ keepX,
3984
+ ay,
3985
+ Math.atan2(-r01, r11) + (sy > 0 ? keepX : -keepX)
3986
+ ];
3987
+ } else a = [
3988
+ Math.atan2(r21, r22),
3989
+ Math.asin(sy),
3990
+ Math.atan2(r10, r00)
3991
+ ];
3992
+ const first = [
3993
+ a[0] / DEG,
3994
+ a[1] / DEG,
3995
+ a[2] / DEG
3996
+ ];
3997
+ if (!previous) return first;
3998
+ const second = [
3999
+ first[0] + 180,
4000
+ 180 - first[1],
4001
+ first[2] + 180
4002
+ ];
4003
+ const unwrap = (c) => [
4004
+ unwrapDegrees(previous[0], c[0]),
4005
+ unwrapDegrees(previous[1], c[1]),
4006
+ unwrapDegrees(previous[2], c[2])
4007
+ ];
4008
+ const p = unwrap(first);
4009
+ const s = unwrap(second);
4010
+ const dist$1 = (c) => Math.abs(c[0] - previous[0]) + Math.abs(c[1] - previous[1]) + Math.abs(c[2] - previous[2]);
4011
+ return dist$1(p) <= dist$1(s) ? p : s;
4012
+ }
4013
+ /**
4014
+ * A simulated 3D body. Like {@link PhysicsBody2D}, its signals hold one
4015
+ * value per composition frame and reading one runs the simulation.
4016
+ */
4017
+ var PhysicsBody3D = class {
4018
+ collisions = [];
4019
+ /** @internal */ recording;
4020
+ /** @internal */ sim;
4021
+ /** @internal */
4022
+ constructor(world, sim, type, layer, start, options, recording) {
4023
+ this.world = world;
4024
+ this.type = type;
4025
+ this.layer = layer;
4026
+ this.start = start;
4027
+ this.options = options;
4028
+ this.sim = sim;
4029
+ this.recording = recording;
4030
+ }
4031
+ get startFrame() {
4032
+ return Math.max(0, Math.round(this.options.startFrame ?? 0));
4033
+ }
4034
+ get gravityScale() {
4035
+ return this.options.gravityScale ?? 1;
4036
+ }
4037
+ get output() {
4038
+ return this.options.output;
4039
+ }
4040
+ /** Center, px (what Layer3D's `x` / `y` / `z` mean). */
4041
+ get x() {
4042
+ return this.recording.signal("x");
4043
+ }
4044
+ get y() {
4045
+ return this.recording.signal("y");
4046
+ }
4047
+ get z() {
4048
+ return this.recording.signal("z");
4049
+ }
4050
+ /** Degrees, continuous. */
4051
+ get rotateX() {
4052
+ return this.recording.signal("rotateX");
4053
+ }
4054
+ get rotateY() {
4055
+ return this.recording.signal("rotateY");
4056
+ }
4057
+ get rotateZ() {
4058
+ return this.recording.signal("rotateZ");
4059
+ }
4060
+ /** px/s. */
4061
+ get vx() {
4062
+ return this.recording.signal("vx");
4063
+ }
4064
+ get vy() {
4065
+ return this.recording.signal("vy");
4066
+ }
4067
+ get vz() {
4068
+ return this.recording.signal("vz");
4069
+ }
4070
+ get speed() {
4071
+ return this.recording.signal("speed");
4072
+ }
4073
+ /** Hit envelope, as on 2D bodies. */
4074
+ get impact() {
4075
+ return this.recording.signal("impact");
4076
+ }
4077
+ /** 1 while the body is at rest, else 0. */
4078
+ get sleeping() {
4079
+ return this.recording.signal("sleeping");
4080
+ }
4081
+ /** @internal */
4082
+ kinematicTarget(frame) {
4083
+ const follow = this.options.follow;
4084
+ if (this.type !== "kinematic" || !follow) return void 0;
4085
+ const fps = this.world.fps;
4086
+ const read = (d, fallback) => d === void 0 ? fallback : sampleDriver(d, frame, fps);
4087
+ const p = this.start.position;
4088
+ const r = this.start.rotation;
4089
+ const ppm = this.world.pixelsPerMeter;
4090
+ return {
4091
+ position: [
4092
+ read(follow.x, p[0]) / ppm,
4093
+ read(follow.y, p[1]) / ppm,
4094
+ read(follow.z, p[2]) / ppm
4095
+ ],
4096
+ rotation: quatFromEuler(read(follow.rotateX, r[0]), read(follow.rotateY, r[1]), read(follow.rotateZ, r[2]))
4097
+ };
4098
+ }
4099
+ /** @internal */
4100
+ record(index, previous) {
4101
+ const ppm = this.world.pixelsPerMeter;
4102
+ const rec = this.recording;
4103
+ const [x, y, z] = this.sim.position();
4104
+ rec.channel("x")[index] = x * ppm;
4105
+ rec.channel("y")[index] = y * ppm;
4106
+ rec.channel("z")[index] = z * ppm;
4107
+ const rx = rec.channel("rotateX");
4108
+ const ry = rec.channel("rotateY");
4109
+ const rz = rec.channel("rotateZ");
4110
+ const prev = previous < 0 ? this.start.rotation : [
4111
+ rx[previous],
4112
+ ry[previous],
4113
+ rz[previous]
4114
+ ];
4115
+ const e = eulerFromQuat(this.sim.rotation(), prev);
4116
+ rx[index] = e[0];
4117
+ ry[index] = e[1];
4118
+ rz[index] = e[2];
4119
+ const [vx, vy, vz] = this.sim.velocity();
4120
+ rec.channel("vx")[index] = vx * ppm;
4121
+ rec.channel("vy")[index] = vy * ppm;
4122
+ rec.channel("vz")[index] = vz * ppm;
4123
+ rec.channel("speed")[index] = Math.hypot(vx, vy, vz) * ppm;
4124
+ rec.channel("sleeping")[index] = this.sim.sleeping() ? 1 : 0;
4125
+ }
4126
+ /** @internal */
4127
+ boundChannels() {
4128
+ const out = [
4129
+ ["x", "x"],
4130
+ ["y", "y"],
4131
+ ["z", "z"]
4132
+ ];
4133
+ if (this.options.lockRotation !== true) out.push(["rotateX", "rotateX"], ["rotateY", "rotateY"], ["rotateZ", "rotateZ"]);
4134
+ return out;
4135
+ }
4136
+ /** @internal World point (px) → local frame (meters) at the start pose. */
4137
+ localAnchor(point) {
4138
+ if (!point) return [
4139
+ 0,
4140
+ 0,
4141
+ 0
4142
+ ];
4143
+ const ppm = this.world.pixelsPerMeter;
4144
+ const p = this.sim.position();
4145
+ const [qx, qy, qz, qw] = this.sim.rotation();
4146
+ return rotateByQuat([
4147
+ point[0] / ppm - p[0],
4148
+ point[1] / ppm - p[1],
4149
+ point[2] / ppm - p[2]
4150
+ ], [
4151
+ -qx,
4152
+ -qy,
4153
+ -qz,
4154
+ qw
4155
+ ]);
4156
+ }
4157
+ /** @internal Start-pose center, px. */
4158
+ center() {
4159
+ const ppm = this.world.pixelsPerMeter;
4160
+ const [x, y, z] = this.sim.position();
4161
+ return [
4162
+ x * ppm,
4163
+ y * ppm,
4164
+ z * ppm
4165
+ ];
4166
+ }
4167
+ };
4168
+ function rotateByQuat(v, q) {
4169
+ const r = quatMul(quatMul(q, [
4170
+ v[0],
4171
+ v[1],
4172
+ v[2],
4173
+ 0
4174
+ ]), [
4175
+ -q[0],
4176
+ -q[1],
4177
+ -q[2],
4178
+ q[3]
4179
+ ]);
4180
+ return [
4181
+ r[0],
4182
+ r[1],
4183
+ r[2]
4184
+ ];
4185
+ }
4186
+ /**
4187
+ * A deterministic 3D rigid-body world (Rapier) for Layer3D primitives and
4188
+ * models, in the 3D scene's pixels (y down). Same flow as 2D: add bodies,
4189
+ * `simulate()`, and each layer's `x/y/z` and `rotateX/Y/Z` follow the
4190
+ * simulation; bodies expose signals for everything else.
4191
+ */
4192
+ var PhysicsWorld3D = class extends WorldCore {
4193
+ /** @internal */
4194
+ constructor(backend, options) {
4195
+ const ppm = options.pixelsPerMeter ?? 100;
4196
+ const g = options.gravity ?? 2400;
4197
+ const gravity = typeof g === "number" ? [
4198
+ 0,
4199
+ g / ppm,
4200
+ 0
4201
+ ] : [
4202
+ g[0] / ppm,
4203
+ g[1] / ppm,
4204
+ g[2] / ppm
4205
+ ];
4206
+ super(backend.createWorld3D(gravity), gravity, options);
4207
+ }
4208
+ /** Adds a body for a Layer3D primitive or model (centered on its `x/y/z`), or a plain box. */
4209
+ body(target, options = {}) {
4210
+ this.assertOpen();
4211
+ const layer = typeof target.kind === "string" ? target : void 0;
4212
+ const t = target;
4213
+ const position = [
4214
+ num(t.x, 0),
4215
+ num(t.y, 0),
4216
+ num(t.z, 0)
4217
+ ];
4218
+ const rotation = [
4219
+ num(t.rotateX, 0),
4220
+ num(t.rotateY, 0),
4221
+ num(t.rotateZ, 0)
4222
+ ];
4223
+ const ppm = this.pixelsPerMeter;
4224
+ const type = options.type ?? "dynamic";
4225
+ const v = options.velocity ?? [
4226
+ 0,
4227
+ 0,
4228
+ 0
4229
+ ];
4230
+ const w = options.angularVelocity ?? [
4231
+ 0,
4232
+ 0,
4233
+ 0
4234
+ ];
4235
+ const spec$1 = {
4236
+ type,
4237
+ position: [
4238
+ position[0] / ppm,
4239
+ position[1] / ppm,
4240
+ position[2] / ppm
4241
+ ],
4242
+ rotation: quatFromEuler(rotation[0], rotation[1], rotation[2]),
4243
+ velocity: [
4244
+ v[0] / ppm,
4245
+ v[1] / ppm,
4246
+ v[2] / ppm
4247
+ ],
4248
+ angularVelocity: [
4249
+ w[0] * DEG,
4250
+ w[1] * DEG,
4251
+ w[2] * DEG
4252
+ ],
4253
+ linearDamping: options.linearDamping ?? 0,
4254
+ angularDamping: options.angularDamping ?? 0,
4255
+ gravityScale: options.gravityScale ?? 1,
4256
+ lockRotation: options.lockRotation === true,
4257
+ ...typeof options.lockRotation === "object" && { enabledRotations: [
4258
+ !options.lockRotation.x,
4259
+ !options.lockRotation.y,
4260
+ !options.lockRotation.z
4261
+ ] },
4262
+ ccd: options.ccd ?? false,
4263
+ enabled: true,
4264
+ sensor: options.sensor ?? false,
4265
+ density: options.density ?? 1,
4266
+ friction: options.friction ?? .6,
4267
+ restitution: options.restitution ?? .3,
4268
+ shape: scaleShape(colliderShape3D(t, options), 1 / ppm)
4269
+ };
4270
+ const simBody = this.sim.addBody(spec$1);
4271
+ const body = new PhysicsBody3D(this, simBody, type, layer, {
4272
+ position,
4273
+ rotation
4274
+ }, options, this.newRecording());
4275
+ return this.addBody(body);
4276
+ }
4277
+ /** A fixed, very large floor whose top face sits at `y`. */
4278
+ ground(options) {
4279
+ const t = 2e3;
4280
+ return this.body({
4281
+ x: 0,
4282
+ y: options.y + t / 2,
4283
+ z: 0,
4284
+ width: 1e6,
4285
+ height: t,
4286
+ depth: 1e6
4287
+ }, {
4288
+ type: "fixed",
4289
+ friction: options.friction,
4290
+ restitution: options.restitution ?? .2
4291
+ });
4292
+ }
4293
+ /** Fixed floor and four walls around a box centered on `x`/`z`, floor at `y + height/2`. */
4294
+ walls(options) {
4295
+ const { width: W, height: H, depth: D } = options;
4296
+ const [x, y, z] = [
4297
+ options.x ?? 0,
4298
+ options.y ?? 0,
4299
+ options.z ?? 0
4300
+ ];
4301
+ const t = options.thickness ?? 400;
4302
+ const mat = {
4303
+ type: "fixed",
4304
+ friction: options.friction,
4305
+ restitution: options.restitution ?? .2
4306
+ };
4307
+ const tall = H * 4;
4308
+ const wy = y + H / 2 - tall / 2;
4309
+ return [
4310
+ this.body({
4311
+ x,
4312
+ y: y + H / 2 + t / 2,
4313
+ z,
4314
+ width: W + 2 * t,
4315
+ height: t,
4316
+ depth: D + 2 * t
4317
+ }, mat),
4318
+ this.body({
4319
+ x: x - W / 2 - t / 2,
4320
+ y: wy,
4321
+ z,
4322
+ width: t,
4323
+ height: tall,
4324
+ depth: D + 2 * t
4325
+ }, mat),
4326
+ this.body({
4327
+ x: x + W / 2 + t / 2,
4328
+ y: wy,
4329
+ z,
4330
+ width: t,
4331
+ height: tall,
4332
+ depth: D + 2 * t
4333
+ }, mat),
4334
+ this.body({
4335
+ x,
4336
+ y: wy,
4337
+ z: z - D / 2 - t / 2,
4338
+ width: W,
4339
+ height: tall,
4340
+ depth: t
4341
+ }, mat),
4342
+ this.body({
4343
+ x,
4344
+ y: wy,
4345
+ z: z + D / 2 + t / 2,
4346
+ width: W,
4347
+ height: tall,
4348
+ depth: t
4349
+ }, mat)
4350
+ ];
4351
+ }
4352
+ /** Pins a body to the world at a point (default its center); it can still turn around it. */
4353
+ pin(body, at) {
4354
+ const point = at ?? body.center();
4355
+ const anchor = this.anchorBody(point);
4356
+ this.joint(body, anchor, {
4357
+ type: "spherical",
4358
+ anchorA: body.localAnchor(point),
4359
+ anchorB: [
4360
+ 0,
4361
+ 0,
4362
+ 0
4363
+ ]
4364
+ });
4365
+ return this;
4366
+ }
4367
+ /** Joins two bodies at a world point, turning only around `axis` (default z, facing the camera). */
4368
+ hinge(a, b, at, axis = [
4369
+ 0,
4370
+ 0,
4371
+ 1
4372
+ ]) {
4373
+ this.joint(a, b, {
4374
+ type: "revolute",
4375
+ anchorA: a.localAnchor(at),
4376
+ anchorB: b.localAnchor(at),
4377
+ axis
4378
+ });
4379
+ return this;
4380
+ }
4381
+ /** Glues two bodies together rigidly. */
4382
+ weld(a, b) {
4383
+ this.joint(a, b, {
4384
+ type: "fixed",
4385
+ anchorA: [
4386
+ 0,
4387
+ 0,
4388
+ 0
4389
+ ],
4390
+ anchorB: b.localAnchor(a.center())
4391
+ });
4392
+ return this;
4393
+ }
4394
+ spring(a, b, options = {}) {
4395
+ const { other, pa, pb } = this.endpoints(a, b, options.anchorA, options.anchorB);
4396
+ const ppm = this.pixelsPerMeter;
4397
+ const length = (options.length ?? dist(pa, pb)) / ppm;
4398
+ const ma = a.type === "dynamic" ? a.sim.mass() : 0;
4399
+ const mb = other.type === "dynamic" ? other.sim.mass() : 0;
4400
+ const mass = ma > 0 && mb > 0 ? ma * mb / (ma + mb) : Math.max(ma, mb, .001);
4401
+ const w = 2 * Math.PI * (options.frequency ?? 2);
4402
+ this.joint(a, other, {
4403
+ type: "spring",
4404
+ anchorA: a.localAnchor(pa),
4405
+ anchorB: other.localAnchor(pb),
4406
+ restLength: length,
4407
+ stiffness: mass * w * w,
4408
+ damping: 2 * (options.dampingRatio ?? .2) * mass * w
4409
+ });
4410
+ return this;
4411
+ }
4412
+ rope(a, b, options = {}) {
4413
+ const { other, pa, pb } = this.endpoints(a, b, options.anchorA, options.anchorB);
4414
+ this.joint(a, other, {
4415
+ type: "rope",
4416
+ anchorA: a.localAnchor(pa),
4417
+ anchorB: other.localAnchor(pb),
4418
+ length: (options.length ?? dist(pa, pb)) / this.pixelsPerMeter
4419
+ });
4420
+ return this;
4421
+ }
4422
+ /** A steady push, px/s² (mass-independent). Drivers are read every frame. */
4423
+ force(body, accel) {
4424
+ const ppm = this.pixelsPerMeter;
4425
+ const read = (d, frame) => d === void 0 ? 0 : sampleDriver(d, frame, this.fps) / ppm;
4426
+ this.addForce(body, (frame) => [
4427
+ read(accel.x, frame),
4428
+ read(accel.y, frame),
4429
+ read(accel.z, frame)
4430
+ ]);
4431
+ return this;
4432
+ }
4433
+ /** A force field, as in 2D: returns `[ax, ay, az]` px/s² for a body at `x/y/z` px. */
4434
+ field(accel, options = {}) {
4435
+ const ppm = this.pixelsPerMeter;
4436
+ this.addField((body, frame) => {
4437
+ const [x, y, z] = body.sim.position();
4438
+ const [vx, vy, vz] = body.sim.velocity();
4439
+ const a = accel({
4440
+ x: x * ppm,
4441
+ y: y * ppm,
4442
+ z: z * ppm,
4443
+ vx: vx * ppm,
4444
+ vy: vy * ppm,
4445
+ vz: vz * ppm,
4446
+ frame,
4447
+ body
4448
+ });
4449
+ return a ? [
4450
+ a[0] / ppm,
4451
+ a[1] / ppm,
4452
+ a[2] / ppm
4453
+ ] : null;
4454
+ }, options.bodies);
4455
+ return this;
4456
+ }
4457
+ /** An instant kick at a simulation frame: adds `[vx, vy, vz]` px/s. */
4458
+ impulse(body, frame, velocity) {
4459
+ const ppm = this.pixelsPerMeter;
4460
+ this.addImpulse(body, frame, [
4461
+ velocity[0] / ppm,
4462
+ velocity[1] / ppm,
4463
+ velocity[2] / ppm
4464
+ ]);
4465
+ return this;
4466
+ }
4467
+ lerpRotation(a, b, t) {
4468
+ const sign = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] < 0 ? -1 : 1;
4469
+ const q = a.map((v, i) => v + (b[i] * sign - v) * t);
4470
+ const len = Math.hypot(...q) || 1;
4471
+ return q.map((v) => v / len);
4472
+ }
4473
+ joint(a, b, spec$1) {
4474
+ this.assertOpen();
4475
+ this.sim.addJoint(a.sim, b.sim, spec$1);
4476
+ }
4477
+ anchorBody(point) {
4478
+ return this.body({
4479
+ x: point[0],
4480
+ y: point[1],
4481
+ z: point[2],
4482
+ width: 1,
4483
+ height: 1,
4484
+ depth: 1
4485
+ }, {
4486
+ type: "fixed",
4487
+ output: "none",
4488
+ sensor: true
4489
+ });
4490
+ }
4491
+ endpoints(a, b, anchorA, anchorB) {
4492
+ const pa = anchorA ?? a.center();
4493
+ if (Array.isArray(b)) {
4494
+ const pb = anchorB ?? b;
4495
+ return {
4496
+ other: this.anchorBody(pb),
4497
+ pa,
4498
+ pb
4499
+ };
4500
+ }
4501
+ return {
4502
+ other: b,
4503
+ pa,
4504
+ pb: anchorB ?? b.center()
4505
+ };
4506
+ }
4507
+ };
4508
+ function dist(a, b) {
4509
+ return Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
4510
+ }
4511
+ function num(v, fallback) {
4512
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
4513
+ }
4514
+ /** Collider in px around the layer's center, with the layer's scale applied. */
4515
+ function colliderShape3D(t, options) {
4516
+ const id = typeof t.id === "string" ? ` "${t.id}"` : "";
4517
+ const s = num(t.scale, 1);
4518
+ const scale = [
4519
+ s * num(t.scaleX, 1),
4520
+ s * num(t.scaleY, 1),
4521
+ s * num(t.scaleZ, 1)
4522
+ ];
4523
+ const uniform = scale[0] === scale[1] && scale[1] === scale[2];
4524
+ const prim = t.primitive3d ?? {};
4525
+ const mode = options.shape ?? "auto";
4526
+ const hull = () => {
4527
+ const pts = meshPoints(t.modelData);
4528
+ if (!pts) return void 0;
4529
+ return {
4530
+ kind: "hull",
4531
+ points: pts.map((v, i) => v * scale[i % 3])
4532
+ };
4533
+ };
4534
+ if (options.size || mode === "box") {
4535
+ const [w, h$1, d] = options.size ?? boxSize(t, prim) ?? [
4536
+ 0,
4537
+ 0,
4538
+ 0
4539
+ ];
4540
+ if (w > 0 && h$1 > 0 && d > 0) return {
4541
+ kind: "box",
4542
+ hx: w * scale[0] / 2,
4543
+ hy: h$1 * scale[1] / 2,
4544
+ hz: d * scale[2] / 2,
4545
+ radius: prim.type === "roundedBox" ? num(prim.radius, 0) * Math.min(...scale) : 0
4546
+ };
4547
+ }
4548
+ if (mode === "hull") {
4549
+ const h$1 = hull();
4550
+ if (h$1) return h$1;
4551
+ }
4552
+ if ((mode === "sphere" || mode === "auto" && prim.type === "sphere") && (uniform || mode === "sphere")) {
4553
+ const r = num(prim.radius, 0) || Math.max(...boxSize(t, prim) ?? [0]) / 2;
4554
+ if (r > 0) return {
4555
+ kind: "ball",
4556
+ radius: r * Math.max(...scale)
4557
+ };
4558
+ }
4559
+ const rTop = num(prim.radiusTop, num(prim.radius, 0));
4560
+ const rBottom = num(prim.radiusBottom, num(prim.radius, 0));
4561
+ if ((mode === "cylinder" || mode === "auto" && prim.type === "cylinder") && rTop === rBottom && rTop > 0 && scale[0] === scale[2]) return {
4562
+ kind: "cylinder",
4563
+ halfHeight: num(prim.height, 0) * scale[1] / 2,
4564
+ radius: rTop * scale[0]
4565
+ };
4566
+ if (mode === "auto" && prim.type === "roundedBox" && (prim.taper ?? 1) === 1) {
4567
+ const [w, h$1, d] = [
4568
+ num(prim.width, 0),
4569
+ num(prim.height, 0),
4570
+ num(prim.depth, 0)
4571
+ ];
4572
+ return {
4573
+ kind: "box",
4574
+ hx: w * scale[0] / 2,
4575
+ hy: h$1 * scale[1] / 2,
4576
+ hz: d * scale[2] / 2,
4577
+ radius: num(prim.radius, 0) * Math.min(...scale)
4578
+ };
4579
+ }
4580
+ const h = hull();
4581
+ if (h) return h;
4582
+ const size$1 = boxSize(t, prim);
4583
+ if (size$1) return {
4584
+ kind: "box",
4585
+ hx: size$1[0] * scale[0] / 2,
4586
+ hy: size$1[1] * scale[1] / 2,
4587
+ hz: size$1[2] * scale[2] / 2
4588
+ };
4589
+ throw new Error(`Physics: layer${id} has no mesh or size to build a 3D collider from; pass \`size: [w, h, d]\`.`);
4590
+ }
4591
+ function boxSize(t, prim) {
4592
+ if (prim.type === "roundedBox") return [
4593
+ num(prim.width, 0),
4594
+ num(prim.height, 0),
4595
+ num(prim.depth, 0)
4596
+ ];
4597
+ if (prim.type === "sphere") {
4598
+ const d = num(prim.radius, 0) * 2;
4599
+ return [
4600
+ d,
4601
+ d,
4602
+ d
4603
+ ];
4604
+ }
4605
+ if (prim.type === "cylinder") {
4606
+ const d = Math.max(num(prim.radiusTop, num(prim.radius, 0)), num(prim.radiusBottom, num(prim.radius, 0))) * 2;
4607
+ return [
4608
+ d,
4609
+ num(prim.height, 0),
4610
+ d
4611
+ ];
4612
+ }
4613
+ if (typeof t.width === "number" && typeof t.height === "number" && typeof t.depth === "number") return [
4614
+ t.width,
4615
+ t.height,
4616
+ t.depth
4617
+ ];
4618
+ }
4619
+ /** Every vertex of a model, flat xyz, at most ~4k points (the hull needs no more). */
4620
+ function meshPoints(modelData) {
4621
+ const meshes = modelData?.meshes;
4622
+ if (!meshes?.length) return void 0;
4623
+ let total = 0;
4624
+ for (const m of meshes) total += (m.positions?.length ?? 0) / 3;
4625
+ if (total < 4) return void 0;
4626
+ const stride = Math.max(1, Math.floor(total / 4096));
4627
+ const out = [];
4628
+ let i = 0;
4629
+ for (const m of meshes) {
4630
+ const p = m.positions;
4631
+ if (!p) continue;
4632
+ for (let v = 0; v < p.length; v += 3, i++) if (i % stride === 0) out.push(p[v], p[v + 1], p[v + 2]);
4633
+ }
4634
+ return out;
4635
+ }
4636
+ function scaleShape(shape, s) {
4637
+ switch (shape.kind) {
4638
+ case "ball": return {
4639
+ kind: "ball",
4640
+ radius: shape.radius * s
4641
+ };
4642
+ case "box": return {
4643
+ kind: "box",
4644
+ hx: shape.hx * s,
4645
+ hy: shape.hy * s,
4646
+ hz: shape.hz * s,
4647
+ radius: (shape.radius ?? 0) * s
4648
+ };
4649
+ case "cylinder": return {
4650
+ kind: "cylinder",
4651
+ halfHeight: shape.halfHeight * s,
4652
+ radius: shape.radius * s
4653
+ };
4654
+ case "hull": return {
4655
+ kind: "hull",
4656
+ points: shape.points.map((v) => v * s)
4657
+ };
4658
+ }
4659
+ }
4660
+
4661
+ //#endregion
4662
+ //#region src/physics/index.ts
4663
+ /**
4664
+ * Rigid-body physics baked into signals. A world simulates once, while the
4665
+ * composition is built (Rapier's deterministic build, so every machine gets
4666
+ * the same motion), and replays as per-frame signals: layers follow their
4667
+ * bodies, and `impact`, `speed`, … drive any other prop or effect.
4668
+ *
4669
+ * ```ts
4670
+ * const world = await Physics.world2d({ fps: 30, frames: 150 });
4671
+ * world.walls({ width: W, height: H });
4672
+ * const card = world.body(cardLayer, { restitution: 0.4 });
4673
+ * world.simulate();
4674
+ * flash.animate(LayerAnimation.create().signal("opacity", card.impact));
4675
+ * ```
4676
+ */
4677
+ const Physics = {
4678
+ async world2d(options) {
4679
+ return new PhysicsWorld2D(await rapierBackend(2), options);
4680
+ },
4681
+ async world3d(options) {
4682
+ return new PhysicsWorld3D(await rapierBackend(3), options);
4683
+ }
4684
+ };
4685
+
4686
+ //#endregion
4687
+ //#region src/styles.ts
4688
+ const look = (...effects) => effects;
4689
+ const Styles = {
4690
+ pixelArt: (o = {}) => look(new Posterize({
4691
+ palette: o.palette ?? "pico8",
4692
+ pixelSize: o.pixelSize ?? 6,
4693
+ dither: .4
4694
+ })),
4695
+ gameBoy: (o = {}) => look(new Posterize({
4696
+ palette: "gameboy",
4697
+ pixelSize: o.pixelSize ?? 4,
4698
+ dither: .6
4699
+ })),
4700
+ teletext: (o = {}) => look(new Posterize({
4701
+ palette: "teletext",
4702
+ pixelSize: o.pixelSize ?? 10
4703
+ })),
4704
+ ledWall: (o = {}) => look(new Pixelate({
4705
+ size: o.size ?? 14,
4706
+ shape: "circle",
4707
+ gap: .18
4708
+ })),
4709
+ ascii: (o = {}) => look(new Ascii({
4710
+ cellSize: o.cellSize ?? 10,
4711
+ colorMode: o.matrix ? "green" : "source",
4712
+ bg: o.matrix ? "#020a04" : "#0b0b0b"
4713
+ })),
4714
+ oneBit: (o = {}) => look(new Dither({
4715
+ mode: "bayer",
4716
+ scale: o.scale ?? 2,
4717
+ dark: o.dark ?? "#111111",
4718
+ light: o.light ?? "#f2efe6"
4719
+ })),
4720
+ risograph: (o = {}) => {
4721
+ const a = o.inkA ?? "#1d3fbb";
4722
+ const b = o.inkB ?? "#ff5fa2";
4723
+ const paper = o.paper ?? "#f4efe4";
4724
+ return look(new GradientMap({ stops: [
4725
+ {
4726
+ position: 0,
4727
+ color: a
4728
+ },
4729
+ {
4730
+ position: .55,
4731
+ color: b
4732
+ },
4733
+ {
4734
+ position: 1,
4735
+ color: paper
4736
+ }
4737
+ ] }), new Posterize({
4738
+ palette: "custom",
4739
+ colors: [
4740
+ a,
4741
+ b,
4742
+ paper
4743
+ ],
4744
+ dither: .8,
4745
+ pixelSize: 2
4746
+ }), new FilmGrain({ strength: .2 }));
4747
+ },
4748
+ cartoon: (o = {}) => look(new Toon({
4749
+ levels: o.levels ?? 4,
4750
+ edgeColor: o.ink ?? "#111111",
4751
+ saturation: 1.3
4752
+ })),
4753
+ comic: (o = {}) => look(new Toon({
4754
+ levels: 4,
4755
+ edgeWidth: 1.5,
4756
+ saturation: 1.4
4757
+ }), new HalftoneScreen({
4758
+ frequency: o.dotFrequency ?? 70,
4759
+ opacity: .35
4760
+ })),
4761
+ thermal: () => look(new GradientMap({ stops: [
4762
+ {
4763
+ position: 0,
4764
+ color: "#000010"
4765
+ },
4766
+ {
4767
+ position: .25,
4768
+ color: "#3b0a7a"
4769
+ },
4770
+ {
4771
+ position: .5,
4772
+ color: "#c4205f"
4773
+ },
4774
+ {
4775
+ position: .75,
4776
+ color: "#ff9a1f"
4777
+ },
4778
+ {
4779
+ position: 1,
4780
+ color: "#fffbe0"
4781
+ }
4782
+ ] })),
4783
+ vhs: (o = {}) => look(new CRT({
4784
+ tracking: o.tracking ?? .5,
4785
+ chroma: 4,
4786
+ curvature: .04,
4787
+ scanlines: .25,
4788
+ mask: .05,
4789
+ noise: .15
4790
+ }), new RGBSplit({ amount: 3 })),
4791
+ crt: (o = {}) => look(new CRT({
4792
+ curvature: o.curvature ?? .15,
4793
+ scanlines: .5,
4794
+ mask: .35
4795
+ })),
4796
+ glitch: (o = {}) => look(new RGBSplit({ amount: o.amount ?? 18 }), new CRT({
4797
+ tracking: 1,
4798
+ chroma: 6,
4799
+ curvature: 0,
4800
+ scanlines: .1,
4801
+ mask: 0,
4802
+ vignette: 0
4803
+ })),
4804
+ oilPainting: (o = {}) => look(new Painterly({
4805
+ style: "oil",
4806
+ radius: o.brush ?? 5
4807
+ })),
4808
+ watercolor: (o = {}) => look(new Painterly({
4809
+ style: "watercolor",
4810
+ radius: o.brush ?? 6,
4811
+ paper: .5
4812
+ })),
4813
+ topographic: (o = {}) => look(new Contour({
4814
+ levels: o.levels ?? 16,
4815
+ fill: "flat",
4816
+ lineColor: o.ink ?? "#5a3a1a",
4817
+ fillColor: o.paper ?? "#f3ead8"
4818
+ })),
4819
+ kaleidoscope: (o = {}) => look(new Kaleidoscope({
4820
+ segments: o.segments ?? 8,
4821
+ rotation: o.rotation ?? 0
4822
+ })),
4823
+ opArt: (o = {}) => look(new OpArt({
4824
+ pattern: o.pattern ?? "stripes",
4825
+ frequency: o.frequency ?? 60
4826
+ })),
4827
+ holographic: (o = {}) => look(new Iridescence({
4828
+ strength: o.strength ?? .7,
4829
+ shift: o.shift ?? 0
4830
+ })),
4831
+ noir: () => look(new GradientMap({ stops: [
4832
+ {
4833
+ position: 0,
4834
+ color: "#000000"
4835
+ },
4836
+ {
4837
+ position: .55,
4838
+ color: "#8a8a8a"
4839
+ },
4840
+ {
4841
+ position: 1,
4842
+ color: "#ffffff"
4843
+ }
4844
+ ] }), new FilmGrain({ strength: .35 }), new Vignette({ strength: .6 })),
4845
+ film: () => look(new FilmGrain({ strength: .25 }), new Vignette({ strength: .35 }))
4846
+ };
4847
+
4848
+ //#endregion
4849
+ //#region src/index.ts
4850
+ function decorateTrackSignals(track, source) {
4851
+ if (!track) return track;
4852
+ if (source && !track.source) Object.defineProperty(track, "source", {
4853
+ value: source,
4854
+ enumerable: true,
4855
+ writable: true,
4856
+ configurable: true
4857
+ });
4858
+ if (typeof track.section !== "function") Object.defineProperty(track, "section", {
4859
+ value: (sourceOrOptions, options) => {
4860
+ if (typeof sourceOrOptions === "object" && sourceOrOptions !== null && !("kind" in sourceOrOptions) && !("inputHandleId" in sourceOrOptions) && !("src" in sourceOrOptions)) {
4861
+ const resolvedSource$1 = sourceOrOptions.source ?? track.source ?? source;
4862
+ return Layer.section(resolvedSource$1, track, sourceOrOptions);
4863
+ }
4864
+ const resolvedSource = sourceOrOptions ?? track.source ?? source;
4865
+ return Layer.section(resolvedSource, track, options);
4866
+ },
4867
+ enumerable: false,
1976
4868
  writable: true,
1977
4869
  configurable: true
1978
4870
  });
@@ -2120,6 +5012,8 @@ var Composition = class Composition {
2120
5012
  audioTracks = [];
2121
5013
  signals = {};
2122
5014
  _frameHooks = [];
5015
+ _prepareHooks = [];
5016
+ _clipVision = /* @__PURE__ */ new Map();
2123
5017
  _visionConfig;
2124
5018
  _visionBundle;
2125
5019
  _effects = [];
@@ -2153,6 +5047,66 @@ var Composition = class Composition {
2153
5047
  return this._visionBundle;
2154
5048
  }
2155
5049
  /**
5050
+ * Vision for a clip, analysed per frame on demand and shared by everything
5051
+ * that reads it (see {@link ClipVision}): `comp.vision("dancer.mp4").person`
5052
+ * gives pose keypoints and a silhouette at any frame. Each frame is
5053
+ * analysed just before it renders, so nothing runs up front. Results
5054
+ * persist on disk in Node. The same clip and options return one instance.
5055
+ */
5056
+ vision(source, options = {}) {
5057
+ const key = `${source}\u0000${JSON.stringify(options)}`;
5058
+ let clip = this._clipVision.get(key);
5059
+ if (!clip) {
5060
+ clip = new ClipVision(source, this.fps, options);
5061
+ this._clipVision.set(key, clip);
5062
+ }
5063
+ return clip;
5064
+ }
5065
+ /**
5066
+ * @internal Analyses every `comp.vision` clip up to a composition frame
5067
+ * (frames already analysed are skipped), so consumers that step frame by
5068
+ * frame — physics, particles — always find every frame before it.
5069
+ */
5070
+ async prepareVision(frame) {
5071
+ this.linkClipMattes();
5072
+ await Promise.all([...this._clipVision.values()].map((clip) => clip.ready(0, frame)));
5073
+ }
5074
+ /**
5075
+ * Points matte-family `withVision` layers at the `comp.vision` clip they
5076
+ * show, so the cutout reuses that clip's per-frame subject instead of
5077
+ * segmenting the frame again during render. Only layers whose settings
5078
+ * would give the same subject are linked; the rest keep their own pass.
5079
+ */
5080
+ linkClipMattes() {
5081
+ if (this._clipVision.size === 0) return;
5082
+ const walk = (node) => {
5083
+ if (!node || typeof node !== "object") return;
5084
+ const n = node;
5085
+ if (n.kind === "media" && n.dataType === "Video" && typeof n.inputHandleId === "string" && n.vision instanceof Vision && !(CLIP_SUBJECT in n.vision)) {
5086
+ const clip = this.clipForMatte(n.inputHandleId, n.vision);
5087
+ if (clip) {
5088
+ clip.keepSubjects();
5089
+ Object.defineProperty(n.vision, CLIP_SUBJECT, {
5090
+ value: clip,
5091
+ enumerable: false,
5092
+ configurable: true
5093
+ });
5094
+ }
5095
+ }
5096
+ if (Array.isArray(n.children)) for (const c of n.children) walk(c);
5097
+ };
5098
+ for (const child of this.children) walk(child);
5099
+ }
5100
+ clipForMatte(source, v) {
5101
+ const mode = v.mode ?? "passthrough";
5102
+ if (mode !== "matte" && mode !== "mask" && mode !== "crop") return;
5103
+ if (v.matteSource === "selfie" || v.keyBackground === true || v.classes !== void 0 || v.enablePose === true || v.enableMatte === true || v.visionBundle !== void 0 || (v.maskThreshold ?? .5) !== .5 || v.featherRadius !== void 0) return;
5104
+ for (const clip of this._clipVision.values()) {
5105
+ const o = clip.options;
5106
+ if (clip.source === source && (o.variant ?? "s") === (v.variant ?? "s") && (o.confidence ?? .3) === (v.confidence ?? .3)) return clip;
5107
+ }
5108
+ }
5109
+ /**
2156
5110
  * One-shot, ffmpeg-free vision analysis of a media source.
2157
5111
  *
2158
5112
  * Decodes frames through the same mediabunny pipeline the renderer uses, runs the requested
@@ -2204,8 +5158,25 @@ var Composition = class Composition {
2204
5158
  this._frameHooks.push(callback);
2205
5159
  return this;
2206
5160
  }
5161
+ /**
5162
+ * Async work a frame needs before it is evaluated (vision, a live physics
5163
+ * world). Every render path awaits these, in order, before drawing the
5164
+ * frame; they may run more than once per frame, so keep them idempotent.
5165
+ */
5166
+ onPrepareFrame(callback) {
5167
+ this._prepareHooks.push(callback);
5168
+ return this;
5169
+ }
2207
5170
  notifyFrame(ctx) {
2208
5171
  for (const hook of this._frameHooks) hook(ctx);
5172
+ if (this._clipVision.size === 0 && this._prepareHooks.length === 0) return;
5173
+ return (async () => {
5174
+ await this.prepareVision(ctx.frame);
5175
+ for (const hook of this._prepareHooks) await hook(ctx);
5176
+ })();
5177
+ }
5178
+ hasFrameHooks() {
5179
+ return this._frameHooks.length > 0 || this._prepareHooks.length > 0 || this._clipVision.size > 0;
2209
5180
  }
2210
5181
  constructor(options) {
2211
5182
  this.width = options.width;
@@ -2538,7 +5509,7 @@ var Composition = class Composition {
2538
5509
  signals: this.signals,
2539
5510
  ...this._effects.length > 0 && { effects: this._effects },
2540
5511
  ...this._visionConfig && { vision: this._visionConfig },
2541
- ...this._frameHooks.length > 0 && { onRequestFrame: (ctx) => this.notifyFrame(ctx) }
5512
+ ...this.hasFrameHooks() && { onRequestFrame: (ctx) => this.notifyFrame(ctx) }
2542
5513
  };
2543
5514
  }
2544
5515
  /**
@@ -2576,9 +5547,9 @@ var Composition = class Composition {
2576
5547
  * Can render either by timestamp in milliseconds (`atMs`) or by frame index (`frame`).
2577
5548
  */
2578
5549
  async renderFrame(options = {}) {
2579
- if (this._frameHooks.length > 0) {
5550
+ if (this.hasFrameHooks()) {
2580
5551
  const targetFrame = options.frame ?? (options.atMs !== void 0 ? Math.round(options.atMs / 1e3 * this.fps) : 0);
2581
- this.notifyFrame({
5552
+ await this.notifyFrame({
2582
5553
  frame: targetFrame,
2583
5554
  fps: this.fps,
2584
5555
  time: this.fps > 0 ? targetFrame / this.fps : 0,
@@ -2641,7 +5612,13 @@ function withAnimation(node) {
2641
5612
  Object.defineProperty(target, "animate", {
2642
5613
  value: (...anims) => {
2643
5614
  const incoming = anims.flat().flatMap((a) => a instanceof LayerAnimation ? a.tracks : a.tracks ?? []);
2644
- target.animation = { tracks: mergeAnimationTracks([...target.animation?.tracks ?? [], ...incoming]) };
5615
+ const current = target.animation;
5616
+ const existing = current?.tracks ?? [];
5617
+ const frameStep = anims.flat().map((a) => a.frameStep).filter((n) => n !== void 0).at(-1) ?? current?.frameStep;
5618
+ target.animation = {
5619
+ tracks: mergeAnimationTracks([...existing, ...incoming]),
5620
+ ...frameStep !== void 0 && frameStep > 1 && { frameStep }
5621
+ };
2645
5622
  return target;
2646
5623
  },
2647
5624
  enumerable: false,
@@ -2910,6 +5887,68 @@ const Layer = {
2910
5887
  children: options.children ?? [],
2911
5888
  ...options
2912
5889
  }),
5890
+ particles: (options) => {
5891
+ const system = new Particles(options);
5892
+ const source = {
5893
+ metadata: {
5894
+ width: options.width,
5895
+ height: options.height
5896
+ },
5897
+ operation: {
5898
+ ...system.toOperation(),
5899
+ effect: system,
5900
+ dataType: "Video"
5901
+ },
5902
+ children: []
5903
+ };
5904
+ return withAnimation({
5905
+ id: options.id ?? autoId("particles"),
5906
+ kind: "media",
5907
+ dataType: "Video",
5908
+ src: source,
5909
+ position: "absolute",
5910
+ x: options.x ?? 0,
5911
+ y: options.y ?? 0,
5912
+ width: options.width,
5913
+ height: options.height,
5914
+ ...options.startFrame !== void 0 && { startFrame: options.startFrame },
5915
+ ...options.durationFrames !== void 0 && { durationFrames: options.durationFrames },
5916
+ ...options.zIndex !== void 0 && { zIndex: options.zIndex }
5917
+ });
5918
+ },
5919
+ vfx: (options) => {
5920
+ const { x, y, id, startFrame, durationFrames, zIndex, ...props } = options;
5921
+ const vfx = new ProceduralVFX({
5922
+ outputType: "Video",
5923
+ ...props
5924
+ });
5925
+ const source = {
5926
+ metadata: {
5927
+ width: options.width,
5928
+ height: options.height
5929
+ },
5930
+ operation: {
5931
+ ...vfx.toOperation(),
5932
+ effect: vfx,
5933
+ dataType: "Video"
5934
+ },
5935
+ children: []
5936
+ };
5937
+ return withAnimation({
5938
+ id: id ?? autoId("vfx"),
5939
+ kind: "media",
5940
+ dataType: "Video",
5941
+ src: source,
5942
+ position: "absolute",
5943
+ x: x ?? 0,
5944
+ y: y ?? 0,
5945
+ width: options.width,
5946
+ height: options.height,
5947
+ ...startFrame !== void 0 && { startFrame },
5948
+ ...durationFrames !== void 0 && { durationFrames },
5949
+ ...zIndex !== void 0 && { zIndex }
5950
+ });
5951
+ },
2913
5952
  section: (source, targetOrOptions = {}, options = {}) => {
2914
5953
  let realSource = source;
2915
5954
  if (source && typeof source === "object" && "toSpec" in source && "children" in source) {
@@ -3216,5 +6255,5 @@ const Effect = Object.assign(Effect$1, effectFactories, {
3216
6255
  });
3217
6256
 
3218
6257
  //#endregion
3219
- export { AETextAnimatorSchema, AdvancedTextAnimatorBuilder, AdvancedTextAnimatorSchema, AnchorGroupingSchema, AnchorPresetSchema, AnimatableGlyphPropsSchema, AnimationTypeSchema, AnyOutputUnionSchema, ApplyLUT, AudioCompressor, AudioDelay, AudioExtractorSignalDataSchema, AudioFade, AudioLatentEngine, AudioLatentTrackCache, AudioMeshDeformPipeline, AudioNoiseGate, AudioParametricEq, AudioReverb, AudioSignal, AudioSignalExtractor, AudioSpectrumTypographySchema, BaseMediaOperationPropsSchema, BaseVideoLayerPropsSchema, BloomConfigSchema, Blur, BoxNodeSchema, CAPTION_LAYER_DEFAULTS, COCO17_BONES, COCO17_KEYPOINTS, COCO17_KEYPOINT_NAMES, COCO_CLASSES, COMPOSITE_OPERATIONS, COMPOSITOR_DEFAULTS, Camera3D, CameraAnimation, CameraNodeSchema, CameraParallax3D, CannyComputePipeline, CarrierHandoffConfigSchema, ChannelMerger, ChannelSplitter, ChromaticGlitchConfigSchema, Color, ColorBalance, ColorKey, ColorStopSchema, Composition, CompositorProgramSchema, ConfigHandleSchema, ConfigSchemaRegistry, ControlNetMultiplexer, CornerPin, Crop, CubicBezierSegmentSchema, Curves, CustomEffect, DATA_TYPE_EXTENSIONS, DEFAULT_CHART_COLORS, DEFAULT_DURATION_MS, DEFAULT_FPS, DEFAULT_MEDIA_DIMENSION, DataType, DataTypeVal, DataTypes, DepthNormalsComputePipeline, DepthOfField, DisplacementMap, DynamicStrokePropertiesSchema, ENVIRONMENT_PRESETS, Easing, Effect, EffectPipeline, EnhancedTextNodeSchema, EnvironmentFogSchema, EnvironmentPresetSchema, ExportResultSchema, ExpressionSelectorSchema, ExtendedGlyphPropertiesSchema, ExtendedLayerSchema, ExtractLUT, FileAssetSchema, FileDataSchema, FilmGrain, FlexNodeSchema, Flip, FontManager, GeneratorSignalDataSchema, GlassPipeline, GlobalCompositeOperation, GlyphAnchorGroupingSchema, GlyphAnchorPointSchema, Gradient, GradientMap, HalftoneScreen, HandleTypeVal, HeadlessMediaRenderer, HeadlessWebGPURenderer, HighPass, JsonValueSchema, KenBurns, KineticMarqueeConfigSchema, LIGHT_UNIFORM_SIZE_BYTES, Layer, Layer3D, LayerAnimation, LayerStyle, LayoutNodeSchema, Levels, Light, Light3D, LightNodeSchema, LightTypeSchema, Lighting, LineSpacingDynamicsSchema, Liquify, LongShadowConfigSchema, MAX_GRADIENT_STOPS, MAX_LIGHTS, MIME_TYPES, MaskMath, MaterialTypeSchema, Matrix4Math, MatteModeSchema, Media, MediaMetadataSchema, MediaNodeSchema, MediaOperationSchema, MediaSourceSchema, MeshWarp, Model3DNodeSchema, ModerationError, ModerationUnrefundableError, Modulate, MotionBlur, MotionBlurPipeline, MultiOutputGenericSchema, NodeMetadataSchema, NodeResultSchema, NodeVisualConfigSchema, NoiseGenerator, OpticalFlowComputePipeline, OutputItemSchema, PBRGlass, Paint, ParticleDissolveConfigSchema, PatchHeal, Path3D, PoseSkeletonRenderer, ProceduralVFX, ProgrammaticSignal, RefineEdge, RefractionCaustics3D, Relight3D, Renderer2D, Renderer3D, ResizerScaler, Rotate, SSAO, SSAOPipeline, Scene, SceneDefinitionSchema, SceneTransitionTypeSchema, SegmentationTexturePool, SelectiveColor, SelectorBasedOnSchema, SelectorModeSchema, SelectorShapeSchema, SelectorUnitsSchema, Sequence, ShadowPipeline, ShadowsHighlights, ShapeNodeSchema, Signal, SignalChannelMetaSchema, SignalDataSchema, SignalGateDataSchema, SignalMathDataSchema, SignalStatsSchema, SingleOutputGenericSchema, SkewPropertiesSchema, SlugFontCache, SlugPipeline, SourceOperationSchema, Spatial3DPropertiesSchema, SpatialLandmarkTransformer, SpringPhysicsSchema, StereoPanning, TEXT_LAYER_DEFAULTS, TemporalDeflicker, TemporalDeflickerPipeline, TemporalObjectTracker, TensorPipeline, TextAnchorConfigSchema, TextAnimator, TextAnimatorBuilder, TextAnimatorSchema, TextCursorConfigSchema, TextCursorStyleSchema, TextNodeSchema, TextOperationSchema, TextPathBuilder, TextPathOptionsSchema, TextPathSourceSchema, TextRangeSelectorSchema, TextScrambleConfigSchema, TextSelectorSchema, TextSignalSelectorSchema, TextSpanMarkSchema, TextSpanSchema, TextWigglySelectorSchema, TileOffset, TimelineSegmentSchema, TimelineTransformSchema, ToneMappingSchema, Transition, TransitionSchema, TransitionTypeSchema, TypewriterAnimatorSchema, TypingCadenceSchema, UnsharpMask, VariableFontAxesSchema, Vec2Schema, Vector3Math, VideoAnimationSchema, VideoLayerTypeSchema, VideoSpatialPropsSchema, VideoStylePropsSchema, VideoTextPropsSchema, VideoTimingPropsSchema, Vignette, VirtualMediaDataSchema, Vision, VisionBundle, VisionNode, VisionRunner, VolumetricFormationConfigSchema, VolumetricFormationModeSchema, accent, analyzeSequence, appendOperation, applyStaggerToChildren, bezier, blurRegion, bold, buildPathLUT, calculateSequenceTimeline, checkNodeResultCache, code, collectNodeOps, color, compositorToProgram, computeAnchorPivotOffset, computeCarrierContinuity, computeGridLayout, computeLayout, computeLayoutSync, computeLineLeadingDisplacement, computeRangeSelectorWeight, computeStaggerDelay, computeStrokeRect, computeVideoCropRenderProps, computed, cosineSignal, createOutputItemSchema, createVirtualMedia, dataTypeColors, describeGpu, deserializeSignalData, deterministicWigglyNoise, distanceToCurveParameter, editTrackedRegion, effectFactories, effectMeta, ellipseToCubicBeziers, encodeStereoWav, ensureDevice, evaluateAnimationAtFrame, evaluateCubicBezier, evaluateCubicBezierDerivative, evaluateExpressionSelector, evaluateMarqueeOffset, evaluateSelectorCombination, evaluateSkewMatrix, evaluateSpringProgress, evaluateTrackAtFrame, evaluateTypewriterState, evaluateVolumetricFormation, extractSvgDimensions, findSourceAsset, formatHex, formatQaReport, frameArraySignal, frameSignal, generateArcLengthLUT, generateId, generatePathSegments, getActiveMediaMetadata, getFileDataMetadata, getFingerprint, getLeafMediaType, getMediaType, getRenderFingerprint, getScramblePool, getShuffledOrder, gradientStopsToOklab, hasOnlySingleSource, hoistMattes, inputStore, interpolate, isCssGradient, isEqual, isSignal, isVirtualMediaData, italic, limitGradientStops, lintComposition, loadFBX, loadModel3D, loadOBJ, lutStore, mapBlendModeToSkia, mark, measureSpring, measureText, measureTextAsync, mergeAnimationTracks, mixAudioTracks, mixColors, mixSfxInto, normalizeColorStops, normalizeTextSpans, oklabToRgb, parseColorToRgb, parseCssColor, parseCssGradient, parseFBX, parseMTL, parseMarkup, parseOBJ, parseSvgPathToCubicBeziers, pinNodeToLandmark, pinNodeToObject, preloadCompositionFonts, preloadFont, programmaticSignal, progressSignal, registerSignalDependency, renderFrameGrid, renderSemaphore, renderSfx, reportRenderDiagnostic, requiresIsolation, resetRenderCaches, resolveBoolean, resolveEnvironment, resolveMediaMimeType, resolveNumber, resolveParam, resolveSamplePoints, resolveString, rgbToOklab, rich, sampleAudioSpectrumScale, sampleColorStops, sampleCurveGeometry, samplePathChainGeometry, section, serializeSignalData, shaderStore, signal, signalBuilder, signalRegistry, sineSignal, size, softLimit, span, spring, springCalculation, stampResult, startPreview, sub, sup, takeRenderDiagnostics, textureCache, timeSignal, updateClockSignals, waveToCubicBeziers };
6258
+ export { AETextAnimatorSchema, AdvancedTextAnimatorBuilder, AdvancedTextAnimatorSchema, AnchorGroupingSchema, AnchorPresetSchema, AnimatableGlyphPropsSchema, AnimationTypeSchema, AnyOutputUnionSchema, ApplyLUT, Ascii, AudioCompressor, AudioDelay, AudioExtractorSignalDataSchema, AudioFade, AudioLatentEngine, AudioLatentTrackCache, AudioMeshDeformPipeline, AudioNoiseGate, AudioParametricEq, AudioReverb, AudioSignal, AudioSignalExtractor, AudioSpectrumTypographySchema, BaseMediaOperationPropsSchema, BaseVideoLayerPropsSchema, BloomConfigSchema, Blur, BoxNodeSchema, CAPTION_LAYER_DEFAULTS, COCO17_BONES, COCO17_KEYPOINTS, COCO17_KEYPOINT_NAMES, COCO_CLASSES, COMPOSITE_OPERATIONS, COMPOSITOR_DEFAULTS, CRT, Camera3D, CameraAnimation, CameraNodeSchema, CameraParallax3D, CannyComputePipeline, CarrierHandoffConfigSchema, ChannelMerger, ChannelSplitter, ChromaticGlitchConfigSchema, ClipVision, Color, ColorBalance, ColorKey, ColorStopSchema, Composition, CompositorProgramSchema, ConfigHandleSchema, ConfigSchemaRegistry, Contour, ControlNetMultiplexer, CornerPin, Crop, CubicBezierSegmentSchema, Curves, CustomEffect, DATA_TYPE_EXTENSIONS, DEFAULT_CHART_COLORS, DEFAULT_DURATION_MS, DEFAULT_FPS, DEFAULT_MEDIA_DIMENSION, DataType, DataTypeVal, DataTypes, Datamosh, DepthNormalsComputePipeline, DepthOfField, DisplacementMap, Dither, DynamicStrokePropertiesSchema, ENVIRONMENT_PRESETS, Easing, Effect, EffectPipeline, EnhancedTextNodeSchema, EnvironmentFogSchema, EnvironmentPresetSchema, ExportResultSchema, ExpressionSelectorSchema, ExtendedGlyphPropertiesSchema, ExtendedLayerSchema, ExtractLUT, FileAssetSchema, FileDataSchema, FilmGrain, FlexNodeSchema, Flip, FontManager, GeneratorSignalDataSchema, GlassPipeline, GlobalCompositeOperation, GlyphAnchorGroupingSchema, GlyphAnchorPointSchema, Gooey, Gradient, GradientMap, HalftoneScreen, HandleTypeVal, HeadlessMediaRenderer, HeadlessWebGPURenderer, HighPass, Iridescence, JsonValueSchema, Kaleidoscope, KenBurns, KineticMarqueeConfigSchema, LIGHT_UNIFORM_SIZE_BYTES, Layer, Layer3D, LayerAnimation, LayerStyle, LayoutNodeSchema, Levels, Light, Light3D, LightNodeSchema, LightTypeSchema, Lighting, LineSpacingDynamicsSchema, Liquify, LongShadowConfigSchema, MAX_GRADIENT_STOPS, MAX_LIGHTS, MIME_TYPES, MaskMath, MaterialTypeSchema, Matrix4Math, MatteModeSchema, Media, MediaMetadataSchema, MediaNodeSchema, MediaOperationSchema, MediaSourceSchema, MeshWarp, Model3DNodeSchema, ModerationError, ModerationUnrefundableError, Modulate, MotionBlur, MotionBlurPipeline, MultiOutputGenericSchema, NodeMetadataSchema, NodeResultSchema, NodeVisualConfigSchema, NoiseGenerator, OpArt, OpticalFlowComputePipeline, OutputItemSchema, PBRGlass, Paint, Painterly, ParticleDissolveConfigSchema, Particles, PatchHeal, Path3D, PersonTrack, Physics, PhysicsBody2D, PhysicsBody3D, PhysicsWorld2D, PhysicsWorld3D, Pixelate, PoseSkeletonRenderer, Posterize, ProceduralVFX, ProgrammaticSignal, RGBSplit, RefineEdge, RefractionCaustics3D, Relight3D, Renderer2D, Renderer3D, ResizerScaler, Rotate, SSAO, SSAOPipeline, Scene, SceneDefinitionSchema, SceneTransitionTypeSchema, SegmentationTexturePool, SelectiveColor, SelectorBasedOnSchema, SelectorModeSchema, SelectorShapeSchema, SelectorUnitsSchema, Sequence, ShadowPipeline, ShadowsHighlights, ShapeNodeSchema, Signal, SignalChannelMetaSchema, SignalDataSchema, SignalGateDataSchema, SignalMathDataSchema, SignalStatsSchema, SingleOutputGenericSchema, SkewPropertiesSchema, SlugFontCache, SlugPipeline, SourceOperationSchema, Spatial3DPropertiesSchema, SpatialLandmarkTransformer, SpringPhysicsSchema, StereoPanning, Styles, TEXT_LAYER_DEFAULTS, TemporalDeflicker, TemporalDeflickerPipeline, TemporalObjectTracker, TensorPipeline, TextAnchorConfigSchema, TextAnimator, TextAnimatorBuilder, TextAnimatorSchema, TextCursorConfigSchema, TextCursorStyleSchema, TextNodeSchema, TextOperationSchema, TextPathBuilder, TextPathOptionsSchema, TextPathSourceSchema, TextRangeSelectorSchema, TextScrambleConfigSchema, TextSelectorSchema, TextSignalSelectorSchema, TextSpanMarkSchema, TextSpanSchema, TextWigglySelectorSchema, TileOffset, TimelineSegmentSchema, TimelineTransformSchema, ToneMappingSchema, Toon, Trails, Transition, TransitionSchema, TransitionTypeSchema, TypewriterAnimatorSchema, TypingCadenceSchema, UnsharpMask, VariableFontAxesSchema, Vec2Schema, Vector3Math, VideoAnimationSchema, VideoLayerTypeSchema, VideoSpatialPropsSchema, VideoStylePropsSchema, VideoTextPropsSchema, VideoTimingPropsSchema, Vignette, VirtualMediaDataSchema, Vision, VisionBundle, VisionNode, VisionRunner, VolumetricFormationConfigSchema, VolumetricFormationModeSchema, accent, analyzeSequence, appendOperation, applyStaggerToChildren, bezier, blurRegion, bold, buildPathLUT, calculateSequenceTimeline, checkNodeResultCache, code, collectNodeOps, color, compositorToProgram, computeAnchorPivotOffset, computeCarrierContinuity, computeGridLayout, computeLayout, computeLayoutSync, computeLineLeadingDisplacement, computeRangeSelectorWeight, computeStaggerDelay, computeStrokeRect, computeVideoCropRenderProps, computed, cosineSignal, createOutputItemSchema, createVirtualMedia, dataTypeColors, describeGpu, deserializeSignalData, deterministicWigglyNoise, distanceToCurveParameter, editTrackedRegion, effectFactories, effectMeta, ellipseToCubicBeziers, encodeStereoWav, ensureDevice, evaluateAnimationAtFrame, evaluateCubicBezier, evaluateCubicBezierDerivative, evaluateExpressionSelector, evaluateMarqueeOffset, evaluateSelectorCombination, evaluateSkewMatrix, evaluateSpringProgress, evaluateTrackAtFrame, evaluateTypewriterState, evaluateVolumetricFormation, extractSvgDimensions, findSourceAsset, formatHex, formatQaReport, frameArraySignal, frameSignal, generateArcLengthLUT, generateId, generatePathSegments, getActiveMediaMetadata, getFileDataMetadata, getFingerprint, getLeafMediaType, getMediaType, getRenderFingerprint, getScramblePool, getShuffledOrder, gradientStopsToOklab, hasOnlySingleSource, hoistMattes, inputStore, interpolate, isCssGradient, isEqual, isSignal, isVirtualMediaData, italic, limitGradientStops, lintComposition, loadFBX, loadModel3D, loadOBJ, lutStore, mapBlendModeToSkia, mark, measureSpring, measureText, measureTextAsync, mergeAnimationTracks, mixAudioTracks, mixColors, mixSfxInto, normalizeColorStops, normalizeTextSpans, oklabToRgb, parseColorToRgb, parseCssColor, parseCssGradient, parseFBX, parseMTL, parseMarkup, parseOBJ, parseSvgPathToCubicBeziers, pinNodeToLandmark, pinNodeToObject, preloadCompositionFonts, preloadFont, programmaticSignal, progressSignal, registerSignalDependency, renderFrameGrid, renderSemaphore, renderSfx, reportRenderDiagnostic, requiresIsolation, resetRenderCaches, resolveBoolean, resolveEnvironment, resolveMediaMimeType, resolveNumber, resolveParam, resolveSamplePoints, resolveString, rgbToOklab, rich, sampleAudioSpectrumScale, sampleColorStops, sampleCurveGeometry, samplePathChainGeometry, section, serializeSignalData, shaderStore, signal, signalBuilder, signalRegistry, sineSignal, size, softLimit, span, spring, springCalculation, stampResult, startPreview, sub, sup, takeRenderDiagnostics, textureCache, timeSignal, updateClockSignals, waveToCubicBeziers };
3220
6259
  //# sourceMappingURL=index.mjs.map