framefields 2.13.1 → 2.15.0

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 (339) hide show
  1. package/NOTICE.md +5 -1
  2. package/dist/audio/index.d.mts +5 -5
  3. package/dist/audio/index.mjs +10 -10
  4. package/dist/{audio-DIvi6hTD.mjs → audio-6TfPlfl4.mjs} +3 -3
  5. package/dist/{audio-DIvi6hTD.mjs.map → audio-6TfPlfl4.mjs.map} +1 -1
  6. package/dist/{audio-C4B9p_yq.d.mts → audio-7oqTUi4G.d.mts} +3 -3
  7. package/dist/{audio-C4B9p_yq.d.mts.map → audio-7oqTUi4G.d.mts.map} +1 -1
  8. package/dist/cli/check-worker.mjs +44 -44
  9. package/dist/cli.mjs +1 -1
  10. package/dist/cloud/index.d.mts.map +1 -1
  11. package/dist/cloud/index.mjs +1 -1
  12. package/dist/{cloud-Cj1TIme8.mjs → cloud-jnk1hPYf.mjs} +2 -2
  13. package/dist/{cloud-Cj1TIme8.mjs.map → cloud-jnk1hPYf.mjs.map} +1 -1
  14. package/dist/components/index.d.mts +13 -13
  15. package/dist/components/index.mjs +43 -43
  16. package/dist/{dist-Kbf-JTry.mjs → dist-BtI6ukB5.mjs} +2 -2
  17. package/dist/{dist-Kbf-JTry.mjs.map → dist-BtI6ukB5.mjs.map} +1 -1
  18. package/dist/{dist-CCrYOkcc.mjs → dist-COOpgG9G.mjs} +4 -3
  19. package/dist/{dist-CCrYOkcc.mjs.map → dist-COOpgG9G.mjs.map} +1 -1
  20. package/dist/{dist-DtPPPsZV.mjs → dist-XqlFM2a8.mjs} +14063 -5308
  21. package/dist/dist-XqlFM2a8.mjs.map +1 -0
  22. package/dist/{dist-CiTgmfUw.mjs → dist-f1zkl69f.mjs} +4 -4
  23. package/dist/dist-f1zkl69f.mjs.map +1 -0
  24. package/dist/{dist-B_rSWeOz.mjs → dist-umQOWz0a.mjs} +1 -1
  25. package/dist/effects/index.d.mts +5 -5
  26. package/dist/effects/index.mjs +35 -35
  27. package/dist/{effects-B-L3rLs6.mjs → effects-DlRMovU5.mjs} +2 -2
  28. package/dist/{effects-B-L3rLs6.mjs.map → effects-DlRMovU5.mjs.map} +1 -1
  29. package/dist/fonts/index.d.mts +1 -1
  30. package/dist/fonts/index.mjs +2 -2
  31. package/dist/{fonts-k5ll8NTE.mjs → fonts-BWYcXjyK.mjs} +3 -3
  32. package/dist/fonts-BWYcXjyK.mjs.map +1 -0
  33. package/dist/{gpu-D2HT3KcE.mjs → gpu-CH1PdM4T.mjs} +2 -2
  34. package/dist/{gpu-D2HT3KcE.mjs.map → gpu-CH1PdM4T.mjs.map} +1 -1
  35. package/dist/{index-rtCXNxGO.d.mts → index-BHTycml5.d.mts} +2 -2
  36. package/dist/{index-rtCXNxGO.d.mts.map → index-BHTycml5.d.mts.map} +1 -1
  37. package/dist/{index-BFTtXosj.d.mts → index-BVd6nXd5.d.mts} +2 -2
  38. package/dist/{index-BFTtXosj.d.mts.map → index-BVd6nXd5.d.mts.map} +1 -1
  39. package/dist/{index-ByhlTwxh.d.mts → index-BcxxxwhV.d.mts} +5 -5
  40. package/dist/{index-ByhlTwxh.d.mts.map → index-BcxxxwhV.d.mts.map} +1 -1
  41. package/dist/{index-CnZhBlob.d.mts → index-BnB_Ou2y.d.mts} +2 -2
  42. package/dist/index-BnB_Ou2y.d.mts.map +1 -0
  43. package/dist/{index-a6JrbAK0.d.mts → index-C-V6CAhP.d.mts} +32 -2
  44. package/dist/index-C-V6CAhP.d.mts.map +1 -0
  45. package/dist/{index-DBh3WphX.d.mts → index-CMhkkc56.d.mts} +44 -12
  46. package/dist/index-CMhkkc56.d.mts.map +1 -0
  47. package/dist/{index-BGlaws7-.d.mts → index-CYVpYGM-.d.mts} +3 -3
  48. package/dist/{index-BGlaws7-.d.mts.map → index-CYVpYGM-.d.mts.map} +1 -1
  49. package/dist/{index-DQ1U3HC3.d.mts → index-DhL7ckvs.d.mts} +7 -7
  50. package/dist/index-DhL7ckvs.d.mts.map +1 -0
  51. package/dist/{index-CtKUQ2VG.d.mts → index-DkAjKnhW.d.mts} +1487 -533
  52. package/dist/index-DkAjKnhW.d.mts.map +1 -0
  53. package/dist/{index-B08eSpaI.d.mts → index-RILu3ULT.d.mts} +2 -2
  54. package/dist/{index-B08eSpaI.d.mts.map → index-RILu3ULT.d.mts.map} +1 -1
  55. package/dist/{index-C5sgRLlG.d.mts → index-TCtdSXd7.d.mts} +3 -1
  56. package/dist/index-TCtdSXd7.d.mts.map +1 -0
  57. package/dist/{index-C2yaponf.d.mts → index-s2qQ8ifZ.d.mts} +911 -57
  58. package/dist/index-s2qQ8ifZ.d.mts.map +1 -0
  59. package/dist/index.d.mts +15 -15
  60. package/dist/index.mjs +52 -52
  61. package/dist/preview/index.d.mts +5 -5
  62. package/dist/preview/index.mjs +10 -10
  63. package/dist/preview-BeGF1Bb1.mjs +1002 -0
  64. package/dist/preview-BeGF1Bb1.mjs.map +1 -0
  65. package/dist/preview-engine/audio.mjs +1 -1
  66. package/dist/preview-engine/{chunk-64L4GUOF.mjs → chunk-4F3DG6YB.mjs} +2 -2
  67. package/dist/preview-engine/chunk-A2OTOW3B.mjs +4694 -0
  68. package/dist/preview-engine/chunk-BR56TQBP.mjs +5 -0
  69. package/dist/preview-engine/{chunk-ADLIF544.mjs → chunk-H2XKXXAU.mjs} +1 -1
  70. package/dist/preview-engine/chunk-NDUODAY2.mjs +3 -0
  71. package/dist/preview-engine/{chunk-FZ4RD7HV.mjs → chunk-QAQJSWUT.mjs} +1 -1
  72. package/dist/preview-engine/chunk-SWRGQTVC.mjs +138 -0
  73. package/dist/preview-engine/{chunk-52X7SURQ.mjs → chunk-TEA3GVBJ.mjs} +1 -1
  74. package/dist/preview-engine/chunk-VM2ZBPLM.mjs +644 -0
  75. package/dist/preview-engine/{chunk-UBY2UYEL.mjs → chunk-XSHNQJ7L.mjs} +1 -1
  76. package/dist/preview-engine/components.mjs +1 -1
  77. package/dist/preview-engine/effects.mjs +1 -1
  78. package/dist/preview-engine/fonts.mjs +1 -1
  79. package/dist/preview-engine/framefields.mjs +1 -1
  80. package/dist/preview-engine/player.mjs +2 -2
  81. package/dist/preview-engine/{renderers-DU7KPFVV.mjs → renderers-6C7NWWDX.mjs} +1 -1
  82. package/dist/preview-engine/renderers-HHVGNMSJ.mjs +206 -0
  83. package/dist/preview-engine/{src-YXNX4MLK.mjs → src-RCNEKIRP.mjs} +1 -1
  84. package/dist/preview-page/index.html +19 -0
  85. package/dist/preview-page/main.css +1 -0
  86. package/dist/preview-page/main.js +327 -0
  87. package/dist/{program-BfiB9ttP.mjs → program-CMigyfso.mjs} +919 -58
  88. package/dist/program-CMigyfso.mjs.map +1 -0
  89. package/dist/renderer/index.d.mts +4 -4
  90. package/dist/renderer/index.mjs +2 -2
  91. package/dist/{renderer-CoC64eam.mjs → renderer-0GMEL_Zi.mjs} +3 -3
  92. package/dist/{renderer-CoC64eam.mjs.map → renderer-0GMEL_Zi.mjs.map} +1 -1
  93. package/dist/{renderer-CSu_vYPn.mjs → renderer-3Wv2ZBJG.mjs} +3 -3
  94. package/dist/{renderer-CSu_vYPn.mjs.map → renderer-3Wv2ZBJG.mjs.map} +1 -1
  95. package/dist/{renderer-Dv_iRIyx.mjs → renderer-4nXkaAWu.mjs} +1280 -285
  96. package/dist/renderer-4nXkaAWu.mjs.map +1 -0
  97. package/dist/{renderer-TfeohPxt.mjs → renderer-6SnfLXeg.mjs} +3 -3
  98. package/dist/{renderer-TfeohPxt.mjs.map → renderer-6SnfLXeg.mjs.map} +1 -1
  99. package/dist/{renderer-D0xM67cK.mjs → renderer-8gHw3O0P.mjs} +2 -2
  100. package/dist/{renderer-D0xM67cK.mjs.map → renderer-8gHw3O0P.mjs.map} +1 -1
  101. package/dist/{renderer-C64_B8It.mjs → renderer-AOBglZHC.mjs} +2 -2
  102. package/dist/{renderer-B10HDC13.mjs → renderer-B0bSARK3.mjs} +3 -3
  103. package/dist/{renderer-B10HDC13.mjs.map → renderer-B0bSARK3.mjs.map} +1 -1
  104. package/dist/{renderer-DWYmJSrl.mjs → renderer-B2_tuRfl.mjs} +2 -2
  105. package/dist/{renderer-DWYmJSrl.mjs.map → renderer-B2_tuRfl.mjs.map} +1 -1
  106. package/dist/{renderer-mDBoz0zT.mjs → renderer-B82FhkEr.mjs} +3 -3
  107. package/dist/{renderer-mDBoz0zT.mjs.map → renderer-B82FhkEr.mjs.map} +1 -1
  108. package/dist/{renderer-DYeNNc_G.mjs → renderer-B9lzA0PY.mjs} +3 -3
  109. package/dist/{renderer-DYeNNc_G.mjs.map → renderer-B9lzA0PY.mjs.map} +1 -1
  110. package/dist/{renderer-BGchUBW_.mjs → renderer-BBSIWSry.mjs} +2 -2
  111. package/dist/{renderer-BGchUBW_.mjs.map → renderer-BBSIWSry.mjs.map} +1 -1
  112. package/dist/{renderer-GIlQ9lZq.mjs → renderer-BEKDMxbi.mjs} +2 -2
  113. package/dist/{renderer-GIlQ9lZq.mjs.map → renderer-BEKDMxbi.mjs.map} +1 -1
  114. package/dist/renderer-BERGAxqA.mjs +5 -0
  115. package/dist/{renderer-Bw0O--gW.mjs → renderer-BF960HY8.mjs} +3 -3
  116. package/dist/{renderer-Bw0O--gW.mjs.map → renderer-BF960HY8.mjs.map} +1 -1
  117. package/dist/{renderer-BhcTYhaP.mjs → renderer-BFwyVxCu.mjs} +3 -3
  118. package/dist/{renderer-BhcTYhaP.mjs.map → renderer-BFwyVxCu.mjs.map} +1 -1
  119. package/dist/{renderer-DYlx7VHo.mjs → renderer-BNiwcI3-.mjs} +2 -2
  120. package/dist/{renderer-DYlx7VHo.mjs.map → renderer-BNiwcI3-.mjs.map} +1 -1
  121. package/dist/{renderer-B3_GddgJ.mjs → renderer-BPbVb2Q4.mjs} +2 -2
  122. package/dist/{renderer-B3_GddgJ.mjs.map → renderer-BPbVb2Q4.mjs.map} +1 -1
  123. package/dist/renderer-BQ_YkBMt.mjs +6 -0
  124. package/dist/{renderer-Y1kjtOto.mjs → renderer-BUWxlA8T.mjs} +3 -3
  125. package/dist/{renderer-Y1kjtOto.mjs.map → renderer-BUWxlA8T.mjs.map} +1 -1
  126. package/dist/renderer-BW0Tjsv9.mjs +5 -0
  127. package/dist/{renderer-DtFZbE1j.mjs → renderer-BX8liu-e.mjs} +2 -2
  128. package/dist/{renderer-BOlHW3Mi.mjs → renderer-BXIwDAr_.mjs} +2 -2
  129. package/dist/{renderer-BOlHW3Mi.mjs.map → renderer-BXIwDAr_.mjs.map} +1 -1
  130. package/dist/{renderer-DzON3wDZ.mjs → renderer-B_Hy1W-g.mjs} +3 -3
  131. package/dist/{renderer-DzON3wDZ.mjs.map → renderer-B_Hy1W-g.mjs.map} +1 -1
  132. package/dist/{renderer-BM19iK8v.mjs → renderer-Bb6cvSgh.mjs} +2 -2
  133. package/dist/{renderer-BM19iK8v.mjs.map → renderer-Bb6cvSgh.mjs.map} +1 -1
  134. package/dist/{renderer-D0h1hTOo.mjs → renderer-BdppwWC9.mjs} +2 -2
  135. package/dist/{renderer-D0h1hTOo.mjs.map → renderer-BdppwWC9.mjs.map} +1 -1
  136. package/dist/{renderer-BTwuM9u-.mjs → renderer-Bhc24HVe.mjs} +3 -3
  137. package/dist/{renderer-BTwuM9u-.mjs.map → renderer-Bhc24HVe.mjs.map} +1 -1
  138. package/dist/{renderer-BZX932Lj.mjs → renderer-BiNA2wF0.mjs} +2 -2
  139. package/dist/{renderer-BZX932Lj.mjs.map → renderer-BiNA2wF0.mjs.map} +1 -1
  140. package/dist/{renderer-CkTehyRX.mjs → renderer-BmoBgTp5.mjs} +3 -3
  141. package/dist/{renderer-CkTehyRX.mjs.map → renderer-BmoBgTp5.mjs.map} +1 -1
  142. package/dist/{renderer-B3un4Pdi.mjs → renderer-BmqFmCWS.mjs} +3 -3
  143. package/dist/{renderer-B3un4Pdi.mjs.map → renderer-BmqFmCWS.mjs.map} +1 -1
  144. package/dist/{renderer-CHCRcCKw.mjs → renderer-BnVwAObV.mjs} +2 -2
  145. package/dist/{renderer-CHCRcCKw.mjs.map → renderer-BnVwAObV.mjs.map} +1 -1
  146. package/dist/{renderer-Cv9CKKWG.mjs → renderer-BxttZHme.mjs} +2 -2
  147. package/dist/{renderer-Cv9CKKWG.mjs.map → renderer-BxttZHme.mjs.map} +1 -1
  148. package/dist/renderer-BzyPdUD1.mjs +5 -0
  149. package/dist/renderer-C0hM-mtY.mjs +5 -0
  150. package/dist/renderer-C6cyUTvk.mjs +5 -0
  151. package/dist/{renderer-B6bK9rXm.mjs → renderer-C8E4XsSg.mjs} +2 -2
  152. package/dist/{renderer-B6bK9rXm.mjs.map → renderer-C8E4XsSg.mjs.map} +1 -1
  153. package/dist/renderer-C8zY3pzk.mjs +5 -0
  154. package/dist/{renderer-4nsuReW2.mjs → renderer-C9U-LY50.mjs} +3 -3
  155. package/dist/{renderer-4nsuReW2.mjs.map → renderer-C9U-LY50.mjs.map} +1 -1
  156. package/dist/{renderer-BvBqTAtk.mjs → renderer-CB2JVu5x.mjs} +3 -3
  157. package/dist/{renderer-BvBqTAtk.mjs.map → renderer-CB2JVu5x.mjs.map} +1 -1
  158. package/dist/{renderer-CQ4h8n7p.mjs → renderer-CC4YBJ8Z.mjs} +3 -3
  159. package/dist/{renderer-CQ4h8n7p.mjs.map → renderer-CC4YBJ8Z.mjs.map} +1 -1
  160. package/dist/renderer-CEkSOyKu.mjs +5 -0
  161. package/dist/{renderer-zLi2qFGT.mjs → renderer-CIycc5O-.mjs} +2 -2
  162. package/dist/{renderer-zLi2qFGT.mjs.map → renderer-CIycc5O-.mjs.map} +1 -1
  163. package/dist/renderer-CJYtfa4x.mjs +5 -0
  164. package/dist/{renderer-yNWYqvvq.mjs → renderer-CJraQlV-.mjs} +2 -2
  165. package/dist/{renderer-yNWYqvvq.mjs.map → renderer-CJraQlV-.mjs.map} +1 -1
  166. package/dist/renderer-CKMtHGZh.mjs +5 -0
  167. package/dist/renderer-CLzicoiy.mjs +5 -0
  168. package/dist/renderer-CM2A4BHd.mjs +5 -0
  169. package/dist/{renderer-BrEeUw7T.mjs → renderer-COWGWtob.mjs} +2 -2
  170. package/dist/{renderer-BrEeUw7T.mjs.map → renderer-COWGWtob.mjs.map} +1 -1
  171. package/dist/{renderer-uER8kn7f.mjs → renderer-COxG2XGf.mjs} +2 -2
  172. package/dist/{renderer-uER8kn7f.mjs.map → renderer-COxG2XGf.mjs.map} +1 -1
  173. package/dist/{renderer-C4hd6Cqi.mjs → renderer-CQDCIsQm.mjs} +2 -2
  174. package/dist/{renderer-C4hd6Cqi.mjs.map → renderer-CQDCIsQm.mjs.map} +1 -1
  175. package/dist/{renderer-Cfx_FCSf.mjs → renderer-CRUeag8i.mjs} +3 -3
  176. package/dist/{renderer-Cfx_FCSf.mjs.map → renderer-CRUeag8i.mjs.map} +1 -1
  177. package/dist/{renderer-CXrnzihz.mjs → renderer-CWVput06.mjs} +3 -3
  178. package/dist/{renderer-CXrnzihz.mjs.map → renderer-CWVput06.mjs.map} +1 -1
  179. package/dist/renderer-CZlHjcxr.mjs +5 -0
  180. package/dist/{renderer-BmyFfvVA.mjs → renderer-CbbnBLOB.mjs} +3 -3
  181. package/dist/{renderer-BmyFfvVA.mjs.map → renderer-CbbnBLOB.mjs.map} +1 -1
  182. package/dist/renderer-CbimvSU8.mjs +5 -0
  183. package/dist/renderer-Ccvc63yd.mjs +5 -0
  184. package/dist/renderer-Cdp-SGfq.mjs +5 -0
  185. package/dist/renderer-CeTcSs3e.mjs +5 -0
  186. package/dist/{renderer-_J9JcCMR.mjs → renderer-CfLZein2.mjs} +3 -3
  187. package/dist/{renderer-_J9JcCMR.mjs.map → renderer-CfLZein2.mjs.map} +1 -1
  188. package/dist/{renderer-D-mX1EVA.mjs → renderer-Ch-q1O-q.mjs} +3 -3
  189. package/dist/{renderer-D-mX1EVA.mjs.map → renderer-Ch-q1O-q.mjs.map} +1 -1
  190. package/dist/{renderer-uzU6dsdR.mjs → renderer-Ch5JvJWl.mjs} +2 -2
  191. package/dist/{renderer-uzU6dsdR.mjs.map → renderer-Ch5JvJWl.mjs.map} +1 -1
  192. package/dist/{renderer-BZMh2io2.mjs → renderer-ChtEzq-R.mjs} +2 -2
  193. package/dist/{renderer-BZMh2io2.mjs.map → renderer-ChtEzq-R.mjs.map} +1 -1
  194. package/dist/{renderer-B2IUPjhw.mjs → renderer-Cj9nTC5l.mjs} +3 -3
  195. package/dist/{renderer-B2IUPjhw.mjs.map → renderer-Cj9nTC5l.mjs.map} +1 -1
  196. package/dist/{renderer-CdXBRdFf.mjs → renderer-CqT8HsSS.mjs} +2 -2
  197. package/dist/{renderer-CdXBRdFf.mjs.map → renderer-CqT8HsSS.mjs.map} +1 -1
  198. package/dist/{renderer-CldjJmRR.mjs → renderer-CuQjMhdV.mjs} +2 -2
  199. package/dist/renderer-CvNuu52U.mjs +5 -0
  200. package/dist/renderer-CwciC0oI.mjs +5 -0
  201. package/dist/renderer-CysLUbIr.mjs +5 -0
  202. package/dist/{renderer-BsrKj6Td.mjs → renderer-Cz30EVws.mjs} +2 -2
  203. package/dist/{renderer-BsrKj6Td.mjs.map → renderer-Cz30EVws.mjs.map} +1 -1
  204. package/dist/renderer-D3A22Vxb.mjs +5 -0
  205. package/dist/renderer-D5SY9EmA.mjs +5 -0
  206. package/dist/renderer-D8h3ZvaE.mjs +5 -0
  207. package/dist/renderer-DE-B6N9n.mjs +5 -0
  208. package/dist/renderer-DETZTI7t.mjs +5 -0
  209. package/dist/{renderer-CC22Djgi.mjs → renderer-DHoX-5U_.mjs} +3 -3
  210. package/dist/{renderer-CC22Djgi.mjs.map → renderer-DHoX-5U_.mjs.map} +1 -1
  211. package/dist/{renderer-HKv5cBdp.mjs → renderer-DOkm0Ycd.mjs} +2 -2
  212. package/dist/{renderer-HKv5cBdp.mjs.map → renderer-DOkm0Ycd.mjs.map} +1 -1
  213. package/dist/{renderer-fG8Jy8Rx.d.mts → renderer-DU3f6ZrS.d.mts} +2 -2
  214. package/dist/{renderer-fG8Jy8Rx.d.mts.map → renderer-DU3f6ZrS.d.mts.map} +1 -1
  215. package/dist/{renderer-C98XwEIr.mjs → renderer-DUzv-shq.mjs} +2 -2
  216. package/dist/{renderer-C98XwEIr.mjs.map → renderer-DUzv-shq.mjs.map} +1 -1
  217. package/dist/renderer-DWnDj0IM.mjs +5 -0
  218. package/dist/renderer-DcGUIbQF.mjs +5 -0
  219. package/dist/renderer-Dfq6FoNO.mjs +5 -0
  220. package/dist/renderer-DhasXW6S.mjs +3 -0
  221. package/dist/{renderer-BEuXJY-C.mjs → renderer-DhnOWnEA.mjs} +3 -3
  222. package/dist/{renderer-BEuXJY-C.mjs.map → renderer-DhnOWnEA.mjs.map} +1 -1
  223. package/dist/{renderer-BIKkxw_Z.mjs → renderer-Dhy1XHzz.mjs} +3 -3
  224. package/dist/{renderer-BIKkxw_Z.mjs.map → renderer-Dhy1XHzz.mjs.map} +1 -1
  225. package/dist/renderer-DjCvpsV_.mjs +5 -0
  226. package/dist/{renderer-pn52dzZz.mjs → renderer-DjJshz9Y.mjs} +2 -2
  227. package/dist/{renderer-pn52dzZz.mjs.map → renderer-DjJshz9Y.mjs.map} +1 -1
  228. package/dist/{renderer-DhGZ41hQ.mjs → renderer-DmTUIdus.mjs} +3 -3
  229. package/dist/{renderer-DhGZ41hQ.mjs.map → renderer-DmTUIdus.mjs.map} +1 -1
  230. package/dist/{renderer-D_m6Qbsi.mjs → renderer-Dq7AioJa.mjs} +2 -2
  231. package/dist/{renderer-D_m6Qbsi.mjs.map → renderer-Dq7AioJa.mjs.map} +1 -1
  232. package/dist/renderer-DrAaM6JD.mjs +5 -0
  233. package/dist/{renderer-D-GWBoVT.mjs → renderer-Dt4sqNEu.mjs} +2 -2
  234. package/dist/{renderer-D-GWBoVT.mjs.map → renderer-Dt4sqNEu.mjs.map} +1 -1
  235. package/dist/{renderer-DCrKEVjb.mjs → renderer-Dtcs4idV.mjs} +3 -3
  236. package/dist/{renderer-DCrKEVjb.mjs.map → renderer-Dtcs4idV.mjs.map} +1 -1
  237. package/dist/renderer-Dxlv8LYm.mjs +5 -0
  238. package/dist/{renderer-CO9vE3sd.mjs → renderer-Gj8SrE2W.mjs} +2 -2
  239. package/dist/{renderer-CO9vE3sd.mjs.map → renderer-Gj8SrE2W.mjs.map} +1 -1
  240. package/dist/{renderer-DvHi_wXE.mjs → renderer-KfnXDJS0.mjs} +3 -3
  241. package/dist/{renderer-DvHi_wXE.mjs.map → renderer-KfnXDJS0.mjs.map} +1 -1
  242. package/dist/{renderer-7xQmXXMH.mjs → renderer-MXVlg4p5.mjs} +3 -3
  243. package/dist/{renderer-7xQmXXMH.mjs.map → renderer-MXVlg4p5.mjs.map} +1 -1
  244. package/dist/{renderer-YONlI6W-.mjs → renderer-N2b6QZ1E.mjs} +3 -3
  245. package/dist/{renderer-YONlI6W-.mjs.map → renderer-N2b6QZ1E.mjs.map} +1 -1
  246. package/dist/renderer-Pb43OO2t.mjs +5 -0
  247. package/dist/{renderer-DNynPM6X.mjs → renderer-Q7gDzm8c.mjs} +2 -2
  248. package/dist/{renderer-DNynPM6X.mjs.map → renderer-Q7gDzm8c.mjs.map} +1 -1
  249. package/dist/{renderer-BEhZiOT4.mjs → renderer-RCiANtRV.mjs} +2 -2
  250. package/dist/{renderer-BEhZiOT4.mjs.map → renderer-RCiANtRV.mjs.map} +1 -1
  251. package/dist/{renderer-Dm57W73p.mjs → renderer-Sig9nZcI.mjs} +2 -2
  252. package/dist/renderer-VQbm-cGr.mjs +5 -0
  253. package/dist/{renderer-DiZkZ0Pr.mjs → renderer-fabBgwQX.mjs} +3 -3
  254. package/dist/{renderer-DiZkZ0Pr.mjs.map → renderer-fabBgwQX.mjs.map} +1 -1
  255. package/dist/{renderer-Bw-_GZVw.mjs → renderer-g-0PCNoo.mjs} +3 -3
  256. package/dist/{renderer-Bw-_GZVw.mjs.map → renderer-g-0PCNoo.mjs.map} +1 -1
  257. package/dist/{renderer-QbSrnPZU.mjs → renderer-gmHKIbKI.mjs} +3 -3
  258. package/dist/{renderer-QbSrnPZU.mjs.map → renderer-gmHKIbKI.mjs.map} +1 -1
  259. package/dist/{renderer-CU6WT5jW.mjs → renderer-kVZwiRoK.mjs} +3 -3
  260. package/dist/{renderer-CU6WT5jW.mjs.map → renderer-kVZwiRoK.mjs.map} +1 -1
  261. package/dist/renderer-oPMypDM1.mjs +5 -0
  262. package/dist/{renderer-CRhEGqW4.mjs → renderer-p7tgxP-A.mjs} +3 -3
  263. package/dist/{renderer-CRhEGqW4.mjs.map → renderer-p7tgxP-A.mjs.map} +1 -1
  264. package/dist/{renderer-CO4NGvAh.mjs → renderer-tvYj306A.mjs} +81 -78
  265. package/dist/renderer-tvYj306A.mjs.map +1 -0
  266. package/dist/renderer-xvWGpVyp.mjs +5 -0
  267. package/dist/renderer-zafZbD6Q.mjs +5 -0
  268. package/dist/{renderers-CP8CFWDs-BufiCyn7.mjs → renderers-CP8CFWDs-DLjtjrwx.mjs} +2 -2
  269. package/dist/{renderers-CP8CFWDs-BufiCyn7.mjs.map → renderers-CP8CFWDs-DLjtjrwx.mjs.map} +1 -1
  270. package/dist/sam/index.d.mts +3 -3
  271. package/dist/sam/index.mjs +1 -1
  272. package/dist/signals/index.d.mts +5 -5
  273. package/dist/signals/index.mjs +4 -4
  274. package/dist/{src-BU6vm9sP-DdTHmCr4.mjs → src-B23p_eh7-Cj6-lvV6.mjs} +293 -6
  275. package/dist/src-B23p_eh7-Cj6-lvV6.mjs.map +1 -0
  276. package/dist/{src-DrP7fGJX.mjs → src-CoHAjviq.mjs} +1355 -178
  277. package/dist/src-CoHAjviq.mjs.map +1 -0
  278. package/dist/storage/index.mjs +1 -1
  279. package/package.json +63 -60
  280. package/dist/dist-CiTgmfUw.mjs.map +0 -1
  281. package/dist/dist-DtPPPsZV.mjs.map +0 -1
  282. package/dist/fonts-k5ll8NTE.mjs.map +0 -1
  283. package/dist/index-C2yaponf.d.mts.map +0 -1
  284. package/dist/index-C5sgRLlG.d.mts.map +0 -1
  285. package/dist/index-CnZhBlob.d.mts.map +0 -1
  286. package/dist/index-CtKUQ2VG.d.mts.map +0 -1
  287. package/dist/index-DBh3WphX.d.mts.map +0 -1
  288. package/dist/index-DQ1U3HC3.d.mts.map +0 -1
  289. package/dist/index-a6JrbAK0.d.mts.map +0 -1
  290. package/dist/preview-engine/chunk-5ZS46EFB.mjs +0 -5
  291. package/dist/preview-engine/chunk-N3XTDAL6.mjs +0 -2227
  292. package/dist/preview-engine/chunk-NCQHOGZK.mjs +0 -3
  293. package/dist/preview-engine/chunk-PH3UUX6A.mjs +0 -138
  294. package/dist/preview-engine/chunk-XCPRRMMW.mjs +0 -2462
  295. package/dist/preview-engine/renderers-ZMMQ7S2A.mjs +0 -228
  296. package/dist/preview-lHH8Tv4j.mjs +0 -2446
  297. package/dist/preview-lHH8Tv4j.mjs.map +0 -1
  298. package/dist/program-BfiB9ttP.mjs.map +0 -1
  299. package/dist/renderer-0rLmztAv.mjs +0 -5
  300. package/dist/renderer-B0pjOXFY.mjs +0 -5
  301. package/dist/renderer-B7J13reL.mjs +0 -5
  302. package/dist/renderer-BPGIKGgl.mjs +0 -5
  303. package/dist/renderer-Bv-Artj1.mjs +0 -5
  304. package/dist/renderer-BvLjbhcL.mjs +0 -5
  305. package/dist/renderer-By6awWaf.mjs +0 -5
  306. package/dist/renderer-C0rvsz7m.mjs +0 -5
  307. package/dist/renderer-CDgud_HB.mjs +0 -5
  308. package/dist/renderer-CDiRF3bG.mjs +0 -6
  309. package/dist/renderer-CIIEQd4B.mjs +0 -5
  310. package/dist/renderer-CJblwOA9.mjs +0 -5
  311. package/dist/renderer-CNMOXtXE.mjs +0 -5
  312. package/dist/renderer-CO4NGvAh.mjs.map +0 -1
  313. package/dist/renderer-COeSeNGg.mjs +0 -5
  314. package/dist/renderer-CUfElmtZ.mjs +0 -5
  315. package/dist/renderer-CYh2lFoJ.mjs +0 -5
  316. package/dist/renderer-CYtVZYMH.mjs +0 -5
  317. package/dist/renderer-CjxZlkjb.mjs +0 -5
  318. package/dist/renderer-Cpd6TvTC.mjs +0 -5
  319. package/dist/renderer-D3ziOPhX.mjs +0 -5
  320. package/dist/renderer-D5yp74NL.mjs +0 -3
  321. package/dist/renderer-DL-phtL5.mjs +0 -5
  322. package/dist/renderer-DSnmYnHg.mjs +0 -5
  323. package/dist/renderer-DUGfsT-E.mjs +0 -5
  324. package/dist/renderer-DW5af9x1.mjs +0 -5
  325. package/dist/renderer-DYMrol1t.mjs +0 -5
  326. package/dist/renderer-DekeUHaz.mjs +0 -5
  327. package/dist/renderer-Dt5uyJdZ.mjs +0 -5
  328. package/dist/renderer-Dv_iRIyx.mjs.map +0 -1
  329. package/dist/renderer-DwLQAnaK.mjs +0 -5
  330. package/dist/renderer-IXQP2CWM.mjs +0 -5
  331. package/dist/renderer-K-Pkw63O.mjs +0 -5
  332. package/dist/renderer-MPw2KH9P.mjs +0 -5
  333. package/dist/renderer-RPu8RMav.mjs +0 -5
  334. package/dist/renderer-dCqxd5N2.mjs +0 -5
  335. package/dist/renderer-lhjmE-Fp.mjs +0 -5
  336. package/dist/renderer-u9cmBuvM.mjs +0 -5
  337. package/dist/renderer-vH12jcpz.mjs +0 -5
  338. package/dist/src-BU6vm9sP-DdTHmCr4.mjs.map +0 -1
  339. package/dist/src-DrP7fGJX.mjs.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import { Dn as sampleMediaSignal, Et as emojiPresentation, F as MediaTimeRemapInputSchema, It as getActiveMediaMetadata, St as createVirtualMedia, Xt as isSignal, _t as compositionFrameContext, dn as parseCssGradient, ht as assertNever, in as mixColors, l as Color, mt as assertFps, un as parseCssColor, y as Effect, zn as validateMediaTimeRemap } from "./dist-C8XSqfTx.mjs";
2
2
  import { t as ColorSchema } from "./dist-BSKAbyea.mjs";
3
- import { Dt as AdvancedTextAnimatorSchema, Hn as signalRegistry, Tt as AETextAnimatorSchema, Vt as KineticMarqueeConfigSchema, dn as TypewriterAnimatorSchema, in as TextPathOptionsSchema } from "./dist-DtPPPsZV.mjs";
3
+ import { Cr as signalRegistry, Kn as TypewriterAnimatorSchema, Sn as KineticMarqueeConfigSchema, cn as AdvancedTextAnimatorSchema, on as AETextAnimatorSchema, zn as TextPathOptionsSchema } from "./dist-XqlFM2a8.mjs";
4
4
  import { z } from "zod";
5
5
  import { loadYoga } from "yoga-layout/load";
6
+ import gsapModule from "gsap";
6
7
 
7
8
  //#region ../compositions/dist/program/index.mjs
8
9
  let yogaInstance = null;
@@ -391,6 +392,14 @@ function collectInlineSignals(nodes, out = {}) {
391
392
  }
392
393
  return out;
393
394
  }
395
+ const PROP_ALIASES = {
396
+ rotationX: "rotateX",
397
+ rotationY: "rotateY",
398
+ rotationZ: "rotateZ"
399
+ };
400
+ function normalizeAnimatableProp(prop) {
401
+ return PROP_ALIASES[prop] ?? prop;
402
+ }
394
403
  const isKeyframeTrack = (t) => !t.source || t.source.type === "keyframe";
395
404
  /**
396
405
  * Merges keyframe tracks that animate the same prop into one sorted track,
@@ -577,6 +586,15 @@ var LayerAnimation = class LayerAnimation$1 {
577
586
  static rotateZ(fromAngle, toAngle, options = {}) {
578
587
  return new LayerAnimation$1().fromTo("rotateZ", fromAngle, toAngle, options);
579
588
  }
589
+ static rotationX(fromAngle, toAngle, options = {}) {
590
+ return new LayerAnimation$1().fromTo("rotateX", fromAngle, toAngle, options);
591
+ }
592
+ static rotationY(fromAngle, toAngle, options = {}) {
593
+ return new LayerAnimation$1().fromTo("rotateY", fromAngle, toAngle, options);
594
+ }
595
+ static rotationZ(fromAngle, toAngle, options = {}) {
596
+ return new LayerAnimation$1().fromTo("rotateZ", fromAngle, toAngle, options);
597
+ }
580
598
  static rotation(fromAngle, toAngle, options = {}) {
581
599
  return new LayerAnimation$1().fromTo("rotation", fromAngle, toAngle, options);
582
600
  }
@@ -599,16 +617,18 @@ var LayerAnimation = class LayerAnimation$1 {
599
617
  * - `N`: repeats N times after the initial iteration (total N + 1 iterations).
600
618
  */
601
619
  repeat(count = -1, prop) {
620
+ const canonical = prop ? normalizeAnimatableProp(prop) : void 0;
602
621
  this.defaultRepeat = count;
603
- for (const track of this.tracks) if (!prop || track.prop === prop) track.repeat = count;
622
+ for (const track of this.tracks) if (!canonical || track.prop === canonical) track.repeat = count;
604
623
  return this;
605
624
  }
606
625
  /**
607
626
  * Enables or disables yoyo (alternate playback direction on each repeat iteration).
608
627
  */
609
628
  yoyo(enable = true, prop) {
629
+ const canonical = prop ? normalizeAnimatableProp(prop) : void 0;
610
630
  this.defaultYoyo = enable;
611
- for (const track of this.tracks) if (!prop || track.prop === prop) track.yoyo = enable;
631
+ for (const track of this.tracks) if (!canonical || track.prop === canonical) track.yoyo = enable;
612
632
  return this;
613
633
  }
614
634
  /**
@@ -623,7 +643,8 @@ var LayerAnimation = class LayerAnimation$1 {
623
643
  /**
624
644
  * Creates a keyframed track animating from fromValue to toValue.
625
645
  */
626
- fromTo(prop, fromValue, toValue, options = {}) {
646
+ fromTo(rawProp, fromValue, toValue, options = {}) {
647
+ const prop = normalizeAnimatableProp(rawProp);
627
648
  const start = options.from ?? options.start ?? options.fromFrame ?? 0;
628
649
  const end = options.to ?? options.end ?? options.toFrame ?? (options.durationFrames !== void 0 ? start + options.durationFrames : start + 24);
629
650
  const ease = parseEase(options.ease);
@@ -665,7 +686,8 @@ var LayerAnimation = class LayerAnimation$1 {
665
686
  /**
666
687
  * Appends a keyframe to an existing track for prop, or creates a new track.
667
688
  */
668
- keyframe(prop, frame, value, ease) {
689
+ keyframe(rawProp, frame, value, ease) {
690
+ const prop = normalizeAnimatableProp(rawProp);
669
691
  let track = this.tracks.find((t) => t.prop === prop && (!t.source || t.source.type === "keyframe"));
670
692
  if (!track) {
671
693
  const newTrack = {
@@ -696,7 +718,8 @@ var LayerAnimation = class LayerAnimation$1 {
696
718
  * `.keys("scale", [[0, 0], [12, 1.1, "back.out"], [20, 1]])`.
697
719
  * Frames are rounded to whole frames, so beat math can be passed straight in.
698
720
  */
699
- keys(prop, keyframes, options) {
721
+ keys(rawProp, keyframes, options) {
722
+ const prop = normalizeAnimatableProp(rawProp);
700
723
  for (const [frame, value, ease] of keyframes) this.keyframe(prop, Math.round(frame), value, ease);
701
724
  if (options) {
702
725
  const track = this.tracks.find((t) => t.prop === prop && (!t.source || t.source.type === "keyframe"));
@@ -815,6 +838,18 @@ var LayerAnimation = class LayerAnimation$1 {
815
838
  rotateZ(fromAngle, toAngle, options = {}) {
816
839
  return this.fromTo("rotateZ", fromAngle, toAngle, options);
817
840
  }
841
+ /** Alias for {@link rotateX}. */
842
+ rotationX(fromAngle, toAngle, options = {}) {
843
+ return this.fromTo("rotateX", fromAngle, toAngle, options);
844
+ }
845
+ /** Alias for {@link rotateY}. */
846
+ rotationY(fromAngle, toAngle, options = {}) {
847
+ return this.fromTo("rotateY", fromAngle, toAngle, options);
848
+ }
849
+ /** Alias for {@link rotateZ}. */
850
+ rotationZ(fromAngle, toAngle, options = {}) {
851
+ return this.fromTo("rotateZ", fromAngle, toAngle, options);
852
+ }
818
853
  /**
819
854
  * Animate scale along the X axis.
820
855
  */
@@ -883,7 +918,8 @@ var LayerAnimation = class LayerAnimation$1 {
883
918
  * registered with the program automatically — or the name of a signal
884
919
  * registered with `comp.addSignal(name, signal)`.
885
920
  */
886
- signal(prop, signalOrHandleId, options = {}) {
921
+ signal(rawProp, signalOrHandleId, options = {}) {
922
+ const prop = normalizeAnimatableProp(rawProp);
887
923
  const { handleId, inline } = resolveSignalArg(signalOrHandleId);
888
924
  const id = `${prop}_sig_${handleId}_${this.tracks.length}`;
889
925
  const source = {
@@ -896,7 +932,8 @@ var LayerAnimation = class LayerAnimation$1 {
896
932
  threshold: options.threshold ?? .15,
897
933
  accumulateThreshold: options.threshold ?? .15,
898
934
  debounceFrames: options.debounceFrames ?? 2,
899
- channel: options.channel ?? "primary"
935
+ channel: options.channel ?? "primary",
936
+ ...options.clock && { clock: options.clock }
900
937
  };
901
938
  if (inline) attachInlineSignal(source, inline);
902
939
  this.tracks.push({
@@ -911,7 +948,8 @@ var LayerAnimation = class LayerAnimation$1 {
911
948
  * Modulates color interpolation based on an active signal (object or
912
949
  * registered name, as in {@link LayerAnimation.signal}).
913
950
  */
914
- colorSignal(prop, signalOrHandleId, options) {
951
+ colorSignal(rawProp, signalOrHandleId, options) {
952
+ const prop = normalizeAnimatableProp(rawProp);
915
953
  const { handleId, inline } = resolveSignalArg(signalOrHandleId);
916
954
  const id = `${prop}_colorSig_${handleId}_${this.tracks.length}`;
917
955
  const source = {
@@ -938,7 +976,8 @@ var LayerAnimation = class LayerAnimation$1 {
938
976
  /**
939
977
  * Adds organic Perlin noise wiggling to a property.
940
978
  */
941
- wiggle(prop, options = {}) {
979
+ wiggle(rawProp, options = {}) {
980
+ const prop = normalizeAnimatableProp(rawProp);
942
981
  const id = `${prop}_wiggle_${this.tracks.length}`;
943
982
  const source = {
944
983
  type: "wiggle",
@@ -958,7 +997,8 @@ var LayerAnimation = class LayerAnimation$1 {
958
997
  /**
959
998
  * Adds physical harmonic spring overshoot behavior to a property transition.
960
999
  */
961
- spring(prop, options = {}) {
1000
+ spring(rawProp, options = {}) {
1001
+ const prop = normalizeAnimatableProp(rawProp);
962
1002
  const id = `${prop}_spring_${this.tracks.length}`;
963
1003
  const source = {
964
1004
  type: "springOvershoot",
@@ -1260,6 +1300,132 @@ var CameraAnimation = class CameraAnimation$1 extends LayerAnimation {
1260
1300
  return this;
1261
1301
  }
1262
1302
  };
1303
+ /**
1304
+ * Schemas for character animation on model nodes: layered clips, two-bone
1305
+ * IK, look-at, spring bones, and skinned crowds on instance nodes.
1306
+ *
1307
+ * Time-varying values are tracks: a constant, keyframes `[[frame, …value]]`
1308
+ * (linear, in the layer's own frames), or, in process, a function of the
1309
+ * frame or a signal (anything with `get(ctx)`: audio, physics, vision,
1310
+ * `Signal.*`). Functions and signals are not serializable; a spec sent as
1311
+ * JSON keeps constants and keys.
1312
+ */
1313
+ const Vec3Schema$1 = z.tuple([
1314
+ z.number(),
1315
+ z.number(),
1316
+ z.number()
1317
+ ]);
1318
+ const isFunction = (v) => typeof v === "function";
1319
+ const isSignal$1 = (v) => typeof v === "object" && v !== null && typeof v.get === "function";
1320
+ /**
1321
+ * A number over time: constant, `[[frame, value], …]` keys, `(frame) =>
1322
+ * value`, or a signal.
1323
+ */
1324
+ const NumberTrackSchema = z.union([
1325
+ z.number(),
1326
+ z.array(z.tuple([z.number(), z.number()])).min(1),
1327
+ z.custom(isFunction),
1328
+ z.custom(isSignal$1)
1329
+ ]);
1330
+ /**
1331
+ * A point over time: `[x, y, z]` where each axis is a {@link NumberTrack}
1332
+ * (so a constant, keys, a function or a signal per axis), `[[frame, x, y,
1333
+ * z], …]` keys, or `(frame) => [x, y, z]`.
1334
+ */
1335
+ const Vec3TrackSchema = z.union([
1336
+ z.tuple([
1337
+ NumberTrackSchema,
1338
+ NumberTrackSchema,
1339
+ NumberTrackSchema
1340
+ ]),
1341
+ z.array(z.tuple([
1342
+ z.number(),
1343
+ z.number(),
1344
+ z.number(),
1345
+ z.number()
1346
+ ])).min(1),
1347
+ z.custom(isFunction)
1348
+ ]);
1349
+ const ClipRefSchema = z.union([z.string(), z.number().int().min(0)]);
1350
+ const ModelAnimationLayerSchema = z.object({
1351
+ clip: ClipRefSchema,
1352
+ weight: NumberTrackSchema.optional(),
1353
+ speed: z.number().optional(),
1354
+ timeOffset: z.number().optional(),
1355
+ mask: z.array(z.string()).optional(),
1356
+ loop: z.boolean().optional()
1357
+ }).strict();
1358
+ const TwoBoneIkSchema = z.object({
1359
+ chain: z.tuple([
1360
+ z.string(),
1361
+ z.string(),
1362
+ z.string()
1363
+ ]),
1364
+ target: Vec3TrackSchema,
1365
+ poleTarget: Vec3TrackSchema.optional(),
1366
+ weight: NumberTrackSchema.optional()
1367
+ }).strict();
1368
+ const LookAtSchema = z.object({
1369
+ joint: z.string(),
1370
+ target: Vec3TrackSchema,
1371
+ weight: NumberTrackSchema.optional(),
1372
+ maxAngleDeg: z.number().min(0).max(180).optional(),
1373
+ axis: Vec3Schema$1.optional()
1374
+ }).strict();
1375
+ /**
1376
+ * A joint posed directly, in its own local frame: Euler degrees (applied
1377
+ * Z, then Y, then X, like layers) and a translation offset in model units,
1378
+ * on top of the animated pose (`"additive"`, default) or of the joint's rest
1379
+ * pose (`"rest"`: clips no longer move it).
1380
+ */
1381
+ const JointPoseSchema = z.object({
1382
+ rotateX: NumberTrackSchema.optional(),
1383
+ rotateY: NumberTrackSchema.optional(),
1384
+ rotateZ: NumberTrackSchema.optional(),
1385
+ x: NumberTrackSchema.optional(),
1386
+ y: NumberTrackSchema.optional(),
1387
+ z: NumberTrackSchema.optional(),
1388
+ weight: NumberTrackSchema.optional(),
1389
+ mode: z.enum(["additive", "rest"]).optional()
1390
+ }).strict();
1391
+ /**
1392
+ * Points a bone along a scene direction (the joint turns so the bone,
1393
+ * toward its first child, or its local `axis` lies along it). Retargeting a
1394
+ * performer's pose is a chain of aims, parents first.
1395
+ */
1396
+ const AimSchema = z.object({
1397
+ joint: z.string(),
1398
+ direction: Vec3TrackSchema,
1399
+ weight: NumberTrackSchema.optional(),
1400
+ axis: Vec3Schema$1.optional()
1401
+ }).strict();
1402
+ /**
1403
+ * A joint driven by another: it turns by a share of the source joint's turn
1404
+ * from its rest, per local axis (Euler degrees, Z then Y then X). Applied
1405
+ * after look-ats, before IK, so eyelids follow eyes a `lookAt` aims.
1406
+ */
1407
+ const JointDriverSchema = z.object({
1408
+ joint: z.string(),
1409
+ from: z.string(),
1410
+ rotate: z.object({
1411
+ x: z.number().optional(),
1412
+ y: z.number().optional(),
1413
+ z: z.number().optional()
1414
+ }).strict()
1415
+ }).strict();
1416
+ const SpringBoneChainSchema = z.object({
1417
+ joints: z.array(z.string()).min(1),
1418
+ stiffness: z.number().min(0).optional(),
1419
+ damping: z.number().min(0).max(1).optional(),
1420
+ gravity: Vec3Schema$1.optional()
1421
+ }).strict();
1422
+ const CrowdSchema = z.object({
1423
+ clips: z.array(ClipRefSchema).min(1),
1424
+ fps: z.number().min(1).max(120).optional(),
1425
+ seed: z.number().optional(),
1426
+ speedRange: z.tuple([z.number().min(0), z.number().min(0)]).optional(),
1427
+ phase: z.enum(["random", "sync"]).optional()
1428
+ }).strict();
1263
1429
  const SAMPLES = 128;
1264
1430
  const CURVE_STEPS = 16;
1265
1431
  const NUM_RE = /-?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?/gi;
@@ -1975,7 +2141,10 @@ const COLOR_PROPS$1 = new Set([
1975
2141
  "fillColor",
1976
2142
  "strokeColor",
1977
2143
  "textBackgroundColor",
1978
- "color"
2144
+ "color",
2145
+ "emissive",
2146
+ "subsurfaceColor",
2147
+ "sheenColor"
1979
2148
  ]);
1980
2149
  function computeRepeatFrame(track, localFrame, startFrame, lastFrame) {
1981
2150
  const repeat = track.repeat ?? 0;
@@ -2059,7 +2228,7 @@ function evaluateTrackAtFrame(track, frame, fps = 24, context = {}) {
2059
2228
  return evaluateSpringOvershoot(source, localFrame / (fps > 0 ? fps : 24), v0, v1);
2060
2229
  }
2061
2230
  case "signal": {
2062
- const sigVal = evaluateSignal(source, frame, fps, context.signals);
2231
+ const sigVal = evaluateSignal(source, source.clock === "layer" ? localFrame : frame, fps, context.signals);
2063
2232
  if (COLOR_PROPS$1.has(track.prop)) {
2064
2233
  const src = source;
2065
2234
  const colorA = src.colorA ?? "#ffffff";
@@ -2120,6 +2289,12 @@ function textOf(node) {
2120
2289
  const spans = node.spans ?? [];
2121
2290
  return [node.text, ...spans.map((s) => s.text)].filter((t) => typeof t === "string").join("");
2122
2291
  }
2292
+ const DIRECT_LIGHTS = new Set([
2293
+ "directional",
2294
+ "spot",
2295
+ "point",
2296
+ "rect"
2297
+ ]);
2123
2298
  /** Contrast below this makes text hard to read (WCAG large-text minimum). */
2124
2299
  const MIN_TEXT_CONTRAST = 3;
2125
2300
  function tracksOf(node) {
@@ -2146,6 +2321,21 @@ function solidColor(value) {
2146
2321
  const c = parseCssColor(value);
2147
2322
  return c && c[3] > .99 ? value : null;
2148
2323
  }
2324
+ /**
2325
+ * Cube cameras (panoramic lenses, relativity) and what they cannot combine
2326
+ * with. Returns whether the camera draws a cube.
2327
+ */
2328
+ function lintCamera(node, id, push) {
2329
+ const lens = node.lens;
2330
+ const projection = lens?.projection ?? "perspective";
2331
+ if (projection === "perspective" && (lens?.fov ?? 0) > 160) push("error", "camera_fov_range", `'${id}' has a ${lens?.fov}° perspective lens: perspective goes up to 160°. Use projection "fisheye" for wider views.`, id);
2332
+ const relativity = node.relativity;
2333
+ const cube = projection !== "perspective" || (relativity?.speed ?? 0) > 0 || animates(node, ["relativitySpeed"]);
2334
+ const dof = node.dof;
2335
+ if (cube && (dof?.enabled || animates(node, ["focusDistance"]))) push("error", "camera_cube_dof", `'${id}' is a cube camera (${relativity ? "relativity" : projection}) with depth of field: depth of field needs a single perspective view.`, id);
2336
+ if (cube && node.motionBlur) push("error", "camera_cube_motion_blur", `'${id}' is a cube camera (${relativity ? "relativity" : projection}) with motionBlur: shutter motion blur needs a single perspective view.`, id);
2337
+ return cube;
2338
+ }
2149
2339
  function lintComposition(config, options = {}) {
2150
2340
  const out = [];
2151
2341
  const push = (severity, code, message, layerId) => out.push({
@@ -2161,8 +2351,17 @@ function lintComposition(config, options = {}) {
2161
2351
  let has3D = false;
2162
2352
  const pbrNodes = [];
2163
2353
  const emojiText = [];
2354
+ const seenIds = /* @__PURE__ */ new Set();
2355
+ let directLights = 0;
2356
+ let fogLight;
2357
+ let cubeCamera;
2358
+ let screenSpaceLight;
2164
2359
  const visit = (node, backdrop, atRoot) => {
2165
2360
  const id = String(node.id ?? "?");
2361
+ if (typeof node.id === "string") {
2362
+ if (seenIds.has(node.id)) push("error", "duplicate_id", `Two layers share the id '${id}': the renderer keeps one and drops the other. Give every layer its own id (scenes reused in one composition need their own prefix).`, id);
2363
+ seenIds.add(node.id);
2364
+ }
2166
2365
  if (options.emojiFont === false && node.kind === "text" && hasEmoji(textOf(node))) emojiText.push(id);
2167
2366
  for (const prop of COLOR_PROPS) {
2168
2367
  const v = node[prop];
@@ -2175,12 +2374,18 @@ function lintComposition(config, options = {}) {
2175
2374
  const type = node.lightType ?? "directional";
2176
2375
  if (type === "environment") hasEnvironment = true;
2177
2376
  if (type === "ambient") ambientLights.push(id);
2377
+ if (DIRECT_LIGHTS.has(String(type))) directLights++;
2378
+ if (type === "environment" && node.volumetricFog) fogLight = id;
2379
+ if (type === "environment" && (node.ssr || node.gi)) screenSpaceLight = id;
2178
2380
  if (node.castShadow) {
2179
- if (type !== "directional" && type !== "spot") push("warning", "shadow_unsupported_light", `'${id}' is a ${String(type)} light: only directional and spot lights cast shadows.`, id);
2381
+ if (type !== "directional" && type !== "spot" && type !== "point" && type !== "rect") push("warning", "shadow_unsupported_light", `'${id}' is a ${String(type)} light: only directional, spot, point, and rect lights cast shadows.`, id);
2180
2382
  }
2181
2383
  return;
2182
2384
  }
2183
- if (node.kind === "camera") return;
2385
+ if (node.kind === "camera") {
2386
+ if (lintCamera(node, id, push)) cubeCamera = id;
2387
+ return;
2388
+ }
2184
2389
  if (node.kind === "media") {
2185
2390
  const src = node.inputHandleId;
2186
2391
  if (typeof src === "string") {
@@ -2193,7 +2398,9 @@ function lintComposition(config, options = {}) {
2193
2398
  }
2194
2399
  const is3D = Boolean(node.is3D) || typeof node.z === "number" && node.z !== 0;
2195
2400
  if (is3D || node.kind === "model3d") has3D = true;
2196
- if (node.roughness !== void 0 || node.metallic !== void 0) pbrNodes.push(id);
2401
+ const scatter = node.scatter3d;
2402
+ if (scatter && scatter.count > 0 && options.scatterCoverage?.(scatter) === 0) push("warning", "scatter_filters_reject_all", `'${id}' scatters onto a surface its slopeRange / elevationRange filters reject entirely, so no instance is placed. Widen the ranges (slope is degrees from level, elevation 0..1 from the surface's lowest to highest point).`, id);
2403
+ if (node.roughness !== void 0 || node.metallic !== void 0 || node.clearcoat !== void 0 || node.anisotropy !== void 0) pbrNodes.push(id);
2197
2404
  if (node.kind === "text" && backdrop && !animates(node, ["fill", "color"])) {
2198
2405
  const fg = solidColor(node.fill ?? node.color);
2199
2406
  const behind = solidColor(node.background) ?? backdrop;
@@ -2240,7 +2447,9 @@ function lintComposition(config, options = {}) {
2240
2447
  push("warning", "missing_emoji_font", `${emojiText.length === 1 ? "Text" : `${emojiText.length} text layers`} ${shown}${emojiText.length > 3 ? ", …" : ""} ${emojiText.length === 1 ? "has" : "have"} emoji, but no emoji font is registered, so the emoji draw nothing. Run \`npx framefields fonts add emoji\` and call the generated \`registerFonts()\`, or \`FontManager.registerEmojiFont(path)\` with a color emoji font.`, emojiText[0]);
2241
2448
  }
2242
2449
  if (hasEnvironment && ambientLights.length > 0) push("info", "ambient_with_environment", `The environment already fills shadows with light; ambient light ${ambientLights.join(", ")} adds flat light on top (remove it, or lower it, if the scene looks washed out).`);
2243
- if (has3D && pbrNodes.length > 0 && !hasEnvironment) push("info", "pbr_without_environment", `roughness / metallic are set (${pbrNodes.slice(0, 3).join(", ")}${pbrNodes.length > 3 ? ", …" : ""}) but the scene has no Layer.environment(): add one for physically based shading, reflections and tone mapping.`);
2450
+ if (cubeCamera && screenSpaceLight) push("error", "camera_cube_screen_space", `'${cubeCamera}' is a cube camera, and '${screenSpaceLight}' turns on ssr / gi: screen-space reflections and GI need a single perspective view. Use the environment's floor for reflections.`, screenSpaceLight);
2451
+ if (fogLight && directLights === 0) push("warning", "volumetric_fog_without_lights", `'${fogLight}' turns on volumetricFog, but the scene has no directional, spot, point or rect light: fog scatters only direct light, so there are no light shafts. Add a light (castShadow for shafts).`, fogLight);
2452
+ if (has3D && pbrNodes.length > 0 && !hasEnvironment) push("info", "pbr_without_environment", `roughness / metallic / clearcoat / anisotropy are set (${pbrNodes.slice(0, 3).join(", ")}${pbrNodes.length > 3 ? ", …" : ""}) but the scene has no Layer.environment(): add one for physically based shading, the coat and brushed-metal reflections, and tone mapping.`);
2244
2453
  return out;
2245
2454
  }
2246
2455
  const GEOMETRY = [
@@ -2266,12 +2475,27 @@ function companion(owner, src, suffix, tag) {
2266
2475
  if (Array.isArray(node.children)) node.children = hoistMattes(node.children);
2267
2476
  return node;
2268
2477
  }
2269
- function hoistOne(owner) {
2478
+ function textureCompanion(owner, src, size) {
2479
+ const node = companion(owner, src, "texture", {
2480
+ textureOf: String(owner.id),
2481
+ is3D: false,
2482
+ z: 0
2483
+ });
2484
+ if (GEOMETRY.every((k) => src[k] === void 0)) {
2485
+ node.x = 0;
2486
+ node.y = 0;
2487
+ if (size.width !== void 0) node.width = size.width;
2488
+ if (size.height !== void 0) node.height = size.height;
2489
+ }
2490
+ return node;
2491
+ }
2492
+ function hoistOne(owner, size) {
2270
2493
  const matte = owner.matte;
2271
2494
  const relief = owner.relief;
2272
- const { matte: _matte, relief: _relief, ...rest } = owner;
2495
+ const texture = owner.textureLayer;
2496
+ const { matte: _matte, relief: _relief, textureLayer: _texture, ...rest } = owner;
2273
2497
  const self = { ...rest };
2274
- if (Array.isArray(self.children)) self.children = hoistMattes(self.children);
2498
+ if (Array.isArray(self.children)) self.children = hoistMattes(self.children, size);
2275
2499
  const out = [self];
2276
2500
  if (matte?.node) {
2277
2501
  const node = companion(owner, matte.node, "matte", {
@@ -2291,11 +2515,16 @@ function hoistOne(owner) {
2291
2515
  self.reliefAmount = relief.amount ?? 0;
2292
2516
  out.push(node);
2293
2517
  }
2518
+ if (texture?.node) {
2519
+ const node = textureCompanion(owner, texture.node, size);
2520
+ self.textureLayerId = node.id;
2521
+ out.push(node);
2522
+ }
2294
2523
  return out;
2295
2524
  }
2296
- /** Returns the tree with every `matte` and `relief` turned into a sibling companion layer. */
2297
- function hoistMattes(nodes) {
2298
- return nodes.flatMap((n) => hoistOne(n));
2525
+ /** Returns the tree with every `matte`, `relief` and `textureLayer` turned into a sibling companion layer. */
2526
+ function hoistMattes(nodes, size = {}) {
2527
+ return nodes.flatMap((n) => hoistOne(n, size));
2299
2528
  }
2300
2529
  /**
2301
2530
  * Read a `timeRemap` signal at a composition frame: a signal instance, a named
@@ -2328,6 +2557,181 @@ function sampleMediaTimeSignal(binding, layer, clock) {
2328
2557
  };
2329
2558
  }
2330
2559
  /**
2560
+ * Schemas for procedural 3D content: terrain, SDF sculptures, surface
2561
+ * scattering and wind. A model node's `primitive3d` is checked against the
2562
+ * terrain / SDF schema when it names one of them.
2563
+ */
2564
+ const Vec3Schema = z.tuple([
2565
+ z.number(),
2566
+ z.number(),
2567
+ z.number()
2568
+ ]);
2569
+ const RangeSchema = (min, max) => z.tuple([z.number().min(min).max(max), z.number().min(min).max(max)]);
2570
+ const ShadingSchema = z.enum([
2571
+ "lit",
2572
+ "unlit",
2573
+ "toon"
2574
+ ]);
2575
+ const PrimitiveSurfaceFields = {
2576
+ color: z.string().optional(),
2577
+ material: ShadingSchema.optional(),
2578
+ shininess: z.number().min(0).optional(),
2579
+ roughness: z.number().min(0).max(1).optional(),
2580
+ metallic: z.number().min(0).max(1).optional()
2581
+ };
2582
+ const TerrainNoiseSchema = z.object({
2583
+ seed: z.number().optional(),
2584
+ scale: z.number().positive().optional(),
2585
+ octaves: z.number().int().min(1).max(10).optional(),
2586
+ persistence: z.number().min(0).max(1).optional(),
2587
+ lacunarity: z.number().min(1).max(4).optional(),
2588
+ ridgeMode: z.enum([
2589
+ "fbm",
2590
+ "ridged",
2591
+ "terrace"
2592
+ ]).optional(),
2593
+ terraceSteps: z.number().int().min(2).max(32).optional()
2594
+ }).strict();
2595
+ const TerrainColorByElevationSchema = z.object({
2596
+ lowColor: z.string(),
2597
+ midColor: z.string().optional(),
2598
+ highColor: z.string(),
2599
+ cliffColor: z.string().optional(),
2600
+ cliffThreshold: z.number().min(0).max(1).optional(),
2601
+ bands: RangeSchema(0, 1).optional()
2602
+ }).strict();
2603
+ const TerrainGeometrySchema = z.object({
2604
+ type: z.literal("terrain"),
2605
+ width: z.number().positive(),
2606
+ depth: z.number().positive(),
2607
+ height: z.number().min(0).optional(),
2608
+ segments: z.union([z.number().int().min(1).max(512), z.tuple([z.number().int().min(1).max(512), z.number().int().min(1).max(512)])]).optional(),
2609
+ noise: TerrainNoiseSchema.optional(),
2610
+ heights: z.array(z.number().min(0).max(1)).optional(),
2611
+ overhangWarp: z.number().min(0).optional(),
2612
+ colorByElevation: TerrainColorByElevationSchema.optional(),
2613
+ flatShaded: z.boolean().optional(),
2614
+ base: z.number().min(0).optional(),
2615
+ ...PrimitiveSurfaceFields
2616
+ }).strict();
2617
+ const SdfBaseFields = {
2618
+ op: z.enum([
2619
+ "union",
2620
+ "subtract",
2621
+ "intersect"
2622
+ ]).optional(),
2623
+ smoothness: z.number().min(0).optional(),
2624
+ center: Vec3Schema.optional(),
2625
+ rotation: Vec3Schema.optional(),
2626
+ color: z.string().optional()
2627
+ };
2628
+ const SdfPrimitiveSchema = z.discriminatedUnion("shape", [
2629
+ z.object({
2630
+ ...SdfBaseFields,
2631
+ shape: z.literal("sphere"),
2632
+ radius: z.number().positive()
2633
+ }).strict(),
2634
+ z.object({
2635
+ ...SdfBaseFields,
2636
+ shape: z.literal("box"),
2637
+ size: z.tuple([
2638
+ z.number().positive(),
2639
+ z.number().positive(),
2640
+ z.number().positive()
2641
+ ]),
2642
+ radius: z.number().min(0).optional()
2643
+ }).strict(),
2644
+ z.object({
2645
+ ...SdfBaseFields,
2646
+ shape: z.literal("cylinder"),
2647
+ radius: z.number().positive(),
2648
+ height: z.number().positive()
2649
+ }).strict(),
2650
+ z.object({
2651
+ ...SdfBaseFields,
2652
+ shape: z.literal("capsule"),
2653
+ radius: z.number().positive(),
2654
+ height: z.number().positive()
2655
+ }).strict(),
2656
+ z.object({
2657
+ ...SdfBaseFields,
2658
+ shape: z.literal("torus"),
2659
+ radius: z.number().positive(),
2660
+ tube: z.number().positive()
2661
+ }).strict(),
2662
+ z.object({
2663
+ ...SdfBaseFields,
2664
+ shape: z.literal("gyroid"),
2665
+ scale: z.number().positive(),
2666
+ thickness: z.number().positive()
2667
+ }).strict()
2668
+ ]);
2669
+ const SdfGeometrySchema = z.object({
2670
+ type: z.literal("sdf"),
2671
+ primitives: z.array(SdfPrimitiveSchema).min(1),
2672
+ bounds: z.tuple([
2673
+ z.number().positive(),
2674
+ z.number().positive(),
2675
+ z.number().positive()
2676
+ ]),
2677
+ resolution: z.number().int().min(16).max(160).optional(),
2678
+ flatShaded: z.boolean().optional(),
2679
+ ...PrimitiveSurfaceFields
2680
+ }).strict();
2681
+ /** `primitive3d`: free-form for the classic primitives, strict for terrain and SDF. */
2682
+ const Primitive3DSpecSchema = z.unknown().superRefine((value, ctx) => {
2683
+ const type = value?.type;
2684
+ const schema = type === "terrain" ? TerrainGeometrySchema : type === "sdf" ? SdfGeometrySchema : void 0;
2685
+ if (!schema) return;
2686
+ const parsed = schema.safeParse(value);
2687
+ if (parsed.success) return;
2688
+ for (const issue$1 of parsed.error.issues) ctx.addIssue({
2689
+ ...issue$1,
2690
+ code: "custom",
2691
+ message: issue$1.message
2692
+ });
2693
+ });
2694
+ const WindSchema = z.object({
2695
+ amplitudeDeg: z.number().min(0).max(90).optional(),
2696
+ frequency: z.number().min(0).max(20).optional(),
2697
+ direction: z.tuple([z.number(), z.number()]).optional(),
2698
+ waveScale: z.number().positive().optional()
2699
+ }).strict();
2700
+ const ScatterExclusionSchema = z.object({
2701
+ x: z.number(),
2702
+ z: z.number(),
2703
+ radius: z.number().min(0),
2704
+ falloff: z.number().min(0).optional()
2705
+ }).strict();
2706
+ const Scatter3DSchema = z.object({
2707
+ surface: z.custom((v) => typeof v === "object" && v !== null),
2708
+ count: z.number().int().min(0).max(2e5),
2709
+ minDistance: z.number().min(0).optional(),
2710
+ seed: z.number().optional(),
2711
+ slopeRange: RangeSchema(0, 180).optional(),
2712
+ elevationRange: RangeSchema(0, 1).optional(),
2713
+ alignToNormal: z.number().min(0).max(1).optional(),
2714
+ scaleRange: z.tuple([z.number().positive(), z.number().positive()]).optional(),
2715
+ randomYaw: z.boolean().optional(),
2716
+ exclude: z.array(ScatterExclusionSchema).optional(),
2717
+ sink: z.number().optional()
2718
+ }).strict();
2719
+ /** A layer drawn offscreen every frame and wrapped onto a model's surface. */
2720
+ const TextureLayerSchema = z.object({ node: z.custom((v) => typeof v === "object" && v !== null) }).strict();
2721
+ /**
2722
+ * Voronoi destruction (`world.fracture`): the model is cut into `cells`
2723
+ * pieces, drawn as one rigidly skinned mesh posed per frame from `track`.
2724
+ * Without a track the pieces rest in place and the model looks whole.
2725
+ */
2726
+ const Fracture3DSchema = z.object({
2727
+ cells: z.number().int().min(2).max(256).optional(),
2728
+ seed: z.number().optional(),
2729
+ impactPoint: Vec3Schema.optional(),
2730
+ interiorColor: z.string().optional(),
2731
+ interiorRoughness: z.number().min(0).max(1).optional(),
2732
+ track: z.array(z.number()).optional()
2733
+ }).strict();
2734
+ /**
2331
2735
  * Compositor program document v2 — THE single source of truth for a
2332
2736
  * composition (spec: `nodes/node-compositor/SKILL.md`).
2333
2737
  *
@@ -2431,6 +2835,7 @@ const AnimatablePropSchema = z.enum([
2431
2835
  "maxBlurRadius",
2432
2836
  "shakeTranslation",
2433
2837
  "shakeRotation",
2838
+ "relativitySpeed",
2434
2839
  "orbitRadius",
2435
2840
  "orbitAzimuth",
2436
2841
  "orbitElevation",
@@ -2459,7 +2864,24 @@ const AnimatablePropSchema = z.enum([
2459
2864
  "scaleY",
2460
2865
  "emissive",
2461
2866
  "emissiveIntensity",
2462
- "exposure"
2867
+ "clearcoat",
2868
+ "clearcoatRoughness",
2869
+ "anisotropy",
2870
+ "anisotropyRotation",
2871
+ "subsurface",
2872
+ "subsurfaceColor",
2873
+ "sheen",
2874
+ "sheenColor",
2875
+ "sheenRoughness",
2876
+ "iridescence",
2877
+ "iridescenceThickness",
2878
+ "iridescenceIor",
2879
+ "triplanarScale",
2880
+ "triplanarSharpness",
2881
+ "exposure",
2882
+ "volumetricFogDensity",
2883
+ "volumetricFogAnisotropy",
2884
+ "volumetricFogNoiseStrength"
2463
2885
  ]);
2464
2886
  const MatteModeSchema = z.enum([
2465
2887
  "alpha",
@@ -2544,6 +2966,12 @@ const KeyframeSchema = z.object({
2544
2966
  }).optional()
2545
2967
  }).strict();
2546
2968
  const SignalModeSchema = z.enum(["continuous", "accumulate"]);
2969
+ /**
2970
+ * Which clock a signal track reads: the composition's (default), as audio
2971
+ * analysis and shared signals need, or its layer's own, from the layer's
2972
+ * start frame, as keyframes do: motion authored for one scene of a sequence.
2973
+ */
2974
+ const SignalClockSchema = z.enum(["composition", "layer"]);
2547
2975
  const RawTrackSourceSchema = z.discriminatedUnion("type", [
2548
2976
  z.object({ type: z.literal("keyframe") }),
2549
2977
  z.object({
@@ -2560,7 +2988,8 @@ const RawTrackSourceSchema = z.discriminatedUnion("type", [
2560
2988
  threshold: z.number().optional(),
2561
2989
  accumulateThreshold: z.number().optional(),
2562
2990
  debounceFrames: z.number().int().min(0).optional(),
2563
- channel: z.string().optional()
2991
+ channel: z.string().optional(),
2992
+ clock: SignalClockSchema.optional()
2564
2993
  }),
2565
2994
  z.object({
2566
2995
  type: z.literal("wiggle"),
@@ -2595,7 +3024,8 @@ const TrackSourceSchema = z.preprocess((val) => {
2595
3024
  threshold: thresh,
2596
3025
  accumulateThreshold: thresh,
2597
3026
  debounceFrames: obj.debounceFrames ?? 2,
2598
- channel: typeof obj.channel === "string" ? obj.channel : "primary"
3027
+ channel: typeof obj.channel === "string" ? obj.channel : "primary",
3028
+ ...obj.clock !== void 0 && { clock: obj.clock }
2599
3029
  };
2600
3030
  }
2601
3031
  return val;
@@ -2717,6 +3147,30 @@ const LayerAnimationSchema = z.object({
2717
3147
  tracks: z.array(AnimationTrackSchema).max(24),
2718
3148
  frameStep: z.number().int().min(1).max(24).optional()
2719
3149
  }).strict().superRefine(animationInvariants);
3150
+ const ToonShadingSchema = z.object({
3151
+ shadowColor: ColorSchema.optional(),
3152
+ lightColor: ColorSchema.optional(),
3153
+ threshold: z.number().min(-1).max(1).optional(),
3154
+ softness: z.number().min(0).max(2).optional(),
3155
+ diffuse: z.number().min(0).max(1).optional()
3156
+ }).strict();
3157
+ const GeometryOutlineOptionsSchema = z.object({
3158
+ color: ColorSchema.optional(),
3159
+ width: z.number().min(0).max(32).optional(),
3160
+ referenceHeight: z.number().positive().optional(),
3161
+ creaseAngle: z.number().min(0).max(180).optional(),
3162
+ depthThreshold: z.number().positive().max(1).optional(),
3163
+ opacity: z.number().min(0).max(1).optional()
3164
+ }).strict();
3165
+ const IridescenceConfigSchema = z.object({
3166
+ intensity: z.number().min(0).max(1).optional(),
3167
+ thickness: z.number().min(100).max(1200).optional(),
3168
+ ior: z.number().min(1.05).max(2.5).optional()
3169
+ }).strict();
3170
+ const TriplanarConfigSchema = z.object({
3171
+ scale: z.number().min(0).optional(),
3172
+ sharpness: z.number().min(1).max(16).optional()
3173
+ }).strict();
2720
3174
  const BaseNodeFields = {
2721
3175
  id: z.string().min(1),
2722
3176
  inputHandleId: z.string().optional(),
@@ -2777,7 +3231,24 @@ const BaseNodeFields = {
2777
3231
  envIntensity: z.number().min(0).max(10).optional(),
2778
3232
  emissive: ColorSchema.optional(),
2779
3233
  emissiveIntensity: z.number().min(0).optional(),
3234
+ clearcoat: z.number().min(0).max(1).optional(),
3235
+ clearcoatRoughness: z.number().min(0).max(1).optional(),
3236
+ anisotropy: z.number().min(-1).max(1).optional(),
3237
+ anisotropyRotation: z.number().optional(),
3238
+ subsurface: z.number().min(0).max(1).optional(),
3239
+ subsurfaceColor: ColorSchema.optional(),
3240
+ sheen: z.number().min(0).max(1).optional(),
3241
+ sheenColor: ColorSchema.optional(),
3242
+ sheenRoughness: z.number().min(.05).max(1).optional(),
3243
+ iridescence: z.union([z.number().min(0).max(1), IridescenceConfigSchema]).optional(),
3244
+ iridescenceThickness: z.number().min(100).max(1200).optional(),
3245
+ iridescenceIor: z.number().min(1.05).max(2.5).optional(),
3246
+ triplanar: z.union([z.boolean(), TriplanarConfigSchema]).optional(),
3247
+ triplanarScale: z.number().min(0).optional(),
3248
+ triplanarSharpness: z.number().min(1).max(16).optional(),
2780
3249
  castShadow: z.boolean().optional(),
3250
+ toon: ToonShadingSchema.optional(),
3251
+ outline: z.boolean().optional(),
2781
3252
  matte: z.object({
2782
3253
  node: z.custom((v) => typeof v === "object" && v !== null),
2783
3254
  mode: MatteModeSchema.optional()
@@ -2792,6 +3263,7 @@ const BaseNodeFields = {
2792
3263
  reliefId: z.string().optional(),
2793
3264
  reliefOf: z.string().optional(),
2794
3265
  reliefAmount: z.number().optional(),
3266
+ textureOf: z.string().optional(),
2795
3267
  animation: LayerAnimationSchema.default({ tracks: [] }),
2796
3268
  vision: z.unknown().optional(),
2797
3269
  relighting: z.unknown().optional()
@@ -2903,13 +3375,25 @@ const TextAnimator = {
2903
3375
  };
2904
3376
  }
2905
3377
  };
3378
+ /**
3379
+ * The picture a camera draws. `perspective` is an ordinary lens; the others
3380
+ * are cube cameras: the scene is drawn as six 90° faces around the eye and
3381
+ * remapped, so they can show what no single frustum holds.
3382
+ */
3383
+ const CameraProjectionSchema = z.enum([
3384
+ "perspective",
3385
+ "equirectangular",
3386
+ "fisheye"
3387
+ ]);
2906
3388
  const CameraLensSchema = z.object({
2907
3389
  focalLength: z.number().min(5).max(500).default(50),
2908
- fov: z.number().min(5).max(160).optional(),
3390
+ fov: z.number().min(5).max(360).optional(),
2909
3391
  sensorWidth: z.number().default(36),
2910
3392
  near: z.number().min(.1).default(1),
2911
3393
  far: z.number().min(10).default(5e4),
2912
- zoom: z.number().min(.01).default(1)
3394
+ zoom: z.number().min(.01).default(1),
3395
+ projection: CameraProjectionSchema.default("perspective"),
3396
+ cubeSize: z.number().int().min(64).max(8192).optional()
2913
3397
  }).strict();
2914
3398
  const CameraDoFSchema = z.object({
2915
3399
  enabled: z.boolean().default(false),
@@ -2926,6 +3410,33 @@ const CameraShakeSchema = z.object({
2926
3410
  octaves: z.number().int().min(1).max(6).default(3),
2927
3411
  seed: z.number().default(42)
2928
3412
  }).strict();
3413
+ /**
3414
+ * Per-object shutter motion blur for the 3D scene: every mesh, skinned
3415
+ * joint, instance and fractured piece streaks by its own motion over the
3416
+ * shutter (and the camera's), reconstructed from a velocity buffer.
3417
+ */
3418
+ const CameraMotionBlurSchema = z.object({
3419
+ shutter: z.number().min(1).max(720).default(180),
3420
+ samples: z.number().int().min(4).max(64).default(20),
3421
+ maxBlur: z.number().min(4).max(160).default(48)
3422
+ }).strict();
3423
+ /**
3424
+ * The camera moves through the scene near the speed of light. What it sees
3425
+ * is physics, not grading: rays crowd towards the direction of motion
3426
+ * (aberration), colours shift blue ahead and red behind (Doppler) and ahead
3427
+ * brightens (beaming). Always drawn by a cube camera.
3428
+ */
3429
+ const CameraRelativitySchema = z.object({
3430
+ speed: z.number().min(0).max(.9999).default(0),
3431
+ direction: z.tuple([
3432
+ z.number(),
3433
+ z.number(),
3434
+ z.number()
3435
+ ]).optional(),
3436
+ doppler: z.boolean().default(true),
3437
+ beaming: z.boolean().default(true),
3438
+ exposure: z.union([z.literal("auto"), z.number().min(-64).max(16)]).default("auto")
3439
+ }).strict();
2929
3440
  const CameraNodeSchema = z.object({
2930
3441
  id: z.string().min(1),
2931
3442
  kind: z.literal("camera"),
@@ -2946,6 +3457,8 @@ const CameraNodeSchema = z.object({
2946
3457
  lens: CameraLensSchema.optional(),
2947
3458
  dof: CameraDoFSchema.optional(),
2948
3459
  shake: CameraShakeSchema.optional(),
3460
+ motionBlur: z.union([z.boolean(), CameraMotionBlurSchema]).optional(),
3461
+ relativity: CameraRelativitySchema.optional(),
2949
3462
  startFrame: z.number().int().min(0).default(0),
2950
3463
  durationFrames: z.number().int().min(1).optional(),
2951
3464
  animation: LayerAnimationSchema.default({ tracks: [] })
@@ -2955,13 +3468,16 @@ const LightTypeSchema = z.enum([
2955
3468
  "directional",
2956
3469
  "point",
2957
3470
  "spot",
3471
+ "rect",
2958
3472
  "environment"
2959
3473
  ]);
2960
3474
  const EnvironmentPresetSchema = z.enum([
2961
3475
  "studio",
2962
3476
  "soft",
3477
+ "warm",
2963
3478
  "sunset",
2964
3479
  "night",
3480
+ "neon",
2965
3481
  "neutral"
2966
3482
  ]);
2967
3483
  const ToneMappingSchema = z.enum([
@@ -2990,6 +3506,39 @@ const EnvironmentFloorSchema = z.object({
2990
3506
  fadeDistance: z.number().min(0).optional(),
2991
3507
  opacity: z.number().min(0).max(1).optional()
2992
3508
  }).strict();
3509
+ const EnvironmentVolumetricFogNoiseSchema = z.object({
3510
+ scale: z.number().min(1e-4).optional(),
3511
+ strength: z.number().min(0).max(1).optional(),
3512
+ speed: z.tuple([
3513
+ z.number(),
3514
+ z.number(),
3515
+ z.number()
3516
+ ]).optional(),
3517
+ octaves: z.number().int().min(1).max(3).optional()
3518
+ }).strict();
3519
+ const EnvironmentVolumetricFogSchema = z.object({
3520
+ density: z.number().min(0).optional(),
3521
+ color: ColorSchema.optional(),
3522
+ anisotropy: z.number().min(-.95).max(.95).optional(),
3523
+ heightFalloff: z.number().min(0).optional(),
3524
+ baseHeight: z.number().optional(),
3525
+ steps: z.number().int().min(8).max(64).optional(),
3526
+ maxDistance: z.number().min(100).optional(),
3527
+ lightIntensity: z.number().min(0).optional(),
3528
+ ambientIntensity: z.number().min(0).optional(),
3529
+ noise: z.union([z.boolean(), EnvironmentVolumetricFogNoiseSchema]).optional()
3530
+ }).strict();
3531
+ const EnvironmentSsrSchema = z.object({
3532
+ intensity: z.number().min(0).max(1).optional(),
3533
+ maxRoughness: z.number().min(0).max(1).optional(),
3534
+ thickness: z.number().min(1).optional(),
3535
+ steps: z.number().int().min(16).max(64).optional()
3536
+ }).strict();
3537
+ const EnvironmentGiSchema = z.object({
3538
+ intensity: z.number().min(0).max(4).optional(),
3539
+ radius: z.number().min(1).optional(),
3540
+ samples: z.number().int().min(4).max(16).optional()
3541
+ }).strict();
2993
3542
  const LightNodeSchema = z.object({
2994
3543
  id: z.string().min(1),
2995
3544
  kind: z.literal("light"),
@@ -3011,11 +3560,15 @@ const LightNodeSchema = z.object({
3011
3560
  decay: z.number().min(0).default(2),
3012
3561
  angle: z.number().min(0).max(180).default(45),
3013
3562
  penumbra: z.number().min(0).max(1).default(.2),
3563
+ width: z.number().min(0).optional(),
3564
+ height: z.number().min(0).optional(),
3565
+ twoSided: z.boolean().optional(),
3014
3566
  castShadow: z.boolean().optional(),
3015
3567
  shadowSoftness: z.number().min(0).max(64).optional(),
3016
3568
  shadowDarkness: z.number().min(0).max(1).optional(),
3017
3569
  shadowMapSize: z.number().int().min(256).max(8192).optional(),
3018
3570
  preset: EnvironmentPresetSchema.optional(),
3571
+ hdri: z.union([z.string(), z.custom((v) => v instanceof Uint8Array)]).optional(),
3019
3572
  top: ColorSchema.optional(),
3020
3573
  horizon: ColorSchema.optional(),
3021
3574
  bottom: ColorSchema.optional(),
@@ -3025,6 +3578,13 @@ const LightNodeSchema = z.object({
3025
3578
  toneMapping: ToneMappingSchema.optional(),
3026
3579
  fog: EnvironmentFogSchema.optional(),
3027
3580
  floor: EnvironmentFloorSchema.optional(),
3581
+ volumetricFog: z.union([z.boolean(), EnvironmentVolumetricFogSchema]).optional(),
3582
+ volumetricFogDensity: z.number().min(0).optional(),
3583
+ volumetricFogAnisotropy: z.number().min(-.95).max(.95).optional(),
3584
+ volumetricFogNoiseStrength: z.number().min(0).max(1).optional(),
3585
+ ssr: z.union([z.boolean(), EnvironmentSsrSchema]).optional(),
3586
+ gi: z.union([z.boolean(), EnvironmentGiSchema]).optional(),
3587
+ outlines: z.union([z.boolean(), GeometryOutlineOptionsSchema]).optional(),
3028
3588
  bloom: z.union([z.boolean(), BloomConfigSchema]).optional(),
3029
3589
  startFrame: z.number().int().min(0).default(0),
3030
3590
  durationFrames: z.number().int().min(1).optional(),
@@ -3057,7 +3617,7 @@ const FlexNodeSchema = z.object({
3057
3617
  "reverse",
3058
3618
  "center-out"
3059
3619
  ]).default("forward"),
3060
- overflow: z.enum(["visible", "hidden"]).default("hidden"),
3620
+ overflow: z.enum(["visible", "hidden"]).default("visible"),
3061
3621
  background: ColorSchema.optional(),
3062
3622
  borderRadius: z.number().min(0).optional(),
3063
3623
  borderColor: ColorSchema.optional(),
@@ -3087,7 +3647,7 @@ const BlockNodeSchema = z.object({
3087
3647
  "reverse",
3088
3648
  "center-out"
3089
3649
  ]).default("forward"),
3090
- overflow: z.enum(["visible", "hidden"]).default("hidden"),
3650
+ overflow: z.enum(["visible", "hidden"]).default("visible"),
3091
3651
  background: ColorSchema.optional(),
3092
3652
  borderRadius: z.number().min(0).optional(),
3093
3653
  borderColor: ColorSchema.optional(),
@@ -3112,7 +3672,7 @@ const BoxNodeSchema = z.object({
3112
3672
  "reverse",
3113
3673
  "center-out"
3114
3674
  ]).default("forward"),
3115
- overflow: z.enum(["visible", "hidden"]).default("hidden"),
3675
+ overflow: z.enum(["visible", "hidden"]).default("visible"),
3116
3676
  borderColor: ColorSchema.optional(),
3117
3677
  borderWidth: z.number().min(0).optional(),
3118
3678
  strokeAlign: z.enum([
@@ -3148,6 +3708,7 @@ const TextFields = {
3148
3708
  fontSize: z.number().positive().optional(),
3149
3709
  fontWeight: z.union([z.number().int(), z.string()]).optional(),
3150
3710
  fontStyle: z.string().optional(),
3711
+ fontVariations: z.record(z.string(), z.number()).optional(),
3151
3712
  fill: ColorSchema,
3152
3713
  align: z.enum([
3153
3714
  "start",
@@ -3353,9 +3914,23 @@ const Model3DNodeSchema = z.object({
3353
3914
  color: ColorSchema.optional(),
3354
3915
  colorTint: ColorSchema.optional(),
3355
3916
  text3dOptions: z.unknown().optional(),
3356
- primitive3d: z.unknown().optional(),
3917
+ primitive3d: Primitive3DSpecSchema.optional(),
3357
3918
  instances3d: z.unknown().optional(),
3358
- swarm3d: z.unknown().optional()
3919
+ swarm3d: z.unknown().optional(),
3920
+ scatter3d: Scatter3DSchema.optional(),
3921
+ fracture3d: Fracture3DSchema.optional(),
3922
+ wind: WindSchema.optional(),
3923
+ textureLayer: TextureLayerSchema.optional(),
3924
+ textureLayerId: z.string().optional(),
3925
+ animationLayers: z.array(ModelAnimationLayerSchema).optional(),
3926
+ ik: z.array(TwoBoneIkSchema).optional(),
3927
+ lookAt: z.array(LookAtSchema).optional(),
3928
+ springBones: z.array(SpringBoneChainSchema).optional(),
3929
+ pose: z.record(z.string(), JointPoseSchema).optional(),
3930
+ morphs: z.record(z.string(), NumberTrackSchema).optional(),
3931
+ aim: z.array(AimSchema).optional(),
3932
+ drive: z.array(JointDriverSchema).optional(),
3933
+ crowd: CrowdSchema.optional()
3359
3934
  }).strict();
3360
3935
  /**
3361
3936
  * Dispatch on `kind`, not a plain union: a plain union tries every member,
@@ -3395,7 +3970,6 @@ const CompositorProgramSchema = z.object({
3395
3970
  * @module @framefields/compositions/program/sequence
3396
3971
  *
3397
3972
  * Multi-Scene Timeline Orchestration, Camera Choreography & Carrier Match Cuts.
3398
- * Complies with specs/cinematic-sequencing.ts.
3399
3973
  */
3400
3974
  /**
3401
3975
  * Camera Transition Type across scene boundaries.
@@ -3636,6 +4210,40 @@ function applyStaggerToChildren(children, staggerFrames, direction = "forward",
3636
4210
  * Pure + deterministic: same doc → same tree. No width/height resolution
3637
4211
  * here — geometry comes from `computeLayout` at render time.
3638
4212
  */
4213
+ /**
4214
+ * A container holding a camera and the layers it films is a 3D scene of its
4215
+ * own: its camera, lights and environment see only its layers. It needs a
4216
+ * fixed size to render at. A container holding only a camera (and lights) is
4217
+ * a shot in a camera cut list over the shared world, and stays one.
4218
+ */
4219
+ function isScene3D(node) {
4220
+ if (node.kind !== "box" && node.kind !== "flex" && node.kind !== "block" || typeof node.width !== "number" || typeof node.height !== "number" || !Array.isArray(node.children)) return false;
4221
+ const kids = node.children;
4222
+ return kids.some((c) => c.kind === "camera") && kids.some((c) => c.kind !== "camera" && c.kind !== "light");
4223
+ }
4224
+ /**
4225
+ * `media` with `node`'s effects applied in order, each a pass over the
4226
+ * picture below it: a clip's frames, or a 3D scene's finished composition.
4227
+ */
4228
+ function wrapEffects(media, node) {
4229
+ if (!Array.isArray(node.effects)) return media;
4230
+ let current = media;
4231
+ for (const eff of node.effects) {
4232
+ const effOp = eff && typeof eff.toOperation === "function" ? eff.toOperation() : eff;
4233
+ current = {
4234
+ metadata: { ...current.metadata },
4235
+ operation: {
4236
+ op: String(effOp.op ?? "effect"),
4237
+ id: node.id ? `${node.id}-${effOp.op ?? "effect"}` : void 0,
4238
+ effect: eff,
4239
+ ...effOp,
4240
+ dataType: current.operation.dataType
4241
+ },
4242
+ children: [current]
4243
+ };
4244
+ }
4245
+ return current;
4246
+ }
3639
4247
  function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDurationMs, inheritedDurationFrames, resolveSignal) {
3640
4248
  if (node.kind === "media" && node.timeRemap !== void 0) {
3641
4249
  const parsed = MediaTimeRemapInputSchema.safeParse(node.timeRemap);
@@ -3665,24 +4273,7 @@ function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDu
3665
4273
  children: [media]
3666
4274
  };
3667
4275
  }
3668
- if (media && Array.isArray(node.effects)) {
3669
- let currentMedia = media;
3670
- for (const eff of node.effects) {
3671
- const effOp = eff && typeof eff.toOperation === "function" ? eff.toOperation() : eff;
3672
- currentMedia = {
3673
- metadata: { ...currentMedia.metadata },
3674
- operation: {
3675
- op: String(effOp.op ?? "effect"),
3676
- id: node.id ? `${node.id}-${effOp.op ?? "effect"}` : void 0,
3677
- effect: eff,
3678
- ...effOp,
3679
- dataType: currentMedia.operation.dataType
3680
- },
3681
- children: [currentMedia]
3682
- };
3683
- }
3684
- media = currentMedia;
3685
- }
4276
+ if (media) media = wrapEffects(media, node);
3686
4277
  if (media && node.vision) {
3687
4278
  const visionRaw = node.vision;
3688
4279
  const visionOp = typeof visionRaw.toOperation === "function" ? visionRaw.toOperation() : visionRaw;
@@ -3706,10 +4297,48 @@ function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDu
3706
4297
  const nodeStart = typeof node.startFrame === "number" && Number.isFinite(node.startFrame) ? Math.round(node.startFrame) : 0;
3707
4298
  const nodeDuration = typeof node.durationFrames === "number" && Number.isFinite(node.durationFrames) ? Math.round(node.durationFrames) : inheritedDurationFrames;
3708
4299
  const nodeChildren = node.children;
4300
+ const scene = isScene3D(node);
3709
4301
  children = nodeChildren.map((c, idx) => {
3710
4302
  const delay = computeStaggerDelay(idx, nodeChildren.length, staggerFrames, staggerDirection);
3711
- return nodeToVirtualMedia(c, resolveMedia, fps, inheritedOffset + nodeStart + delay, compDurationMs, c.durationFrames === void 0 ? nodeDuration : void 0, resolveSignal);
4303
+ return nodeToVirtualMedia(c, resolveMedia, fps, scene ? delay : inheritedOffset + nodeStart + delay, compDurationMs, c.durationFrames === void 0 ? nodeDuration : void 0, resolveSignal);
3712
4304
  });
4305
+ if (scene) {
4306
+ const frames = nodeDuration ?? Math.round((compDurationMs ?? 1e4) / 1e3 * fps);
4307
+ const durationMs$1 = frames / fps * 1e3;
4308
+ const background = typeof node.background === "string" ? node.background : void 0;
4309
+ const clear = background && parseCssColor(background) ? background : void 0;
4310
+ if (background && !clear) children.unshift(nodeToVirtualMedia({
4311
+ kind: "box",
4312
+ id: `${node.id ?? "scene"}-background`,
4313
+ position: "absolute",
4314
+ x: 0,
4315
+ y: 0,
4316
+ width: node.width,
4317
+ height: node.height,
4318
+ background
4319
+ }, resolveMedia, fps, 0, compDurationMs, frames, resolveSignal));
4320
+ media = {
4321
+ metadata: {
4322
+ width: node.width,
4323
+ height: node.height,
4324
+ fps,
4325
+ durationMs: durationMs$1
4326
+ },
4327
+ operation: {
4328
+ op: "Compositor",
4329
+ width: node.width,
4330
+ height: node.height,
4331
+ fps,
4332
+ mode: "Video",
4333
+ dataType: "Video",
4334
+ volume: 1,
4335
+ ...clear && { backgroundColor: clear }
4336
+ },
4337
+ children
4338
+ };
4339
+ media = wrapEffects(media, node);
4340
+ children = [media];
4341
+ }
3713
4342
  }
3714
4343
  let dataType = "Image";
3715
4344
  let limit;
@@ -3724,7 +4353,8 @@ function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDu
3724
4353
  let dur = typeof node.durationFrames === "number" && Number.isFinite(node.durationFrames) && node.durationFrames > 0 ? Math.round(node.durationFrames) : void 0;
3725
4354
  const defaultCompDuration = inheritedDurationFrames ?? Math.round((compDurationMs ?? 1e4) / 1e3 * fps);
3726
4355
  if (isContainer && children.length > 0) {
3727
- if (dur === void 0) {
4356
+ if (dur === void 0 && isScene3D(node)) dur = Math.max(1, defaultCompDuration);
4357
+ else if (dur === void 0) {
3728
4358
  const childEnds = children.map((c) => (c.operation.startFrame ?? 0) + (c.operation.durationFrames ?? defaultCompDuration));
3729
4359
  dur = Math.max(1, Math.max(...childEnds) - startFrame);
3730
4360
  }
@@ -3751,6 +4381,12 @@ function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDu
3751
4381
  operation: {
3752
4382
  op: "CompositorLayer",
3753
4383
  ...node,
4384
+ ...isScene3D(node) && {
4385
+ kind: "media",
4386
+ background: void 0,
4387
+ children: void 0,
4388
+ effects: void 0
4389
+ },
3754
4390
  startFrame,
3755
4391
  durationFrames: dur,
3756
4392
  dataType,
@@ -3795,8 +4431,12 @@ function compositorToProgram(config, options) {
3795
4431
  signals: programSignals,
3796
4432
  ...config.onRequestFrame || options.onRequestFrame ? { onRequestFrame: config.onRequestFrame ?? options.onRequestFrame } : {}
3797
4433
  },
3798
- children: hoistMattes(config.layout).map((n) => nodeToVirtualMedia(n, resolveMedia, fps, 0, durationMs, void 0, resolveMediaSignal))
4434
+ children: hoistMattes(config.layout, {
4435
+ width: config.width,
4436
+ height: config.height
4437
+ }).map((n) => nodeToVirtualMedia(n, resolveMedia, fps, 0, durationMs, void 0, resolveMediaSignal))
3799
4438
  };
4439
+ shareSignals(rootMedia.children ?? [], programSignals);
3800
4440
  const effectsList = Array.isArray(options.effects) ? options.effects : Array.isArray(config.effects) ? config.effects : [];
3801
4441
  for (const eff of effectsList) {
3802
4442
  const effOp = eff && typeof eff.toOperation === "function" ? eff.toOperation() : eff;
@@ -3824,17 +4464,238 @@ function compositorToProgram(config, options) {
3824
4464
  }
3825
4465
  return rootMedia;
3826
4466
  }
3827
- /** Recursively gather every node op from a render tree (in order). */
4467
+ /** Hands every nested scene composition the program's signals, which its tracks read. */
4468
+ function shareSignals(nodes, signals) {
4469
+ for (const vm of nodes) {
4470
+ if (vm?.operation?.op === "Compositor") vm.operation.signals = signals;
4471
+ shareSignals(vm?.children ?? [], signals);
4472
+ }
4473
+ }
4474
+ /**
4475
+ * Recursively gather every node op from a render tree (in order), stopping at
4476
+ * nested scene compositions: their layers belong to their own render.
4477
+ */
4478
+ /**
4479
+ * Every layer, 3D scenes' layers included, with its start on the
4480
+ * composition's clock. A scene's layers run on the scene's own clock, which
4481
+ * starts where the scene's layer does, so their starts are offset by it.
4482
+ */
4483
+ function collectLayersOnClock(nodes) {
4484
+ const out = [];
4485
+ const walk = (vm, offset, layerStart) => {
4486
+ const op = vm?.operation;
4487
+ if (op?.op === "Compositor") {
4488
+ for (const c of vm.children ?? []) walk(c, layerStart, layerStart);
4489
+ return;
4490
+ }
4491
+ let start = layerStart;
4492
+ if (op?.op === "CompositorLayer") {
4493
+ start = offset + (op.startFrame ?? 0);
4494
+ out.push({
4495
+ vm,
4496
+ startFrame: start
4497
+ });
4498
+ }
4499
+ for (const c of vm?.children ?? []) walk(c, offset, start);
4500
+ };
4501
+ for (const n of nodes) walk(n, 0, 0);
4502
+ return out;
4503
+ }
3828
4504
  function collectNodeOps(nodes) {
3829
4505
  const out = [];
3830
4506
  const walk = (vm) => {
4507
+ if (vm?.operation?.op === "Compositor") return;
3831
4508
  if (vm?.operation?.op === "CompositorLayer") out.push(vm);
3832
4509
  for (const c of vm?.children ?? []) walk(c);
3833
4510
  };
3834
4511
  for (const n of nodes) walk(n);
3835
4512
  return out;
3836
4513
  }
4514
+ /**
4515
+ * Sampling a layer's animation at a frame exactly as the compositor draws
4516
+ * it: keyframe segments shaped by GSAP's eases (what the compiled GSAP
4517
+ * timeline plays), other sources (wiggle, spring, signals) by the program
4518
+ * evaluator. The compositor's draw-time tracks and anything that must agree
4519
+ * with the picture outside a render (physics following a layer) share it.
4520
+ */
4521
+ const gsap = gsapModule.default ?? gsapModule;
4522
+ /**
4523
+ * Solves a cubic bezier curve defined by control points (x1, y1) and (x2, y2)
4524
+ * for a given progress parameter t in [0, 1].
4525
+ */
4526
+ function solveCubicBezier(x1, y1, x2, y2, t) {
4527
+ if (t <= 0) return 0;
4528
+ if (t >= 1) return 1;
4529
+ if (x1 === y1 && x2 === y2) return t;
4530
+ let u = t;
4531
+ for (let i = 0; i < 8; i++) {
4532
+ const oneMinusU$1 = 1 - u;
4533
+ const oneMinusU2 = oneMinusU$1 * oneMinusU$1;
4534
+ const u2 = u * u;
4535
+ const diff = 3 * oneMinusU2 * u * x1 + 3 * oneMinusU$1 * u2 * x2 + u2 * u - t;
4536
+ if (Math.abs(diff) < 1e-6) break;
4537
+ const dx = 3 * oneMinusU2 * x1 + 6 * oneMinusU$1 * u * (x2 - x1) + 3 * u2 * (1 - x2);
4538
+ if (Math.abs(dx) < 1e-6) break;
4539
+ u -= diff / dx;
4540
+ u = Math.max(0, Math.min(1, u));
4541
+ }
4542
+ const oneMinusU = 1 - u;
4543
+ const checkX = 3 * oneMinusU * oneMinusU * u * x1 + 3 * oneMinusU * u * u * x2 + u * u * u;
4544
+ if (Math.abs(checkX - t) > .001) {
4545
+ let low = 0;
4546
+ let high = 1;
4547
+ u = t;
4548
+ for (let i = 0; i < 16; i++) {
4549
+ const mid = (low + high) * .5;
4550
+ const oMid = 1 - mid;
4551
+ const xMid = 3 * oMid * oMid * mid * x1 + 3 * oMid * mid * mid * x2 + mid * mid * mid;
4552
+ if (Math.abs(xMid - t) < 1e-5) {
4553
+ u = mid;
4554
+ break;
4555
+ }
4556
+ if (xMid < t) low = mid;
4557
+ else high = mid;
4558
+ u = mid;
4559
+ }
4560
+ }
4561
+ const oU = 1 - u;
4562
+ return 3 * oU * oU * u * y1 + 3 * oU * u * u * y2 + u * u * u;
4563
+ }
4564
+ function mappedEase(ease, durationFrames, fps = 24) {
4565
+ if (!ease) return "none";
4566
+ const { name, dir, params } = ease;
4567
+ if (name === "none") return "none";
4568
+ if (name === "spring") {
4569
+ const damping = Math.max(.001, params?.[0] ?? 10);
4570
+ const stiffness = Math.max(.001, params?.[1] ?? 100);
4571
+ const mass = Math.max(.001, params?.[2] ?? 1);
4572
+ return (p) => {
4573
+ const t = p * (durationFrames && durationFrames > 0 ? durationFrames / (fps > 0 ? fps : 24) : 1);
4574
+ const m = mass;
4575
+ const k = stiffness;
4576
+ const c = damping;
4577
+ const w0 = Math.sqrt(k / m);
4578
+ const zeta = c / (2 * Math.sqrt(k * m));
4579
+ let x = 0;
4580
+ if (zeta < 1) {
4581
+ const wd = w0 * Math.sqrt(1 - zeta * zeta);
4582
+ const A = -1;
4583
+ const B = -zeta * w0 / wd;
4584
+ x = Math.exp(-zeta * w0 * t) * (A * Math.cos(wd * t) + B * Math.sin(wd * t));
4585
+ } else if (zeta === 1) {
4586
+ const A = -1;
4587
+ const B = -w0;
4588
+ x = Math.exp(-w0 * t) * (A + B * t);
4589
+ } else {
4590
+ const r1 = -w0 * (zeta - Math.sqrt(zeta * zeta - 1));
4591
+ const r2 = -w0 * (zeta + Math.sqrt(zeta * zeta - 1));
4592
+ const C1 = -1 / (1 - r1 / r2);
4593
+ const C2 = -1 - C1;
4594
+ x = C1 * Math.exp(r1 * t) + C2 * Math.exp(r2 * t);
4595
+ }
4596
+ return 1 + x;
4597
+ };
4598
+ }
4599
+ if (name === "cubic") {
4600
+ const x1 = params?.[0] ?? .25;
4601
+ const y1 = params?.[1] ?? .1;
4602
+ const x2 = params?.[2] ?? .25;
4603
+ const y2 = params?.[3] ?? 1;
4604
+ return (p) => solveCubicBezier(x1, y1, x2, y2, p);
4605
+ }
4606
+ if (name === "hold") return (p) => p >= .9999 ? 1 : 0;
4607
+ const easeName = name;
4608
+ let suffix = "";
4609
+ if (params && params.length > 0) suffix = `(${params.join(", ")})`;
4610
+ else if (name === "back") suffix = "(1.7)";
4611
+ else if (name === "elastic") suffix = "(1, 0.3)";
4612
+ return `${easeName}.${dir}${suffix}`;
4613
+ }
4614
+ /** GSAP's shaping for a keyframe segment, so draw-time tracks ease like baked ones. */
4615
+ function gsapEase(fps) {
4616
+ return (ease, deltaFrames, t) => {
4617
+ const e = mappedEase(ease, deltaFrames, fps);
4618
+ const fn = typeof e === "function" ? e : gsap.parseEase(e);
4619
+ return fn ? fn(t) : t;
4620
+ };
4621
+ }
4622
+ /** A track's value at composition frame `frame`. */
4623
+ function sampleTrack(track, frame, fps, ctx = {}) {
4624
+ const startFrame = ctx.startFrame ?? 0;
4625
+ const step = ctx.step ?? 1;
4626
+ const f = step > 1 ? startFrame + Math.floor((frame - startFrame) / step) * step : frame;
4627
+ if ((track.source ?? { type: "keyframe" }).type === "keyframe") return evaluateKeyframes(track, f - startFrame, gsapEase(fps));
4628
+ return evaluateTrackAtFrame(track, f, fps, {
4629
+ startFrame,
4630
+ baseValues: ctx.base,
4631
+ signals: ctx.signals
4632
+ });
4633
+ }
4634
+ /**
4635
+ * A layer's numeric prop at composition frame `frame`: its own value, then
4636
+ * each of its tracks on that prop in order (a later track overrides).
4637
+ */
4638
+ function sampleLayerProp(layer, prop, frame, fps, fallback = 0) {
4639
+ const own = layer[prop];
4640
+ let value = typeof own === "number" && Number.isFinite(own) ? own : fallback;
4641
+ const animation = layer.animation;
4642
+ for (const track of animation?.tracks ?? []) {
4643
+ if (track.prop !== prop) continue;
4644
+ const v = sampleTrack(track, frame, fps, {
4645
+ startFrame: layer.startFrame ?? 0,
4646
+ step: animation?.frameStep,
4647
+ base: layer
4648
+ });
4649
+ if (typeof v === "number" && Number.isFinite(v)) value = v;
4650
+ }
4651
+ return value;
4652
+ }
4653
+ const signalContext = (c) => ({
4654
+ frame: c.frame,
4655
+ fps: c.fps,
4656
+ time: c.frame / c.fps,
4657
+ duration: 0,
4658
+ durationMs: 0,
4659
+ progress: 0,
4660
+ deltaTime: 1 / c.fps
4661
+ });
4662
+ /** A number track's value: constant, keys, function, or signal. */
4663
+ function numberAt(track, clock, fallback) {
4664
+ if (track === void 0) return fallback;
4665
+ if (typeof track === "number") return track;
4666
+ if (typeof track === "function") return track(clock.frame);
4667
+ if (Array.isArray(track)) return keyed(track, clock.frame, 1)[0] ?? fallback;
4668
+ const v = track.get(signalContext(clock));
4669
+ return Number.isFinite(v) ? v : fallback;
4670
+ }
4671
+ /** Whether a point track is `[[frame, x, y, z], …]` keys (not one track per axis). */
4672
+ const isPointKeys = (track) => Array.isArray(track[0]) && track[0].length === 4;
4673
+ /** A point track's value: per-axis tracks, keys, or a function. */
4674
+ function vec3At(track, clock) {
4675
+ if (typeof track === "function") return track(clock.frame);
4676
+ if (isPointKeys(track)) return keyed(track, clock.frame, 3);
4677
+ const axes = track;
4678
+ return [
4679
+ numberAt(axes[0], clock, 0),
4680
+ numberAt(axes[1], clock, 0),
4681
+ numberAt(axes[2], clock, 0)
4682
+ ];
4683
+ }
4684
+ /** Linear interpolation over `[[frame, …values]]` keys, held past the ends. */
4685
+ function keyed(keys, frame, size) {
4686
+ const sorted = keys;
4687
+ const first = sorted[0];
4688
+ const last = sorted[sorted.length - 1];
4689
+ if (frame <= first[0]) return first.slice(1, 1 + size);
4690
+ if (frame >= last[0]) return last.slice(1, 1 + size);
4691
+ let k = 0;
4692
+ while (k + 1 < sorted.length && sorted[k + 1][0] <= frame) k++;
4693
+ const a = sorted[k];
4694
+ const b = sorted[k + 1];
4695
+ const u = (frame - a[0]) / Math.max(1e-9, b[0] - a[0]);
4696
+ return a.slice(1, 1 + size).map((v, i) => v + (b[i + 1] - v) * u);
4697
+ }
3837
4698
 
3838
4699
  //#endregion
3839
- export { ToneMappingSchema as A, evaluateKeyframes as B, Sequence as C, TextNodeSchema as D, TextAnimatorSchema as E, computeCarrierContinuity as F, mediaSignalSampler as G, hoistMattes as H, computeLayout as I, mergeAnimationTracks as K, computeLayoutSync as L, calculateSequenceTimeline as M, collectNodeOps as N, TextSpanMarkSchema as O, compositorToProgram as P, computeStaggerDelay as R, SceneTransitionTypeSchema as S, TextAnimator as T, initLayout as U, evaluateTrackAtFrame as V, lintComposition as W, MatteModeSchema as _, CarrierHandoffConfigSchema as a, Scene as b, EnvironmentFloorSchema as c, FlexNodeSchema as d, LayerAnimation as f, MaterialTypeSchema as g, LightTypeSchema as h, CameraNodeSchema as i, applyStaggerToChildren as j, TextSpanSchema as k, EnvironmentFogSchema as l, LightNodeSchema as m, BoxNodeSchema as n, ColorStopSchema as o, LayoutNodeSchema as p, sampleMediaTimeSignal as q, CameraAnimation as r, CompositorProgramSchema as s, BloomConfigSchema as t, EnvironmentPresetSchema as u, MediaNodeSchema as v, ShapeNodeSchema as w, SceneDefinitionSchema as x, Model3DNodeSchema as y, evaluateAnimationAtFrame as z };
3840
- //# sourceMappingURL=program-BfiB9ttP.mjs.map
4700
+ export { mergeAnimationTracks as $, TextAnimator as A, collectNodeOps as B, MediaNodeSchema as C, SceneTransitionTypeSchema as D, SceneDefinitionSchema as E, ToneMappingSchema as F, computeStaggerDelay as G, computeCarrierContinuity as H, ToonShadingSchema as I, hoistMattes as J, evaluateAnimationAtFrame as K, applyStaggerToChildren as L, TextNodeSchema as M, TextSpanMarkSchema as N, Sequence as O, TextSpanSchema as P, mediaSignalSampler as Q, calculateSequenceTimeline as R, MatteModeSchema as S, Scene as T, computeLayout as U, compositorToProgram as V, computeLayoutSync as W, lintComposition as X, initLayout as Y, mappedEase as Z, LayerAnimation as _, CarrierHandoffConfigSchema as a, LightTypeSchema as b, EnvironmentFloorSchema as c, EnvironmentPresetSchema as d, numberAt as et, EnvironmentSsrSchema as f, GeometryOutlineOptionsSchema as g, FlexNodeSchema as h, CameraNodeSchema as i, vec3At as it, TextAnimatorSchema as j, ShapeNodeSchema as k, EnvironmentFogSchema as l, EnvironmentVolumetricFogSchema as m, BoxNodeSchema as n, sampleMediaTimeSignal as nt, ColorStopSchema as o, EnvironmentVolumetricFogNoiseSchema as p, evaluateTrackAtFrame as q, CameraAnimation as r, sampleTrack as rt, CompositorProgramSchema as s, BloomConfigSchema as t, sampleLayerProp as tt, EnvironmentGiSchema as u, LayoutNodeSchema as v, Model3DNodeSchema as w, MaterialTypeSchema as x, LightNodeSchema as y, collectLayersOnClock as z };
4701
+ //# sourceMappingURL=program-CMigyfso.mjs.map