framefields 2.0.10 → 2.1.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.
- package/README.md +39 -11
- package/dist/audio/index.d.mts +4 -4
- package/dist/audio/index.mjs +13 -12
- package/dist/{audio-BxA0sL9z.d.mts → audio-C2fLC3Tx.d.mts} +3 -3
- package/dist/{audio-BxA0sL9z.d.mts.map → audio-C2fLC3Tx.d.mts.map} +1 -1
- package/dist/{audio-TAvPwzLR.mjs → audio-DJeVoE8b.mjs} +1 -1
- package/dist/{audio-TAvPwzLR.mjs.map → audio-DJeVoE8b.mjs.map} +1 -1
- package/dist/{audio-B7Al-W_0.mjs → audio-D_4SeMRK.mjs} +4 -4
- package/dist/{audio-B7Al-W_0.mjs.map → audio-D_4SeMRK.mjs.map} +1 -1
- package/dist/{client-CwRhflHE.mjs → client-dVxUnmHz.mjs} +1 -1
- package/dist/{client-CwRhflHE.mjs.map → client-dVxUnmHz.mjs.map} +1 -1
- package/dist/{dist-C_hjvkdN.mjs → dist-0QGroRYZ.mjs} +1 -1
- package/dist/{dist-C_hjvkdN.mjs.map → dist-0QGroRYZ.mjs.map} +1 -1
- package/dist/{dist-DzUJmIHt.mjs → dist-BY0bIWgr.mjs} +10 -2
- package/dist/dist-BY0bIWgr.mjs.map +1 -0
- package/dist/{dist-B9PkqWnN.mjs → dist-Bun_TUvZ.mjs} +24046 -20774
- package/dist/dist-Bun_TUvZ.mjs.map +1 -0
- package/dist/{dist-BFjSQP7i.mjs → dist-DlzqyRar.mjs} +75 -618
- package/dist/dist-DlzqyRar.mjs.map +1 -0
- package/dist/{dist-cjs-TsA8LFXC.mjs → dist-cjs-91nR6B7Z.mjs} +3 -3
- package/dist/{dist-cjs-TsA8LFXC.mjs.map → dist-cjs-91nR6B7Z.mjs.map} +1 -1
- package/dist/{dist-cjs-DJ8fcQEe.mjs → dist-cjs-BAIenEMC.mjs} +11 -11
- package/dist/{dist-cjs-DJ8fcQEe.mjs.map → dist-cjs-BAIenEMC.mjs.map} +1 -1
- package/dist/{dist-cjs-BmyyWYWv.mjs → dist-cjs-BEQhh76X.mjs} +2 -2
- package/dist/{dist-cjs-BmyyWYWv.mjs.map → dist-cjs-BEQhh76X.mjs.map} +1 -1
- package/dist/{dist-cjs--pxyGFw2.mjs → dist-cjs-BYPq7pfw.mjs} +1 -1
- package/dist/{dist-cjs--pxyGFw2.mjs.map → dist-cjs-BYPq7pfw.mjs.map} +1 -1
- package/dist/{dist-cjs--lfMLs3U.mjs → dist-cjs-BocDqSCX.mjs} +4 -4
- package/dist/{dist-cjs--lfMLs3U.mjs.map → dist-cjs-BocDqSCX.mjs.map} +1 -1
- package/dist/{dist-cjs-CsU2sZoX.mjs → dist-cjs-CWiNggTl.mjs} +4 -4
- package/dist/{dist-cjs-CsU2sZoX.mjs.map → dist-cjs-CWiNggTl.mjs.map} +1 -1
- package/dist/{dist-cjs-DjzmP0-x.mjs → dist-cjs-CwabutT6.mjs} +13 -13
- package/dist/{dist-cjs-DjzmP0-x.mjs.map → dist-cjs-CwabutT6.mjs.map} +1 -1
- package/dist/{dist-cjs-BDpO-TH_.mjs → dist-cjs-D-EE4Ahy.mjs} +1 -1
- package/dist/{dist-cjs-BDpO-TH_.mjs.map → dist-cjs-D-EE4Ahy.mjs.map} +1 -1
- package/dist/{dist-cjs-CQwmMllY.mjs → dist-cjs-DNtDUWfk.mjs} +6 -6
- package/dist/{dist-cjs-CQwmMllY.mjs.map → dist-cjs-DNtDUWfk.mjs.map} +1 -1
- package/dist/{dist-cjs-CND_ghfH.mjs → dist-cjs-DbZhsgS0.mjs} +1 -1
- package/dist/{dist-cjs-CND_ghfH.mjs.map → dist-cjs-DbZhsgS0.mjs.map} +1 -1
- package/dist/{dist-cjs-CgFzrgj8.mjs → dist-cjs-Dh7REKcN.mjs} +1 -1
- package/dist/{dist-cjs-CgFzrgj8.mjs.map → dist-cjs-Dh7REKcN.mjs.map} +1 -1
- package/dist/{dist-cjs-DT2jJlcK.mjs → dist-cjs-Dobx0Nz-.mjs} +5 -5
- package/dist/{dist-cjs-DT2jJlcK.mjs.map → dist-cjs-Dobx0Nz-.mjs.map} +1 -1
- package/dist/{dist-cjs-DzjrlfbE.mjs → dist-cjs-Du0UpNof.mjs} +14 -14
- package/dist/{dist-cjs-DzjrlfbE.mjs.map → dist-cjs-Du0UpNof.mjs.map} +1 -1
- package/dist/dist-cjs-DyHiUfsr.mjs +6 -0
- package/dist/{dist-cjs-M-8QOgS_.mjs → dist-cjs-HHMfMF5a.mjs} +2 -2
- package/dist/{dist-cjs-M-8QOgS_.mjs.map → dist-cjs-HHMfMF5a.mjs.map} +1 -1
- package/dist/{dist-cjs-BiKQozdJ.mjs → dist-cjs-UJYQzLNT.mjs} +3 -3
- package/dist/{dist-cjs-BiKQozdJ.mjs.map → dist-cjs-UJYQzLNT.mjs.map} +1 -1
- package/dist/{dist-cjs-agQl9T8M.mjs → dist-cjs-UKxm5cFR.mjs} +6 -6
- package/dist/{dist-cjs-agQl9T8M.mjs.map → dist-cjs-UKxm5cFR.mjs.map} +1 -1
- package/dist/{dist-B9Afsv83.mjs → dist-fjKpBYkc.mjs} +662 -28
- package/dist/dist-fjKpBYkc.mjs.map +1 -0
- package/dist/effects/index.d.mts +4 -4
- package/dist/effects/index.mjs +36 -34
- package/dist/{effects-CREopCyP.mjs → effects-FTlu0dri.mjs} +3 -3
- package/dist/{effects-CREopCyP.mjs.map → effects-FTlu0dri.mjs.map} +1 -1
- package/dist/{event-streams-BaNGaLxh.mjs → event-streams-DnRe8uwT.mjs} +2 -2
- package/dist/{event-streams-BaNGaLxh.mjs.map → event-streams-DnRe8uwT.mjs.map} +1 -1
- package/dist/fonts/index.d.mts +2 -2
- package/dist/fonts/index.mjs +3 -1
- package/dist/{fonts-DhEQ5h6E.mjs → fonts-UM5xaBOx.mjs} +66 -6
- package/dist/fonts-UM5xaBOx.mjs.map +1 -0
- package/dist/gpu-RkpiFGOA.mjs +215 -0
- package/dist/gpu-RkpiFGOA.mjs.map +1 -0
- package/dist/{index-BXNNJVs8.d.mts → index-CHQ39_Oe.d.mts} +2 -2
- package/dist/{index-BXNNJVs8.d.mts.map → index-CHQ39_Oe.d.mts.map} +1 -1
- package/dist/{index-CvDVpaKn.d.mts → index-CzQseCtg.d.mts} +8 -8
- package/dist/{index-CvDVpaKn.d.mts.map → index-CzQseCtg.d.mts.map} +1 -1
- package/dist/{index-D1zaOwEU.d.mts → index-D67p-rHX.d.mts} +3506 -1280
- package/dist/index-D67p-rHX.d.mts.map +1 -0
- package/dist/{index-J9CIK_nu.d.mts → index-DPicEt8H.d.mts} +10 -2
- package/dist/index-DPicEt8H.d.mts.map +1 -0
- package/dist/{index-oodg5k9K.d.mts → index-Db8Z3AtX.d.mts} +3 -3
- package/dist/{index-oodg5k9K.d.mts.map → index-Db8Z3AtX.d.mts.map} +1 -1
- package/dist/{index-fo4E7A6C.d.mts → index-DsOqONsj.d.mts} +3 -3
- package/dist/{index-fo4E7A6C.d.mts.map → index-DsOqONsj.d.mts.map} +1 -1
- package/dist/{index-CQcdKyxF.d.mts → index-l03NV8JS.d.mts} +59 -2
- package/dist/index-l03NV8JS.d.mts.map +1 -0
- package/dist/index.d.mts +416 -1849
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +669 -79
- package/dist/index.mjs.map +1 -1
- package/dist/{package-XpCRbTOA.mjs → package-CudzAF-n.mjs} +1 -1
- package/dist/{package-XpCRbTOA.mjs.map → package-CudzAF-n.mjs.map} +1 -1
- package/dist/preview/index.d.mts +2 -2
- package/dist/preview/index.mjs +13 -12
- package/dist/{preview-9ifxywUM.mjs → preview-DwClLMlU.mjs} +3 -3
- package/dist/{preview-9ifxywUM.mjs.map → preview-DwClLMlU.mjs.map} +1 -1
- package/dist/preview-engine/audio.mjs +1 -1
- package/dist/preview-engine/{chunk-AW7HNZKR.mjs → chunk-3GNP7TJH.mjs} +3 -3
- package/dist/preview-engine/{chunk-LIHUEYI5.mjs → chunk-44CQSOYE.mjs} +2 -2
- package/dist/preview-engine/{chunk-6JW37VJA.mjs → chunk-5AUB4Y3L.mjs} +3 -23
- package/dist/preview-engine/chunk-5DOD2NVY.mjs +26 -0
- package/dist/preview-engine/chunk-5FC7GOWW.mjs +474 -0
- package/dist/preview-engine/chunk-5W4AFQP7.mjs +97 -0
- package/dist/preview-engine/chunk-63SFBHEH.mjs +1 -0
- package/dist/preview-engine/chunk-7EPIRODI.mjs +91 -0
- package/dist/preview-engine/{chunk-PQD5UPHG.mjs → chunk-7G3XIOP7.mjs} +1 -1
- package/dist/preview-engine/chunk-7J2FWGVD.mjs +1 -0
- package/dist/preview-engine/chunk-AXHB4J37.mjs +147 -0
- package/dist/preview-engine/chunk-AY7UX37L.mjs +450 -0
- package/dist/preview-engine/chunk-B43Z3J7J.mjs +5 -0
- package/dist/preview-engine/chunk-BWJS6G7R.mjs +314 -0
- package/dist/preview-engine/{chunk-24DXIKXL.mjs → chunk-DIGIQ5MJ.mjs} +2 -2
- package/dist/preview-engine/{chunk-AEK5BO3J.mjs → chunk-E4RAFHZM.mjs} +1 -1
- package/dist/preview-engine/chunk-ENKKLU7B.mjs +22 -0
- package/dist/preview-engine/{chunk-XLFYM7KH.mjs → chunk-EVXWDOCL.mjs} +2 -2
- package/dist/preview-engine/{chunk-EQ4QZRXB.mjs → chunk-EYWPOCZW.mjs} +2 -2
- package/dist/preview-engine/{chunk-IYVN2QEL.mjs → chunk-FLPSWDX4.mjs} +1 -1
- package/dist/preview-engine/chunk-FU7AIAMM.mjs +88 -0
- package/dist/preview-engine/{chunk-CBM7B7EW.mjs → chunk-GMGGDADT.mjs} +1 -1
- package/dist/preview-engine/chunk-GSFN4WCH.mjs +62 -0
- package/dist/preview-engine/chunk-HE4R7EZM.mjs +121 -0
- package/dist/preview-engine/chunk-IQC2I5A5.mjs +1 -0
- package/dist/preview-engine/chunk-IQKIHFNZ.mjs +1 -0
- package/dist/preview-engine/{chunk-XCYFPA34.mjs → chunk-IR5DNNWR.mjs} +3 -23
- package/dist/preview-engine/chunk-IUPDOATX.mjs +114 -0
- package/dist/preview-engine/{chunk-GHMCGTJ2.mjs → chunk-J2R5R7YY.mjs} +3 -23
- package/dist/preview-engine/chunk-JAJOZG5P.mjs +1 -0
- package/dist/preview-engine/chunk-JXNG2ACR.mjs +118 -0
- package/dist/preview-engine/{chunk-V6VU46ZG.mjs → chunk-L6BH5J4P.mjs} +1 -1
- package/dist/preview-engine/chunk-LGVEFPOG.mjs +3 -0
- package/dist/preview-engine/{chunk-MDDF2GCF.mjs → chunk-MLY5M7Y5.mjs} +3 -23
- package/dist/preview-engine/chunk-NPD6W3RP.mjs +1 -0
- package/dist/preview-engine/chunk-OCX5AD23.mjs +1 -0
- package/dist/preview-engine/{chunk-D3TETPLI.mjs → chunk-OG62XGCT.mjs} +1 -1
- package/dist/preview-engine/chunk-OJ2PKBXE.mjs +40 -0
- package/dist/preview-engine/chunk-OKH2VU2U.mjs +97 -0
- package/dist/preview-engine/chunk-PAQNDZQB.mjs +83 -0
- package/dist/preview-engine/chunk-PEWYB6WP.mjs +43 -0
- package/dist/preview-engine/chunk-PL4IH5V4.mjs +89 -0
- package/dist/preview-engine/chunk-PSRQA3QW.mjs +84 -0
- package/dist/preview-engine/{chunk-JAOXXYXG.mjs → chunk-PXT52LEH.mjs} +3 -23
- package/dist/preview-engine/chunk-Q22PJXFJ.mjs +69 -0
- package/dist/preview-engine/chunk-Q4Z54DQ7.mjs +1 -0
- package/dist/preview-engine/{chunk-BHFI3Y4T.mjs → chunk-QBEUICZD.mjs} +1 -1
- package/dist/preview-engine/chunk-RQLMW6MA.mjs +4 -0
- package/dist/preview-engine/chunk-RSMO7NPN.mjs +1 -0
- package/dist/preview-engine/chunk-RW2F3XLQ.mjs +90 -0
- package/dist/preview-engine/{chunk-25IW7NYO.mjs → chunk-S2CTIJSI.mjs} +1 -1
- package/dist/preview-engine/chunk-SGPRLTNF.mjs +52 -0
- package/dist/preview-engine/{chunk-Y6FEU4TV.mjs → chunk-SZW5J72T.mjs} +3 -23
- package/dist/preview-engine/{chunk-7DIAFPQP.mjs → chunk-T2FE5VOW.mjs} +3 -23
- package/dist/preview-engine/{chunk-ZSIJB76A.mjs → chunk-TS3JI3BH.mjs} +2 -2
- package/dist/preview-engine/{chunk-AMBSW6OA.mjs → chunk-U4JIFQRR.mjs} +2 -2
- package/dist/preview-engine/chunk-VRGREB3V.mjs +1 -0
- package/dist/preview-engine/{chunk-BJKH76OM.mjs → chunk-VXS5SIEC.mjs} +3 -23
- package/dist/preview-engine/chunk-WFGJXCZT.mjs +53 -0
- package/dist/preview-engine/chunk-WH5Q2NFN.mjs +32 -0
- package/dist/preview-engine/{chunk-YG35X5R5.mjs → chunk-WUKH7BD7.mjs} +1 -1
- package/dist/preview-engine/chunk-XC5WZNOY.mjs +1448 -0
- package/dist/preview-engine/chunk-YQZOGEPZ.mjs +186 -0
- package/dist/preview-engine/{chunk-VVLM6LZ3.mjs → chunk-ZDQF3OTC.mjs} +1 -1
- package/dist/preview-engine/chunk-ZIIFTWDH.mjs +58 -0
- package/dist/preview-engine/effects.mjs +1 -1
- package/dist/preview-engine/fonts.mjs +1 -1
- package/dist/preview-engine/framefields.mjs +127 -130
- package/dist/preview-engine/player.mjs +6 -6
- package/dist/preview-engine/renderers-2H7YEUTD.mjs +1 -0
- package/dist/preview-engine/renderers-2ILG23ED.mjs +1 -0
- package/dist/preview-engine/renderers-2P6KXWEZ.mjs +1 -0
- package/dist/preview-engine/renderers-2SVWAB42.mjs +1 -0
- package/dist/preview-engine/renderers-2VN3AH45.mjs +104 -0
- package/dist/preview-engine/renderers-3RC5FDWX.mjs +1 -0
- package/dist/preview-engine/renderers-57WDL6XN.mjs +1 -0
- package/dist/preview-engine/{renderers-CAUWP4XH.mjs → renderers-6OGFUSH6.mjs} +3 -23
- package/dist/preview-engine/renderers-6WH7NZCC.mjs +1 -0
- package/dist/preview-engine/renderers-7VJN5L3Z.mjs +1 -0
- package/dist/preview-engine/renderers-A6HM64UZ.mjs +1 -0
- package/dist/preview-engine/{renderers-WLH4HRUE.mjs → renderers-A7VH3ON5.mjs} +1 -1
- package/dist/preview-engine/renderers-B7DSGUMI.mjs +1 -0
- package/dist/preview-engine/renderers-BFNJ7VCI.mjs +1 -0
- package/dist/preview-engine/renderers-BSKZXITT.mjs +35 -0
- package/dist/preview-engine/renderers-CGYIDAVV.mjs +1 -0
- package/dist/preview-engine/renderers-CRRLV7IO.mjs +1 -0
- package/dist/preview-engine/{renderers-JQHUBWLL.mjs → renderers-D6T6IPER.mjs} +3 -23
- package/dist/preview-engine/renderers-DXHJAMZR.mjs +1 -0
- package/dist/preview-engine/renderers-ECA3P4ON.mjs +1 -0
- package/dist/preview-engine/{renderers-W5CVDJVH.mjs → renderers-F55XFVMP.mjs} +1 -1
- package/dist/preview-engine/renderers-FWGMNPYB.mjs +1 -0
- package/dist/preview-engine/renderers-H46TS3IG.mjs +228 -0
- package/dist/preview-engine/renderers-HXFRTIJD.mjs +1 -0
- package/dist/preview-engine/renderers-IWQ3V6AJ.mjs +1 -0
- package/dist/preview-engine/renderers-JHFT27YU.mjs +1 -0
- package/dist/preview-engine/renderers-KZWGSKRF.mjs +1 -0
- package/dist/preview-engine/renderers-MON4QFRF.mjs +1 -0
- package/dist/preview-engine/renderers-NQXMYNSY.mjs +1 -0
- package/dist/preview-engine/renderers-NWHS7N2L.mjs +1 -0
- package/dist/preview-engine/renderers-ORAIXUL3.mjs +1 -0
- package/dist/preview-engine/renderers-OT7D3BUA.mjs +1 -0
- package/dist/preview-engine/renderers-Q4OFCMXI.mjs +1 -0
- package/dist/preview-engine/renderers-QVZVEYP5.mjs +1 -0
- package/dist/preview-engine/renderers-RJO6H4FC.mjs +1 -0
- package/dist/preview-engine/renderers-RKDPX5JU.mjs +1 -0
- package/dist/preview-engine/{renderers-2US2NIUG.mjs → renderers-RLHTNLRE.mjs} +3 -23
- package/dist/preview-engine/renderers-SBFF7JP5.mjs +1 -0
- package/dist/preview-engine/renderers-SCJ6OKTB.mjs +1 -0
- package/dist/preview-engine/renderers-T4JMJXWL.mjs +1 -0
- package/dist/preview-engine/renderers-TAWT3ZSS.mjs +1 -0
- package/dist/preview-engine/renderers-U6KY34TP.mjs +100 -0
- package/dist/preview-engine/renderers-UHTO6BQA.mjs +1 -0
- package/dist/preview-engine/renderers-UNK6I4JJ.mjs +1 -0
- package/dist/preview-engine/renderers-UPTJJE5F.mjs +1 -0
- package/dist/preview-engine/renderers-W773SBPV.mjs +1 -0
- package/dist/preview-engine/renderers-XHTMRXC5.mjs +1 -0
- package/dist/preview-engine/renderers-YECY2YFT.mjs +1 -0
- package/dist/preview-engine/renderers-YMN6QXK7.mjs +1 -0
- package/dist/preview-engine/renderers-ZANPE3OK.mjs +1 -0
- package/dist/preview-engine/renderers-ZHTX73PR.mjs +1 -0
- package/dist/preview-engine/renderers-ZJTRANIX.mjs +1 -0
- package/dist/preview-engine/signals.mjs +1 -1
- package/dist/preview-engine/skia-canvas-QBXAOGPB.mjs +1 -0
- package/dist/{program-xRfFoPxe.mjs → program-BqFVw5Mu.mjs} +295 -2279
- package/dist/program-BqFVw5Mu.mjs.map +1 -0
- package/dist/renderer/index.d.mts +2 -2
- package/dist/renderer/index.mjs +3 -3
- package/dist/{renderer-BgdkEFmv.mjs → renderer-2Nf9ypST.mjs} +85 -279
- package/dist/renderer-2Nf9ypST.mjs.map +1 -0
- package/dist/{renderer-BREIjsUU.mjs → renderer-2uN2cd0y.mjs} +14 -40
- package/dist/renderer-2uN2cd0y.mjs.map +1 -0
- package/dist/renderer-31jAuNzF.mjs +5 -0
- package/dist/renderer-36EI7Rsz.mjs +5 -0
- package/dist/renderer-3io-cjTt.mjs +5 -0
- package/dist/renderer-9_zWTHbg.mjs +5 -0
- package/dist/{renderer-5h0llpx7.mjs → renderer-B12_76qk.mjs} +4 -3
- package/dist/{renderer-5h0llpx7.mjs.map → renderer-B12_76qk.mjs.map} +1 -1
- package/dist/{renderer-_bygZSKk.mjs → renderer-B4oS8ZFO.mjs} +29 -98
- package/dist/renderer-B4oS8ZFO.mjs.map +1 -0
- package/dist/renderer-B6KnbfdA.mjs +5 -0
- package/dist/renderer-B7Y2bmRc.mjs +5 -0
- package/dist/renderer-BA6miaaI.mjs +5 -0
- package/dist/{renderer-CoZKST2Y.mjs → renderer-BGr_cBKV.mjs} +61 -208
- package/dist/renderer-BGr_cBKV.mjs.map +1 -0
- package/dist/renderer-BHi-Q6Z_.mjs +5 -0
- package/dist/{renderer-BiSALMQy.mjs → renderer-BLcu9RDt.mjs} +3 -1
- package/dist/{renderer-D2XD4QYk.mjs → renderer-BO2lYmtE.mjs} +34 -147
- package/dist/renderer-BO2lYmtE.mjs.map +1 -0
- package/dist/renderer-BOlN9HeG.mjs +5 -0
- package/dist/renderer-BSitV56h.mjs +268 -0
- package/dist/renderer-BSitV56h.mjs.map +1 -0
- package/dist/renderer-BTOW-ceB.mjs +5 -0
- package/dist/{renderer-wVldKtFU.mjs → renderer-BYqfkwLf.mjs} +51 -163
- package/dist/renderer-BYqfkwLf.mjs.map +1 -0
- package/dist/{renderer-bZU_ndxf.mjs → renderer-BajIOuZH.mjs} +2 -2
- package/dist/{renderer-bZU_ndxf.mjs.map → renderer-BajIOuZH.mjs.map} +1 -1
- package/dist/{renderer-jkZ_IQnW.mjs → renderer-BgnJUx24.mjs} +80 -258
- package/dist/renderer-BgnJUx24.mjs.map +1 -0
- package/dist/renderer-BiQ0PYOp.mjs +5 -0
- package/dist/{renderer-BnvqEqvE.mjs → renderer-BjTq3a0L.mjs} +5 -4
- package/dist/{renderer-BnvqEqvE.mjs.map → renderer-BjTq3a0L.mjs.map} +1 -1
- package/dist/{renderer-DEJwPRkR.mjs → renderer-BkN20ZKO.mjs} +15 -51
- package/dist/renderer-BkN20ZKO.mjs.map +1 -0
- package/dist/renderer-Bla7GDyV.mjs +5 -0
- package/dist/renderer-BoYyLVKy.mjs +5 -0
- package/dist/{renderer-D7zvPHKn.mjs → renderer-BpZaHFRc.mjs} +18 -28
- package/dist/renderer-BpZaHFRc.mjs.map +1 -0
- package/dist/renderer-BqOgb7bM.mjs +5 -0
- package/dist/{renderer-DNNqpK7t.mjs → renderer-Bq_dO0LG.mjs} +10 -17
- package/dist/renderer-Bq_dO0LG.mjs.map +1 -0
- package/dist/renderer-BqeM8yTJ.mjs +5 -0
- package/dist/{renderer-DryPrxYc.mjs → renderer-BqsV75Ml.mjs} +3 -1
- package/dist/{renderer-8qpGxSSO.mjs → renderer-Bs4tz_pw.mjs} +20 -87
- package/dist/renderer-Bs4tz_pw.mjs.map +1 -0
- package/dist/{renderer-DdVBt8Rz.mjs → renderer-Bsaokil3.mjs} +24 -104
- package/dist/renderer-Bsaokil3.mjs.map +1 -0
- package/dist/{renderer-D7ztfQHX.mjs → renderer-BvG1GF1c.mjs} +10 -16
- package/dist/renderer-BvG1GF1c.mjs.map +1 -0
- package/dist/{renderer-BGXbGqY4.mjs → renderer-BvpSIFkw.mjs} +83 -266
- package/dist/renderer-BvpSIFkw.mjs.map +1 -0
- package/dist/{renderer-Dju9CaeL.mjs → renderer-BwAqwTQq.mjs} +62 -209
- package/dist/renderer-BwAqwTQq.mjs.map +1 -0
- package/dist/{renderer-CzPWB0Ss.mjs → renderer-BwVfhrEx.mjs} +13 -45
- package/dist/renderer-BwVfhrEx.mjs.map +1 -0
- package/dist/renderer-BzpRe50i.mjs +5 -0
- package/dist/renderer-C0eAPwpr.mjs +5 -0
- package/dist/{renderer-But0u-xi.mjs → renderer-C3RfT8Gv.mjs} +59 -194
- package/dist/renderer-C3RfT8Gv.mjs.map +1 -0
- package/dist/{renderer-CgmFh6MY.mjs → renderer-C3cYDT3m.mjs} +3 -1
- package/dist/{renderer-D-4Yh-RK.mjs → renderer-CEGbqT2m.mjs} +236 -96
- package/dist/renderer-CEGbqT2m.mjs.map +1 -0
- package/dist/{renderer-CcU7dVn9.mjs → renderer-CGldH-Zx.mjs} +40 -142
- package/dist/renderer-CGldH-Zx.mjs.map +1 -0
- package/dist/renderer-CGn8V63v.mjs +5 -0
- package/dist/{renderer-DffynBHa.mjs → renderer-CH9Qtpy7.mjs} +4 -4
- package/dist/{renderer-DffynBHa.mjs.map → renderer-CH9Qtpy7.mjs.map} +1 -1
- package/dist/{renderer-ho_jXJ0H.mjs → renderer-CLyuu_19.mjs} +23 -117
- package/dist/renderer-CLyuu_19.mjs.map +1 -0
- package/dist/renderer-CM5Syo9r.mjs +5 -0
- package/dist/{renderer-BJ6Y-7ke.mjs → renderer-CRIM_XRK.mjs} +3 -3
- package/dist/{renderer-BJ6Y-7ke.mjs.map → renderer-CRIM_XRK.mjs.map} +1 -1
- package/dist/{renderer-2NQWaZd7.d.mts → renderer-CTGe8SqQ.d.mts} +2 -2
- package/dist/{renderer-2NQWaZd7.d.mts.map → renderer-CTGe8SqQ.d.mts.map} +1 -1
- package/dist/renderer-CWCEW6Wv.mjs +5 -0
- package/dist/{renderer-CNF10fCq.mjs → renderer-CgyOylPO.mjs} +10 -17
- package/dist/renderer-CgyOylPO.mjs.map +1 -0
- package/dist/{renderer-DjTiNeAp.mjs → renderer-CjT5Zy-J.mjs} +81 -221
- package/dist/renderer-CjT5Zy-J.mjs.map +1 -0
- package/dist/{renderer-_uvdg48N.mjs → renderer-Cjq1s3br.mjs} +24 -93
- package/dist/renderer-Cjq1s3br.mjs.map +1 -0
- package/dist/renderer-Cl70zxkP.mjs +5 -0
- package/dist/renderer-ClJjoVpB.mjs +6 -0
- package/dist/{renderer-DBlPbsgi.mjs → renderer-CpKNqciR.mjs} +3 -1
- package/dist/{renderer-DTvfYkI9.mjs → renderer-Cwhux4VX.mjs} +9 -16
- package/dist/renderer-Cwhux4VX.mjs.map +1 -0
- package/dist/{renderer-CJNyhr_S.mjs → renderer-D0nWLogn.mjs} +99 -282
- package/dist/renderer-D0nWLogn.mjs.map +1 -0
- package/dist/{renderer-9wp5R7PL.mjs → renderer-D1lynYuy.mjs} +23 -107
- package/dist/renderer-D1lynYuy.mjs.map +1 -0
- package/dist/{renderer-DYm4duFr.mjs → renderer-D4sYVV-I.mjs} +41 -140
- package/dist/renderer-D4sYVV-I.mjs.map +1 -0
- package/dist/{renderer-CroHPOsX.mjs → renderer-D5z3WDkm.mjs} +99 -287
- package/dist/renderer-D5z3WDkm.mjs.map +1 -0
- package/dist/renderer-D8C-pamu.mjs +148 -0
- package/dist/renderer-D8C-pamu.mjs.map +1 -0
- package/dist/{renderer-D_1oDOCP.mjs → renderer-DAtBnNGC.mjs} +14 -69
- package/dist/renderer-DAtBnNGC.mjs.map +1 -0
- package/dist/{renderer-DZGtBUCx.mjs → renderer-DG1NFsSV.mjs} +35 -185
- package/dist/renderer-DG1NFsSV.mjs.map +1 -0
- package/dist/{renderer-BM05sB8m.mjs → renderer-DHAErBtJ.mjs} +11 -74
- package/dist/renderer-DHAErBtJ.mjs.map +1 -0
- package/dist/{renderer-CStktK20.mjs → renderer-DIDSmoFA.mjs} +73 -73
- package/dist/{renderer-CStktK20.mjs.map → renderer-DIDSmoFA.mjs.map} +1 -1
- package/dist/{renderer-BA8YwBRQ.mjs → renderer-DKtP7-fr.mjs} +58 -234
- package/dist/renderer-DKtP7-fr.mjs.map +1 -0
- package/dist/renderer-DLnF-V_h.mjs +5 -0
- package/dist/renderer-DN1rjmcL.mjs +5 -0
- package/dist/{renderer-BZmfKIom.mjs → renderer-DOEsFT7Q.mjs} +57 -192
- package/dist/renderer-DOEsFT7Q.mjs.map +1 -0
- package/dist/{renderer-6GeDT4Mx.mjs → renderer-DPYB6ZcB.mjs} +57 -197
- package/dist/renderer-DPYB6ZcB.mjs.map +1 -0
- package/dist/{renderer-DCkSR2Ne.mjs → renderer-DRsPCkxr.mjs} +76 -210
- package/dist/renderer-DRsPCkxr.mjs.map +1 -0
- package/dist/renderer-DXTw9Oqb.mjs +5 -0
- package/dist/{renderer-DAMJZNtX.mjs → renderer-DZLJnnU2.mjs} +63 -190
- package/dist/renderer-DZLJnnU2.mjs.map +1 -0
- package/dist/{renderer-BtRfKx5N.mjs → renderer-DZrQffIP.mjs} +56 -167
- package/dist/renderer-DZrQffIP.mjs.map +1 -0
- package/dist/renderer-DbAVSBNI.mjs +5 -0
- package/dist/renderer-Dg8rD--8.mjs +5 -0
- package/dist/{renderer-BpCxKWQm.mjs → renderer-DhEyjn6Q.mjs} +52 -202
- package/dist/renderer-DhEyjn6Q.mjs.map +1 -0
- package/dist/{renderer-CIYcdZuZ.mjs → renderer-Dmv_Aj6x.mjs} +161 -457
- package/dist/renderer-Dmv_Aj6x.mjs.map +1 -0
- package/dist/renderer-DnFxegGu.mjs +5 -0
- package/dist/renderer-DnfmelHn.mjs +5 -0
- package/dist/{renderer-DxtHmyAa.mjs → renderer-Dpj68gTn.mjs} +11 -18
- package/dist/renderer-Dpj68gTn.mjs.map +1 -0
- package/dist/renderer-DuOjzggd.mjs +5 -0
- package/dist/renderer-DuuOlYIG.mjs +3 -0
- package/dist/renderer-DvYql0Cl.mjs +5 -0
- package/dist/{renderer-xKOVmd2O.mjs → renderer-DzhRNdBS.mjs} +245 -231
- package/dist/renderer-DzhRNdBS.mjs.map +1 -0
- package/dist/renderer-GSFP7v2z.mjs +3 -0
- package/dist/renderer-LfUdjgjF.mjs +5 -0
- package/dist/{renderer-CfeoxM_3.mjs → renderer-Q63y7HP_.mjs} +8 -15
- package/dist/renderer-Q63y7HP_.mjs.map +1 -0
- package/dist/renderer-SecCv3U8.mjs +5 -0
- package/dist/{renderer-b6sZN90h.mjs → renderer-mp1NN5zk.mjs} +4 -4
- package/dist/{renderer-b6sZN90h.mjs.map → renderer-mp1NN5zk.mjs.map} +1 -1
- package/dist/renderer-oZyoB4CT.mjs +5 -0
- package/dist/renderer-rzci_kTy.mjs +5 -0
- package/dist/{renderer-CpkiHRhh.mjs → renderer-to9DwqXK.mjs} +17 -99
- package/dist/renderer-to9DwqXK.mjs.map +1 -0
- package/dist/{renderer-CepMDQ06.mjs → renderer-v0vuUUUI.mjs} +19 -106
- package/dist/renderer-v0vuUUUI.mjs.map +1 -0
- package/dist/renderer-vLaZuZbX.mjs +5 -0
- package/dist/{renderers-CP8CFWDs-BLgwUYX2.mjs → renderers-CP8CFWDs-DlFq8jmz.mjs} +4 -4
- package/dist/{renderers-CP8CFWDs-BLgwUYX2.mjs.map → renderers-CP8CFWDs-DlFq8jmz.mjs.map} +1 -1
- package/dist/signals/index.d.mts +5 -5
- package/dist/signals/index.mjs +7 -7
- package/dist/{signals-CsxqD2AA.mjs → signals-BDkO0xcZ.mjs} +3 -3
- package/dist/{signals-CsxqD2AA.mjs.map → signals-BDkO0xcZ.mjs.map} +1 -1
- package/dist/{signin-Db08vl-g.mjs → signin-SVSXQw9i.mjs} +9 -9
- package/dist/{signin-Db08vl-g.mjs.map → signin-SVSXQw9i.mjs.map} +1 -1
- package/dist/{sso-oidc-CpLz_lIu.mjs → sso-oidc-B3Sagl43.mjs} +9 -9
- package/dist/{sso-oidc-CpLz_lIu.mjs.map → sso-oidc-B3Sagl43.mjs.map} +1 -1
- package/dist/{sts-BQefGuml.mjs → sts-CYeWec9i.mjs} +2 -2
- package/dist/{sts-Dgl0kH-t.mjs → sts-ClVtt-bV.mjs} +9 -9
- package/dist/{sts-Dgl0kH-t.mjs.map → sts-ClVtt-bV.mjs.map} +1 -1
- package/package.json +55 -55
- package/dist/dist-B9Afsv83.mjs.map +0 -1
- package/dist/dist-B9PkqWnN.mjs.map +0 -1
- package/dist/dist-BFjSQP7i.mjs.map +0 -1
- package/dist/dist-DzUJmIHt.mjs.map +0 -1
- package/dist/dist-cjs-3pon9kTt.mjs +0 -6
- package/dist/fonts-DhEQ5h6E.mjs.map +0 -1
- package/dist/index-CQcdKyxF.d.mts.map +0 -1
- package/dist/index-D1zaOwEU.d.mts.map +0 -1
- package/dist/index-J9CIK_nu.d.mts.map +0 -1
- package/dist/preview-engine/chunk-36YGYLKD.mjs +0 -58
- package/dist/preview-engine/chunk-5JD65JSJ.mjs +0 -110
- package/dist/preview-engine/chunk-7O24H4YT.mjs +0 -117
- package/dist/preview-engine/chunk-AG5JNZYQ.mjs +0 -8
- package/dist/preview-engine/chunk-AUFSM5KI.mjs +0 -141
- package/dist/preview-engine/chunk-BQ65MU6H.mjs +0 -138
- package/dist/preview-engine/chunk-BWDARDO6.mjs +0 -117
- package/dist/preview-engine/chunk-CNSHAFEA.mjs +0 -1
- package/dist/preview-engine/chunk-DLXQDDIN.mjs +0 -46
- package/dist/preview-engine/chunk-EJGLUZMW.mjs +0 -1
- package/dist/preview-engine/chunk-FE6RSVKZ.mjs +0 -73
- package/dist/preview-engine/chunk-HPIULG7P.mjs +0 -111
- package/dist/preview-engine/chunk-HRIKNYPF.mjs +0 -60
- package/dist/preview-engine/chunk-JPXQPP6J.mjs +0 -1
- package/dist/preview-engine/chunk-K52S5DJX.mjs +0 -109
- package/dist/preview-engine/chunk-MJM3NFEC.mjs +0 -315
- package/dist/preview-engine/chunk-NRHSNPZV.mjs +0 -182
- package/dist/preview-engine/chunk-OWOSYNMF.mjs +0 -104
- package/dist/preview-engine/chunk-QGBSLNFI.mjs +0 -52
- package/dist/preview-engine/chunk-QM3XFEJN.mjs +0 -63
- package/dist/preview-engine/chunk-QTKJXDIW.mjs +0 -997
- package/dist/preview-engine/chunk-R3ZH7YF3.mjs +0 -89
- package/dist/preview-engine/chunk-R6YNSBKL.mjs +0 -108
- package/dist/preview-engine/chunk-RNOO4UR5.mjs +0 -3
- package/dist/preview-engine/chunk-S4CSX6K5.mjs +0 -610
- package/dist/preview-engine/chunk-SNYAHQ25.mjs +0 -186
- package/dist/preview-engine/chunk-SRT2OCQW.mjs +0 -1
- package/dist/preview-engine/chunk-SUUUYXXT.mjs +0 -1
- package/dist/preview-engine/chunk-T6CC2KCZ.mjs +0 -418
- package/dist/preview-engine/chunk-T6COGNOW.mjs +0 -134
- package/dist/preview-engine/chunk-UC7CSW2A.mjs +0 -1
- package/dist/preview-engine/chunk-XFYXT76H.mjs +0 -52
- package/dist/preview-engine/chunk-XUM42I4R.mjs +0 -1
- package/dist/preview-engine/chunk-YITWSOG4.mjs +0 -103
- package/dist/preview-engine/chunk-ZDCA6NVT.mjs +0 -82
- package/dist/preview-engine/chunk-ZNGOAGAI.mjs +0 -1
- package/dist/preview-engine/renderers-27Q5X3U6.mjs +0 -1
- package/dist/preview-engine/renderers-32PIFHPS.mjs +0 -1
- package/dist/preview-engine/renderers-3Y3EMRDJ.mjs +0 -1
- package/dist/preview-engine/renderers-4AHH6BHF.mjs +0 -1
- package/dist/preview-engine/renderers-6PRVCTYV.mjs +0 -1
- package/dist/preview-engine/renderers-76PQY2SO.mjs +0 -1
- package/dist/preview-engine/renderers-7HNVXNAI.mjs +0 -248
- package/dist/preview-engine/renderers-B52QT6MT.mjs +0 -55
- package/dist/preview-engine/renderers-BE6RVJSE.mjs +0 -1
- package/dist/preview-engine/renderers-BMM2BH56.mjs +0 -1
- package/dist/preview-engine/renderers-CHJWUJVI.mjs +0 -1
- package/dist/preview-engine/renderers-CHOGQHVQ.mjs +0 -1
- package/dist/preview-engine/renderers-CI2GXWLP.mjs +0 -1
- package/dist/preview-engine/renderers-CRKRWR2Y.mjs +0 -1
- package/dist/preview-engine/renderers-DEYDSGJX.mjs +0 -1
- package/dist/preview-engine/renderers-DZTNRCR7.mjs +0 -1
- package/dist/preview-engine/renderers-EE2GFG7J.mjs +0 -1
- package/dist/preview-engine/renderers-ELO3KWTK.mjs +0 -1
- package/dist/preview-engine/renderers-F2KJNDWA.mjs +0 -124
- package/dist/preview-engine/renderers-FCV4COVB.mjs +0 -1
- package/dist/preview-engine/renderers-GJSUN5HU.mjs +0 -1
- package/dist/preview-engine/renderers-GXCRINGC.mjs +0 -1
- package/dist/preview-engine/renderers-IHKORHMT.mjs +0 -1
- package/dist/preview-engine/renderers-JA4SLMG3.mjs +0 -1
- package/dist/preview-engine/renderers-JLN77CFZ.mjs +0 -1
- package/dist/preview-engine/renderers-KBFW7B5F.mjs +0 -1
- package/dist/preview-engine/renderers-LJRJMFCR.mjs +0 -1
- package/dist/preview-engine/renderers-LPAPZ5QS.mjs +0 -1
- package/dist/preview-engine/renderers-NQUDQEHY.mjs +0 -1
- package/dist/preview-engine/renderers-NS3AIJVG.mjs +0 -1
- package/dist/preview-engine/renderers-NSY2SDIE.mjs +0 -1
- package/dist/preview-engine/renderers-PW4OJWHF.mjs +0 -120
- package/dist/preview-engine/renderers-PWLWOZY4.mjs +0 -1
- package/dist/preview-engine/renderers-Q3MD34JN.mjs +0 -1
- package/dist/preview-engine/renderers-RXGNA2Q7.mjs +0 -1
- package/dist/preview-engine/renderers-UGZUPONY.mjs +0 -1
- package/dist/preview-engine/renderers-VTTGFO55.mjs +0 -1
- package/dist/preview-engine/renderers-W3VVM5HB.mjs +0 -1
- package/dist/preview-engine/renderers-WG7QBD4D.mjs +0 -1
- package/dist/preview-engine/renderers-WLLJFZTF.mjs +0 -1
- package/dist/preview-engine/renderers-WN4SYFCU.mjs +0 -1
- package/dist/preview-engine/renderers-WSMLLSWX.mjs +0 -1
- package/dist/preview-engine/renderers-XFBSGTHU.mjs +0 -1
- package/dist/preview-engine/renderers-XFC6ZPO5.mjs +0 -1
- package/dist/preview-engine/renderers-XUHRY3XH.mjs +0 -1
- package/dist/preview-engine/renderers-YAOB5XU6.mjs +0 -1
- package/dist/preview-engine/renderers-YTB4FOHT.mjs +0 -1
- package/dist/program-xRfFoPxe.mjs.map +0 -1
- package/dist/renderer-6GeDT4Mx.mjs.map +0 -1
- package/dist/renderer-8qpGxSSO.mjs.map +0 -1
- package/dist/renderer-9wp5R7PL.mjs.map +0 -1
- package/dist/renderer-B2XzjK0z.mjs +0 -3
- package/dist/renderer-B4F6wL68.mjs +0 -3
- package/dist/renderer-B4i1jmiT.mjs +0 -3
- package/dist/renderer-B5ylY3uM.mjs +0 -3
- package/dist/renderer-BA8YwBRQ.mjs.map +0 -1
- package/dist/renderer-BGXbGqY4.mjs.map +0 -1
- package/dist/renderer-BM05sB8m.mjs.map +0 -1
- package/dist/renderer-BPw23wiR.mjs +0 -3
- package/dist/renderer-BREIjsUU.mjs.map +0 -1
- package/dist/renderer-BTu2EVhF.mjs +0 -3
- package/dist/renderer-BZmfKIom.mjs.map +0 -1
- package/dist/renderer-BfJSUjPN.mjs +0 -3
- package/dist/renderer-BgdkEFmv.mjs.map +0 -1
- package/dist/renderer-BghW-bSZ.mjs +0 -3
- package/dist/renderer-BpCxKWQm.mjs.map +0 -1
- package/dist/renderer-BtRfKx5N.mjs.map +0 -1
- package/dist/renderer-But0u-xi.mjs.map +0 -1
- package/dist/renderer-Bw3oZ9YT.mjs +0 -3
- package/dist/renderer-C-H680_l.mjs +0 -3
- package/dist/renderer-C2009W-_.mjs +0 -3
- package/dist/renderer-C36yoGXG.mjs +0 -3
- package/dist/renderer-CDLrNgfo.mjs +0 -3
- package/dist/renderer-CIYcdZuZ.mjs.map +0 -1
- package/dist/renderer-CJNyhr_S.mjs.map +0 -1
- package/dist/renderer-CL3evUmF.mjs +0 -3
- package/dist/renderer-CM1_2ZWA.mjs +0 -3
- package/dist/renderer-CNF10fCq.mjs.map +0 -1
- package/dist/renderer-CQdVj2JS.mjs +0 -3
- package/dist/renderer-CQiTodg9.mjs +0 -337
- package/dist/renderer-CQiTodg9.mjs.map +0 -1
- package/dist/renderer-CWlzudP8.mjs +0 -3
- package/dist/renderer-CZgB5st8.mjs +0 -3
- package/dist/renderer-CcU7dVn9.mjs.map +0 -1
- package/dist/renderer-Cd5vzrGs.mjs +0 -3
- package/dist/renderer-CeJ_vDXI.mjs +0 -3
- package/dist/renderer-CepMDQ06.mjs.map +0 -1
- package/dist/renderer-CfeoxM_3.mjs.map +0 -1
- package/dist/renderer-CjY77sB_.mjs +0 -3
- package/dist/renderer-CkykdR_D.mjs +0 -3
- package/dist/renderer-CoZKST2Y.mjs.map +0 -1
- package/dist/renderer-CpkiHRhh.mjs.map +0 -1
- package/dist/renderer-CroHPOsX.mjs.map +0 -1
- package/dist/renderer-CtVkU_GA.mjs +0 -44
- package/dist/renderer-CtVkU_GA.mjs.map +0 -1
- package/dist/renderer-CzPWB0Ss.mjs.map +0 -1
- package/dist/renderer-D-4Yh-RK.mjs.map +0 -1
- package/dist/renderer-D2XD4QYk.mjs.map +0 -1
- package/dist/renderer-D5Z6mda5.mjs +0 -3
- package/dist/renderer-D7ztfQHX.mjs.map +0 -1
- package/dist/renderer-D7zvPHKn.mjs.map +0 -1
- package/dist/renderer-D9NnIx7o.mjs +0 -3
- package/dist/renderer-DAMJZNtX.mjs.map +0 -1
- package/dist/renderer-DCJa7OGk.mjs +0 -3
- package/dist/renderer-DCkSR2Ne.mjs.map +0 -1
- package/dist/renderer-DEJwPRkR.mjs.map +0 -1
- package/dist/renderer-DGwSl7g1.mjs +0 -3
- package/dist/renderer-DNNqpK7t.mjs.map +0 -1
- package/dist/renderer-DNoRNfMm.mjs +0 -3
- package/dist/renderer-DOZ8bpyY.mjs +0 -3
- package/dist/renderer-DRHyRNU8.mjs +0 -3
- package/dist/renderer-DTvfYkI9.mjs.map +0 -1
- package/dist/renderer-DYm4duFr.mjs.map +0 -1
- package/dist/renderer-DZGtBUCx.mjs.map +0 -1
- package/dist/renderer-D_1oDOCP.mjs.map +0 -1
- package/dist/renderer-DdVBt8Rz.mjs.map +0 -1
- package/dist/renderer-DjTiNeAp.mjs.map +0 -1
- package/dist/renderer-Dju9CaeL.mjs.map +0 -1
- package/dist/renderer-DlD85Xoi.mjs +0 -3
- package/dist/renderer-Dr0bgOrW.mjs +0 -3
- package/dist/renderer-DurtG-Hc.mjs +0 -3
- package/dist/renderer-DxtHmyAa.mjs.map +0 -1
- package/dist/renderer-_bygZSKk.mjs.map +0 -1
- package/dist/renderer-_uvdg48N.mjs.map +0 -1
- package/dist/renderer-d5-F_48R.mjs +0 -3
- package/dist/renderer-eFv9HBmL.mjs +0 -3
- package/dist/renderer-ho_jXJ0H.mjs.map +0 -1
- package/dist/renderer-iuV6wQoL.mjs +0 -4
- package/dist/renderer-jkZ_IQnW.mjs.map +0 -1
- package/dist/renderer-n-uuWPF4.mjs +0 -3
- package/dist/renderer-rzccTFuY.mjs +0 -3
- package/dist/renderer-wVldKtFU.mjs.map +0 -1
- package/dist/renderer-xKOVmd2O.mjs.map +0 -1
- package/dist/renderer-y9eGFPFL.mjs +0 -3
- /package/dist/{renderer-C2n-EHxg.mjs → renderer-B-BcgA6d.mjs} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as ColorSchema } from "./dist-
|
|
3
|
-
import {
|
|
1
|
+
import { Bt as parseCssColor, Lt as mixColors, Vt as parseCssGradient, ht as createVirtualMedia, l as Color, wt as getActiveMediaMetadata } from "./dist-fjKpBYkc.mjs";
|
|
2
|
+
import { t as ColorSchema } from "./dist-BY0bIWgr.mjs";
|
|
3
|
+
import { $t as TypewriterAnimatorSchema, An as signalRegistry, Kt as TextPathOptionsSchema, ht as AdvancedTextAnimatorSchema, kt as KineticMarqueeConfigSchema, pt as AETextAnimatorSchema } from "./dist-Bun_TUvZ.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { loadYoga } from "yoga-layout/load";
|
|
6
6
|
|
|
@@ -385,6 +385,36 @@ function collectInlineSignals(nodes, out = {}) {
|
|
|
385
385
|
}
|
|
386
386
|
return out;
|
|
387
387
|
}
|
|
388
|
+
const isKeyframeTrack = (t) => !t.source || t.source.type === "keyframe";
|
|
389
|
+
/**
|
|
390
|
+
* Merges keyframe tracks that animate the same prop into one sorted track,
|
|
391
|
+
* the later key winning on a shared frame. Procedural tracks (signal,
|
|
392
|
+
* wiggle, spring…) pass through untouched.
|
|
393
|
+
*/
|
|
394
|
+
function mergeAnimationTracks(tracks) {
|
|
395
|
+
const out = [];
|
|
396
|
+
const byProp = /* @__PURE__ */ new Map();
|
|
397
|
+
for (const t of tracks) {
|
|
398
|
+
if (!isKeyframeTrack(t)) {
|
|
399
|
+
out.push(t);
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
const existing = byProp.get(t.prop);
|
|
403
|
+
if (!existing) {
|
|
404
|
+
const copy = {
|
|
405
|
+
...t,
|
|
406
|
+
keyframes: [...t.keyframes ?? []]
|
|
407
|
+
};
|
|
408
|
+
byProp.set(t.prop, copy);
|
|
409
|
+
out.push(copy);
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const frames = new Map(existing.keyframes.map((k) => [k.frame, k]));
|
|
413
|
+
for (const k of t.keyframes ?? []) frames.set(k.frame, k);
|
|
414
|
+
existing.keyframes = [...frames.values()].sort((a, b) => a.frame - b.frame);
|
|
415
|
+
}
|
|
416
|
+
return out;
|
|
417
|
+
}
|
|
388
418
|
function evaluateEasingProgress(ease, t) {
|
|
389
419
|
if (!ease) return t;
|
|
390
420
|
const ref = parseEase(ease);
|
|
@@ -586,12 +616,15 @@ var LayerAnimation = class LayerAnimation$1 {
|
|
|
586
616
|
this.tracks.push(track);
|
|
587
617
|
}
|
|
588
618
|
const parsedEase = parseEase(ease);
|
|
589
|
-
|
|
619
|
+
const kf = {
|
|
590
620
|
id: `k_${track.keyframes.length}_f${frame}`,
|
|
591
621
|
frame,
|
|
592
622
|
value,
|
|
593
623
|
...parsedEase && { ease: parsedEase }
|
|
594
|
-
}
|
|
624
|
+
};
|
|
625
|
+
const at = track.keyframes.findIndex((k) => k.frame === frame);
|
|
626
|
+
if (at >= 0) track.keyframes[at] = kf;
|
|
627
|
+
else track.keyframes.push(kf);
|
|
595
628
|
track.keyframes.sort((a, b) => a.frame - b.frame);
|
|
596
629
|
return this;
|
|
597
630
|
}
|
|
@@ -968,6 +1001,19 @@ var LayerAnimation = class LayerAnimation$1 {
|
|
|
968
1001
|
return node;
|
|
969
1002
|
}
|
|
970
1003
|
/**
|
|
1004
|
+
* Folds other animations into this one. Keyframe tracks on the same prop
|
|
1005
|
+
* merge into one track (a later key wins on a shared frame), so separate
|
|
1006
|
+
* behaviours — an entrance, presses, a wave — can be authored apart:
|
|
1007
|
+
* `LayerAnimation.merge(rainIn, presses, wave)`.
|
|
1008
|
+
*/
|
|
1009
|
+
merge(...others) {
|
|
1010
|
+
this.tracks = mergeAnimationTracks([...this.tracks, ...others.flatMap((o) => o.tracks)]);
|
|
1011
|
+
return this;
|
|
1012
|
+
}
|
|
1013
|
+
static merge(...anims) {
|
|
1014
|
+
return new LayerAnimation$1().merge(...anims);
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
971
1017
|
* Returns the validated LayerAnimation specification object.
|
|
972
1018
|
*/
|
|
973
1019
|
toSpec() {
|
|
@@ -1467,17 +1513,9 @@ function parseHexColor(hex) {
|
|
|
1467
1513
|
1
|
|
1468
1514
|
];
|
|
1469
1515
|
}
|
|
1516
|
+
/** Color keyframes blend perceptually (OKLab) and accept any CSS color. */
|
|
1470
1517
|
function lerpColor(c1, c2, t) {
|
|
1471
|
-
|
|
1472
|
-
const [r1, g1, b1, a1] = parseHexColor(c1);
|
|
1473
|
-
const [r2, g2, b2, a2] = parseHexColor(c2);
|
|
1474
|
-
const r = Math.round(lerp(r1, r2, t));
|
|
1475
|
-
const g = Math.round(lerp(g1, g2, t));
|
|
1476
|
-
const b = Math.round(lerp(b1, b2, t));
|
|
1477
|
-
const a = lerp(a1, a2, t);
|
|
1478
|
-
const toHex = (n) => n.toString(16).padStart(2, "0");
|
|
1479
|
-
if (a >= .999) return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
1480
|
-
return `rgba(${r}, ${g}, ${b}, ${Math.round(a * 100) / 100})`;
|
|
1518
|
+
return mixColors(c1, c2, t);
|
|
1481
1519
|
}
|
|
1482
1520
|
function hueToRgb(p, q, t) {
|
|
1483
1521
|
let tt = t;
|
|
@@ -1529,7 +1567,7 @@ function rotateHue(hex, delta) {
|
|
|
1529
1567
|
if (a >= .999) return `#${toHex(newR)}${toHex(newG)}${toHex(newB)}`;
|
|
1530
1568
|
return `rgba(${Math.round(newR * 255)}, ${Math.round(newG * 255)}, ${Math.round(newB * 255)}, ${Math.round(a * 100) / 100})`;
|
|
1531
1569
|
}
|
|
1532
|
-
const COLOR_PROPS = new Set([
|
|
1570
|
+
const COLOR_PROPS$1 = new Set([
|
|
1533
1571
|
"fill",
|
|
1534
1572
|
"fillColor",
|
|
1535
1573
|
"strokeColor",
|
|
@@ -1589,7 +1627,7 @@ function evaluateTrackAtFrame(track, frame, fps = 24, context = {}) {
|
|
|
1589
1627
|
}
|
|
1590
1628
|
case "signal": {
|
|
1591
1629
|
const sigVal = evaluateSignal(source, frame, fps, context.signals);
|
|
1592
|
-
if (COLOR_PROPS.has(track.prop)) {
|
|
1630
|
+
if (COLOR_PROPS$1.has(track.prop)) {
|
|
1593
1631
|
const src = source;
|
|
1594
1632
|
const colorA = src.colorA ?? "#ffffff";
|
|
1595
1633
|
const colorB = src.colorB ?? "#ffffff";
|
|
@@ -1613,2268 +1651,168 @@ function evaluateAnimationAtFrame(animation, frame, fps = 24, context = {}) {
|
|
|
1613
1651
|
return result;
|
|
1614
1652
|
}
|
|
1615
1653
|
/**
|
|
1616
|
-
*
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
props = {};
|
|
1621
|
-
selectors = [];
|
|
1622
|
-
constructor(name) {
|
|
1623
|
-
this.name = name;
|
|
1624
|
-
}
|
|
1625
|
-
static create(name) {
|
|
1626
|
-
return new AdvancedTextAnimatorBuilder$1(name);
|
|
1627
|
-
}
|
|
1628
|
-
/** Directional Skew */
|
|
1629
|
-
skew(angleDeg, axisDeg = 0) {
|
|
1630
|
-
this.props.skew = angleDeg;
|
|
1631
|
-
this.props.skewAxis = axisDeg;
|
|
1632
|
-
return this;
|
|
1633
|
-
}
|
|
1634
|
-
/** Anchor Point Grouping and Preset Pivot */
|
|
1635
|
-
anchor(preset, grouping = "character", offsetX = 0, offsetY = 0) {
|
|
1636
|
-
this.props.anchor = {
|
|
1637
|
-
grouping,
|
|
1638
|
-
preset,
|
|
1639
|
-
anchorX: .5,
|
|
1640
|
-
anchorY: .5,
|
|
1641
|
-
offsetX,
|
|
1642
|
-
offsetY
|
|
1643
|
-
};
|
|
1644
|
-
return this;
|
|
1645
|
-
}
|
|
1646
|
-
/** Custom Anchor Point Coordinates (0 to 1 normalized) */
|
|
1647
|
-
anchorNormalized(ax, ay, grouping = "character") {
|
|
1648
|
-
this.props.anchor = {
|
|
1649
|
-
grouping,
|
|
1650
|
-
preset: "custom",
|
|
1651
|
-
anchorX: ax,
|
|
1652
|
-
anchorY: ay,
|
|
1653
|
-
offsetX: 0,
|
|
1654
|
-
offsetY: 0
|
|
1655
|
-
};
|
|
1656
|
-
return this;
|
|
1657
|
-
}
|
|
1658
|
-
/** 3D Spatial Z-Depth */
|
|
1659
|
-
translateZ(zPixels) {
|
|
1660
|
-
this.props.translateZ = zPixels;
|
|
1661
|
-
return this;
|
|
1662
|
-
}
|
|
1663
|
-
/** 3D Tilts */
|
|
1664
|
-
tilt3D(rx = 0, ry = 0, rz = 0) {
|
|
1665
|
-
this.props.rotationX = rx;
|
|
1666
|
-
this.props.rotationY = ry;
|
|
1667
|
-
this.props.rotationZ = rz;
|
|
1668
|
-
return this;
|
|
1669
|
-
}
|
|
1670
|
-
/** 3D Rotation along X axis */
|
|
1671
|
-
rotationX(deg) {
|
|
1672
|
-
this.props.rotationX = deg;
|
|
1673
|
-
return this;
|
|
1674
|
-
}
|
|
1675
|
-
/** 3D Rotation along Y axis */
|
|
1676
|
-
rotationY(deg) {
|
|
1677
|
-
this.props.rotationY = deg;
|
|
1678
|
-
return this;
|
|
1679
|
-
}
|
|
1680
|
-
/** 3D Rotation along Z axis */
|
|
1681
|
-
rotationZ(deg) {
|
|
1682
|
-
this.props.rotationZ = deg;
|
|
1683
|
-
return this;
|
|
1684
|
-
}
|
|
1685
|
-
/** 3D Volumetric Formations */
|
|
1686
|
-
volumetricFormation(mode = "cylinder", radius = 300, pitch = 120, totalAngle = 360, perspective = 1200, axis = "y") {
|
|
1687
|
-
this.props.formation = {
|
|
1688
|
-
mode,
|
|
1689
|
-
radius,
|
|
1690
|
-
pitch,
|
|
1691
|
-
totalAngle,
|
|
1692
|
-
perspective,
|
|
1693
|
-
axis
|
|
1694
|
-
};
|
|
1695
|
-
return this;
|
|
1696
|
-
}
|
|
1697
|
-
/** Dynamic Line Spacing (Leading) */
|
|
1698
|
-
lineSpacing(extraLeadingPixels, lineAnchor = 0) {
|
|
1699
|
-
this.props.lineSpacing = extraLeadingPixels;
|
|
1700
|
-
this.props.lineAnchor = lineAnchor;
|
|
1701
|
-
return this;
|
|
1702
|
-
}
|
|
1703
|
-
/** Normalized Line Anchor (0=top, 0.5=center, 1=bottom) */
|
|
1704
|
-
lineAnchor(anchor) {
|
|
1705
|
-
this.props.lineAnchor = anchor;
|
|
1706
|
-
return this;
|
|
1707
|
-
}
|
|
1708
|
-
/** Inertial Spring Settling Physics */
|
|
1709
|
-
spring(stiffness = 180, damping = 12, mass = 1, initialVelocity = 0) {
|
|
1710
|
-
this.props.spring = {
|
|
1711
|
-
stiffness,
|
|
1712
|
-
damping,
|
|
1713
|
-
mass,
|
|
1714
|
-
initialVelocity,
|
|
1715
|
-
overshootMultiplier: 1
|
|
1716
|
-
};
|
|
1717
|
-
return this;
|
|
1718
|
-
}
|
|
1719
|
-
/** Dynamic Stroke & Wireframe Properties */
|
|
1720
|
-
stroke(widthPixels, color = "#ffffff", fillOpacity = 1) {
|
|
1721
|
-
this.props.stroke = {
|
|
1722
|
-
strokeWidth: widthPixels,
|
|
1723
|
-
strokeColor: color,
|
|
1724
|
-
strokeAlign: "center",
|
|
1725
|
-
fillOpacity,
|
|
1726
|
-
dashOffset: 0
|
|
1727
|
-
};
|
|
1728
|
-
return this;
|
|
1729
|
-
}
|
|
1730
|
-
/** Variable Font Axes */
|
|
1731
|
-
variableFont(axes) {
|
|
1732
|
-
this.props.variableAxes = axes;
|
|
1733
|
-
return this;
|
|
1734
|
-
}
|
|
1735
|
-
/** Chromatic Aberration / Cyberpunk Glitch */
|
|
1736
|
-
chromaticGlitch(redShiftX, redShiftY = 0, blueShiftX = -redShiftX, blueShiftY = 0) {
|
|
1737
|
-
this.props.chromaticGlitch = {
|
|
1738
|
-
redShiftX,
|
|
1739
|
-
redShiftY,
|
|
1740
|
-
blueShiftX,
|
|
1741
|
-
blueShiftY,
|
|
1742
|
-
sliceProbability: 0,
|
|
1743
|
-
sliceAmplitude: 0
|
|
1744
|
-
};
|
|
1745
|
-
return this;
|
|
1746
|
-
}
|
|
1747
|
-
/** Multi-Band Audio Spectrum Equalizer */
|
|
1748
|
-
audioSpectrum(signalChannel, minFreqHz = 60, maxFreqHz = 16e3, maxScale = 2.5) {
|
|
1749
|
-
this.props.audioSpectrum = {
|
|
1750
|
-
signalChannel,
|
|
1751
|
-
minFreqHz,
|
|
1752
|
-
maxFreqHz,
|
|
1753
|
-
scaleAxis: "scaleY",
|
|
1754
|
-
minScale: .2,
|
|
1755
|
-
maxScale,
|
|
1756
|
-
peakDecay: .8
|
|
1757
|
-
};
|
|
1758
|
-
return this;
|
|
1759
|
-
}
|
|
1760
|
-
/** Long Shadow Extrusion */
|
|
1761
|
-
longShadow(angle = 45, length = 40, color = "#000000", startOpacity = .8, endOpacity = 0, steps = 16) {
|
|
1762
|
-
this.props.longShadow = {
|
|
1763
|
-
angle,
|
|
1764
|
-
length,
|
|
1765
|
-
color,
|
|
1766
|
-
startOpacity,
|
|
1767
|
-
endOpacity,
|
|
1768
|
-
steps
|
|
1769
|
-
};
|
|
1770
|
-
return this;
|
|
1771
|
-
}
|
|
1772
|
-
/** Particle Dust / Quantum Dissolve */
|
|
1773
|
-
particleDissolve(progress = 0, dispersalAngle = 90, maxDisplacement = 120) {
|
|
1774
|
-
this.props.particleDissolve = {
|
|
1775
|
-
progress,
|
|
1776
|
-
dispersalAngle,
|
|
1777
|
-
maxDisplacement,
|
|
1778
|
-
turbulence: .5,
|
|
1779
|
-
particleSize: 2
|
|
1780
|
-
};
|
|
1781
|
-
return this;
|
|
1782
|
-
}
|
|
1783
|
-
/** Add Expression Selector */
|
|
1784
|
-
addExpressionSelector(expression, mode = "add") {
|
|
1785
|
-
this.selectors.push({
|
|
1786
|
-
type: "expression",
|
|
1787
|
-
expression,
|
|
1788
|
-
mode,
|
|
1789
|
-
amount: 1
|
|
1790
|
-
});
|
|
1791
|
-
return this;
|
|
1792
|
-
}
|
|
1793
|
-
/** Alias for addExpressionSelector */
|
|
1794
|
-
expressionSelector(expression, mode = "add") {
|
|
1795
|
-
return this.addExpressionSelector(expression, mode);
|
|
1796
|
-
}
|
|
1797
|
-
/** Standard 2D Transforms */
|
|
1798
|
-
x(v) {
|
|
1799
|
-
this.props.x = v;
|
|
1800
|
-
return this;
|
|
1801
|
-
}
|
|
1802
|
-
y(v) {
|
|
1803
|
-
this.props.y = v;
|
|
1804
|
-
return this;
|
|
1805
|
-
}
|
|
1806
|
-
scale(v) {
|
|
1807
|
-
this.props.scale = v;
|
|
1808
|
-
return this;
|
|
1809
|
-
}
|
|
1810
|
-
scaleX(v) {
|
|
1811
|
-
this.props.scaleX = v;
|
|
1812
|
-
return this;
|
|
1813
|
-
}
|
|
1814
|
-
scaleY(v) {
|
|
1815
|
-
this.props.scaleY = v;
|
|
1816
|
-
return this;
|
|
1817
|
-
}
|
|
1818
|
-
rotation(deg) {
|
|
1819
|
-
this.props.rotation = deg;
|
|
1820
|
-
return this;
|
|
1821
|
-
}
|
|
1822
|
-
opacity(v) {
|
|
1823
|
-
this.props.opacity = v;
|
|
1824
|
-
return this;
|
|
1825
|
-
}
|
|
1826
|
-
blur(v) {
|
|
1827
|
-
this.props.blur = v;
|
|
1828
|
-
return this;
|
|
1829
|
-
}
|
|
1830
|
-
fillColor(hex) {
|
|
1831
|
-
this.props.fillColor = hex;
|
|
1832
|
-
return this;
|
|
1833
|
-
}
|
|
1834
|
-
build() {
|
|
1835
|
-
return {
|
|
1836
|
-
name: this.name,
|
|
1837
|
-
selectors: this.selectors,
|
|
1838
|
-
props: this.props
|
|
1839
|
-
};
|
|
1840
|
-
}
|
|
1841
|
-
};
|
|
1842
|
-
/**
|
|
1843
|
-
* @file packages/compositions/src/program/text-animations/advanced-types.ts
|
|
1844
|
-
* Data contracts and Zod schemas for Advanced Motion Design & After Effects Extended Typography Engine.
|
|
1845
|
-
*/
|
|
1846
|
-
const AnchorGroupingSchema = z.enum([
|
|
1847
|
-
"character",
|
|
1848
|
-
"word",
|
|
1849
|
-
"line",
|
|
1850
|
-
"all"
|
|
1851
|
-
]);
|
|
1852
|
-
const AnchorPresetSchema = z.enum([
|
|
1853
|
-
"center",
|
|
1854
|
-
"baseline",
|
|
1855
|
-
"bottom_left",
|
|
1856
|
-
"bottom_center",
|
|
1857
|
-
"bottom_right",
|
|
1858
|
-
"top_left",
|
|
1859
|
-
"top_center",
|
|
1860
|
-
"top_right",
|
|
1861
|
-
"custom"
|
|
1862
|
-
]);
|
|
1863
|
-
const TextAnchorConfigSchema = z.object({
|
|
1864
|
-
grouping: AnchorGroupingSchema.default("character"),
|
|
1865
|
-
preset: AnchorPresetSchema.default("center"),
|
|
1866
|
-
anchorX: z.number().default(.5),
|
|
1867
|
-
anchorY: z.number().default(.5),
|
|
1868
|
-
offsetX: z.number().default(0),
|
|
1869
|
-
offsetY: z.number().default(0)
|
|
1870
|
-
});
|
|
1871
|
-
const SkewPropertiesSchema = z.object({
|
|
1872
|
-
skew: z.number().min(-90).max(90),
|
|
1873
|
-
skewAxis: z.number().default(0)
|
|
1874
|
-
});
|
|
1875
|
-
const LineSpacingDynamicsSchema = z.object({
|
|
1876
|
-
lineSpacing: z.number(),
|
|
1877
|
-
lineAnchor: z.number().min(0).max(1).default(0)
|
|
1878
|
-
});
|
|
1879
|
-
const VolumetricFormationModeSchema = z.enum([
|
|
1880
|
-
"planar",
|
|
1881
|
-
"vortex",
|
|
1882
|
-
"cylinder",
|
|
1883
|
-
"helix"
|
|
1884
|
-
]);
|
|
1885
|
-
const VolumetricFormationConfigSchema = z.object({
|
|
1886
|
-
mode: VolumetricFormationModeSchema.default("planar"),
|
|
1887
|
-
radius: z.number().default(300),
|
|
1888
|
-
pitch: z.number().default(120),
|
|
1889
|
-
totalAngle: z.number().default(360),
|
|
1890
|
-
axis: z.enum([
|
|
1891
|
-
"x",
|
|
1892
|
-
"y",
|
|
1893
|
-
"z"
|
|
1894
|
-
]).default("y"),
|
|
1895
|
-
perspective: z.number().positive().default(1200)
|
|
1896
|
-
});
|
|
1897
|
-
const Spatial3DPropertiesSchema = z.object({
|
|
1898
|
-
translateZ: z.number().optional(),
|
|
1899
|
-
rotationX: z.number().optional(),
|
|
1900
|
-
rotationY: z.number().optional(),
|
|
1901
|
-
rotationZ: z.number().optional(),
|
|
1902
|
-
formation: VolumetricFormationConfigSchema.optional()
|
|
1903
|
-
});
|
|
1904
|
-
const SpringPhysicsSchema = z.object({
|
|
1905
|
-
stiffness: z.number().positive().default(180),
|
|
1906
|
-
damping: z.number().positive().default(12),
|
|
1907
|
-
mass: z.number().positive().default(1),
|
|
1908
|
-
initialVelocity: z.number().default(0),
|
|
1909
|
-
overshootMultiplier: z.number().min(.5).max(3).default(1)
|
|
1910
|
-
});
|
|
1911
|
-
const ExpressionSelectorSchema = z.object({
|
|
1912
|
-
type: z.literal("expression"),
|
|
1913
|
-
name: z.string().optional(),
|
|
1914
|
-
expression: z.string(),
|
|
1915
|
-
mode: z.enum([
|
|
1916
|
-
"add",
|
|
1917
|
-
"subtract",
|
|
1918
|
-
"intersect",
|
|
1919
|
-
"min",
|
|
1920
|
-
"max",
|
|
1921
|
-
"difference"
|
|
1922
|
-
]).default("add"),
|
|
1923
|
-
amount: z.number().default(1)
|
|
1924
|
-
});
|
|
1925
|
-
const DynamicStrokePropertiesSchema = z.object({
|
|
1926
|
-
strokeWidth: z.number().min(0).default(0),
|
|
1927
|
-
strokeColor: z.string().default("#ffffff"),
|
|
1928
|
-
strokeAlign: z.enum([
|
|
1929
|
-
"center",
|
|
1930
|
-
"inside",
|
|
1931
|
-
"outside"
|
|
1932
|
-
]).default("center"),
|
|
1933
|
-
fillOpacity: z.number().min(0).max(1).default(1),
|
|
1934
|
-
dashArray: z.tuple([z.number(), z.number()]).optional(),
|
|
1935
|
-
dashOffset: z.number().default(0)
|
|
1936
|
-
});
|
|
1937
|
-
const KineticMarqueeConfigSchema = z.object({
|
|
1938
|
-
direction: z.enum([
|
|
1939
|
-
"left",
|
|
1940
|
-
"right",
|
|
1941
|
-
"up",
|
|
1942
|
-
"down"
|
|
1943
|
-
]).default("left"),
|
|
1944
|
-
velocity: z.number().default(120),
|
|
1945
|
-
loop: z.boolean().default(true),
|
|
1946
|
-
repeatGap: z.number().default(80),
|
|
1947
|
-
snap: z.object({
|
|
1948
|
-
enabled: z.boolean().default(false),
|
|
1949
|
-
granularity: z.enum([
|
|
1950
|
-
"character",
|
|
1951
|
-
"word",
|
|
1952
|
-
"line"
|
|
1953
|
-
]).default("word"),
|
|
1954
|
-
stopIndex: z.number().default(0),
|
|
1955
|
-
decelEase: z.string().default("cubic.out")
|
|
1956
|
-
}).optional()
|
|
1957
|
-
});
|
|
1958
|
-
const VariableFontAxesSchema = z.object({
|
|
1959
|
-
weight: z.number().min(100).max(1e3).optional(),
|
|
1960
|
-
width: z.number().min(50).max(200).optional(),
|
|
1961
|
-
slant: z.number().min(-25).max(25).optional(),
|
|
1962
|
-
italic: z.number().min(0).max(1).optional(),
|
|
1963
|
-
opticalSize: z.number().min(6).max(144).optional()
|
|
1964
|
-
});
|
|
1965
|
-
const ChromaticGlitchConfigSchema = z.object({
|
|
1966
|
-
redShiftX: z.number().default(0),
|
|
1967
|
-
redShiftY: z.number().default(0),
|
|
1968
|
-
blueShiftX: z.number().default(0),
|
|
1969
|
-
blueShiftY: z.number().default(0),
|
|
1970
|
-
sliceProbability: z.number().min(0).max(1).default(0),
|
|
1971
|
-
sliceAmplitude: z.number().default(0)
|
|
1972
|
-
});
|
|
1973
|
-
const AudioSpectrumTypographySchema = z.object({
|
|
1974
|
-
signalChannel: z.string(),
|
|
1975
|
-
minFreqHz: z.number().default(60),
|
|
1976
|
-
maxFreqHz: z.number().default(16e3),
|
|
1977
|
-
scaleAxis: z.enum([
|
|
1978
|
-
"scaleY",
|
|
1979
|
-
"scaleX",
|
|
1980
|
-
"scale",
|
|
1981
|
-
"y"
|
|
1982
|
-
]).default("scaleY"),
|
|
1983
|
-
minScale: z.number().default(.2),
|
|
1984
|
-
maxScale: z.number().default(2.5),
|
|
1985
|
-
peakDecay: z.number().min(0).max(.99).default(.8)
|
|
1986
|
-
});
|
|
1987
|
-
const LongShadowConfigSchema = z.object({
|
|
1988
|
-
angle: z.number().default(45),
|
|
1989
|
-
length: z.number().min(0).default(0),
|
|
1990
|
-
color: z.string().default("#000000"),
|
|
1991
|
-
startOpacity: z.number().min(0).max(1).default(.8),
|
|
1992
|
-
endOpacity: z.number().min(0).max(1).default(0),
|
|
1993
|
-
steps: z.number().int().min(4).max(64).default(16)
|
|
1994
|
-
});
|
|
1995
|
-
const ParticleDissolveConfigSchema = z.object({
|
|
1996
|
-
progress: z.number().min(0).max(1).default(0),
|
|
1997
|
-
dispersalAngle: z.number().default(90),
|
|
1998
|
-
maxDisplacement: z.number().default(120),
|
|
1999
|
-
turbulence: z.number().default(.5),
|
|
2000
|
-
particleSize: z.number().default(2)
|
|
2001
|
-
});
|
|
2002
|
-
const ExtendedGlyphPropertiesSchema = z.object({
|
|
2003
|
-
x: z.number().optional(),
|
|
2004
|
-
y: z.number().optional(),
|
|
2005
|
-
translateZ: z.number().optional(),
|
|
2006
|
-
scale: z.number().optional(),
|
|
2007
|
-
scaleX: z.number().optional(),
|
|
2008
|
-
scaleY: z.number().optional(),
|
|
2009
|
-
rotation: z.number().optional(),
|
|
2010
|
-
rotationX: z.number().optional(),
|
|
2011
|
-
rotationY: z.number().optional(),
|
|
2012
|
-
rotationZ: z.number().optional(),
|
|
2013
|
-
formation: VolumetricFormationConfigSchema.optional(),
|
|
2014
|
-
skew: z.number().optional(),
|
|
2015
|
-
skewAxis: z.number().optional(),
|
|
2016
|
-
tracking: z.number().optional(),
|
|
2017
|
-
lineSpacing: z.number().optional(),
|
|
2018
|
-
lineAnchor: z.number().optional(),
|
|
2019
|
-
anchor: TextAnchorConfigSchema.optional(),
|
|
2020
|
-
opacity: z.number().optional(),
|
|
2021
|
-
blur: z.number().optional(),
|
|
2022
|
-
fillColor: z.string().optional(),
|
|
2023
|
-
stroke: DynamicStrokePropertiesSchema.optional(),
|
|
2024
|
-
variableAxes: VariableFontAxesSchema.optional(),
|
|
2025
|
-
chromaticGlitch: ChromaticGlitchConfigSchema.optional(),
|
|
2026
|
-
longShadow: LongShadowConfigSchema.optional(),
|
|
2027
|
-
particleDissolve: ParticleDissolveConfigSchema.optional(),
|
|
2028
|
-
audioSpectrum: AudioSpectrumTypographySchema.optional(),
|
|
2029
|
-
spring: SpringPhysicsSchema.optional()
|
|
2030
|
-
});
|
|
2031
|
-
const AdvancedTextAnimatorSchema = z.object({
|
|
2032
|
-
name: z.string().default("AdvancedAnimator"),
|
|
2033
|
-
selectors: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
2034
|
-
props: ExtendedGlyphPropertiesSchema
|
|
2035
|
-
});
|
|
2036
|
-
/**
|
|
2037
|
-
* @file packages/compositions/src/program/text-animations/types.ts
|
|
2038
|
-
* Data contracts and Zod schemas for After Effects Parity Text Animation Engine.
|
|
1654
|
+
* Static checks for things that render "fine" but not as intended: a color
|
|
1655
|
+
* the parser can't read (drawn transparent), text that disappears into its
|
|
1656
|
+
* background, a layer parked off-canvas, a shadow on a light that can't cast
|
|
1657
|
+
* one. Pure and fast; `renderVideo({ qa })` folds the findings into its report.
|
|
2039
1658
|
*/
|
|
2040
|
-
const
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
z.object({
|
|
2060
|
-
type: z.literal("ellipse"),
|
|
2061
|
-
cx: z.number(),
|
|
2062
|
-
cy: z.number(),
|
|
2063
|
-
rx: z.number().positive(),
|
|
2064
|
-
ry: z.number().positive(),
|
|
2065
|
-
startAngleDeg: z.number().default(0),
|
|
2066
|
-
endAngleDeg: z.number().default(360)
|
|
2067
|
-
}),
|
|
2068
|
-
z.object({
|
|
2069
|
-
type: z.literal("wave"),
|
|
2070
|
-
startX: z.number(),
|
|
2071
|
-
startY: z.number(),
|
|
2072
|
-
length: z.number().positive(),
|
|
2073
|
-
amplitude: z.number(),
|
|
2074
|
-
frequency: z.number().positive(),
|
|
2075
|
-
phaseDeg: z.number().default(0)
|
|
2076
|
-
})
|
|
2077
|
-
]);
|
|
2078
|
-
const TextPathOptionsSchema = z.object({
|
|
2079
|
-
path: TextPathSourceSchema,
|
|
2080
|
-
firstMargin: z.number().default(0),
|
|
2081
|
-
lastMargin: z.number().default(0),
|
|
2082
|
-
reversePath: z.boolean().default(false),
|
|
2083
|
-
perpendicularToPath: z.boolean().default(true),
|
|
2084
|
-
forceAlignment: z.boolean().default(false),
|
|
2085
|
-
loop: z.boolean().default(false),
|
|
2086
|
-
baselineOffset: z.enum([
|
|
2087
|
-
"baseline",
|
|
2088
|
-
"center",
|
|
2089
|
-
"ascender",
|
|
2090
|
-
"descender"
|
|
2091
|
-
]).default("baseline"),
|
|
2092
|
-
baselineShift: z.number().default(0)
|
|
2093
|
-
});
|
|
2094
|
-
const TextCursorStyleSchema = z.enum([
|
|
2095
|
-
"bar",
|
|
2096
|
-
"underscore",
|
|
1659
|
+
const COLOR_PROPS = [
|
|
1660
|
+
"background",
|
|
1661
|
+
"fill",
|
|
1662
|
+
"fillColor",
|
|
1663
|
+
"strokeColor",
|
|
1664
|
+
"borderColor",
|
|
1665
|
+
"gradientEndColor",
|
|
1666
|
+
"emissive",
|
|
1667
|
+
"color"
|
|
1668
|
+
];
|
|
1669
|
+
/** Contrast below this makes text hard to read (WCAG large-text minimum). */
|
|
1670
|
+
const MIN_TEXT_CONTRAST = 3;
|
|
1671
|
+
function tracksOf(node) {
|
|
1672
|
+
return node.animation?.tracks ?? [];
|
|
1673
|
+
}
|
|
1674
|
+
const animates = (node, props) => tracksOf(node).some((t) => props.includes(t.prop));
|
|
1675
|
+
const CONTAINERS = new Set([
|
|
1676
|
+
"box",
|
|
1677
|
+
"flex",
|
|
2097
1678
|
"block",
|
|
2098
|
-
"
|
|
2099
|
-
]);
|
|
2100
|
-
const TextCursorConfigSchema = z.object({
|
|
2101
|
-
enabled: z.boolean().default(true),
|
|
2102
|
-
style: TextCursorStyleSchema.default("bar"),
|
|
2103
|
-
customChar: z.string().default("|"),
|
|
2104
|
-
color: z.string().optional(),
|
|
2105
|
-
blinkFrequency: z.number().min(0).default(2),
|
|
2106
|
-
hideOnComplete: z.boolean().default(false),
|
|
2107
|
-
width: z.number().positive().default(2.5),
|
|
2108
|
-
spacing: z.number().default(3)
|
|
2109
|
-
});
|
|
2110
|
-
const TypingCadenceSchema = z.discriminatedUnion("mode", [z.object({ mode: z.literal("constant") }), z.object({
|
|
2111
|
-
mode: z.literal("human"),
|
|
2112
|
-
jitter: z.number().min(0).max(1).default(.35),
|
|
2113
|
-
commaPauseMultiplier: z.number().min(1).default(3),
|
|
2114
|
-
sentencePauseMultiplier: z.number().min(1).default(5.5),
|
|
2115
|
-
paragraphPauseMultiplier: z.number().min(1).default(7)
|
|
2116
|
-
})]);
|
|
2117
|
-
const TextScrambleConfigSchema = z.object({
|
|
2118
|
-
enabled: z.boolean().default(false),
|
|
2119
|
-
charset: z.enum([
|
|
2120
|
-
"ascii",
|
|
2121
|
-
"alphanumeric",
|
|
2122
|
-
"matrix",
|
|
2123
|
-
"binary",
|
|
2124
|
-
"hex",
|
|
2125
|
-
"custom"
|
|
2126
|
-
]).default("alphanumeric"),
|
|
2127
|
-
customCharset: z.string().optional(),
|
|
2128
|
-
scrambleFramesPerChar: z.number().int().min(1).default(8),
|
|
2129
|
-
highlightProbability: z.number().min(0).max(1).default(.25),
|
|
2130
|
-
scrambleColor: z.string().optional()
|
|
2131
|
-
});
|
|
2132
|
-
const TypewriterAnimatorSchema = z.object({
|
|
2133
|
-
granularity: z.enum([
|
|
2134
|
-
"character",
|
|
2135
|
-
"word",
|
|
2136
|
-
"line"
|
|
2137
|
-
]).default("character"),
|
|
2138
|
-
cursor: TextCursorConfigSchema.default({
|
|
2139
|
-
enabled: true,
|
|
2140
|
-
style: "bar",
|
|
2141
|
-
customChar: "|",
|
|
2142
|
-
blinkFrequency: 2,
|
|
2143
|
-
hideOnComplete: false,
|
|
2144
|
-
width: 2.5,
|
|
2145
|
-
spacing: 3
|
|
2146
|
-
}),
|
|
2147
|
-
cadence: TypingCadenceSchema.default({
|
|
2148
|
-
mode: "human",
|
|
2149
|
-
jitter: .35,
|
|
2150
|
-
commaPauseMultiplier: 3,
|
|
2151
|
-
sentencePauseMultiplier: 5.5,
|
|
2152
|
-
paragraphPauseMultiplier: 7
|
|
2153
|
-
}),
|
|
2154
|
-
scramble: TextScrambleConfigSchema.default({
|
|
2155
|
-
enabled: false,
|
|
2156
|
-
charset: "alphanumeric",
|
|
2157
|
-
scrambleFramesPerChar: 8,
|
|
2158
|
-
highlightProbability: .25
|
|
2159
|
-
}),
|
|
2160
|
-
soundSync: z.boolean().default(false)
|
|
2161
|
-
});
|
|
2162
|
-
const SelectorBasedOnSchema = z.enum([
|
|
2163
|
-
"characters",
|
|
2164
|
-
"characters_excluding_spaces",
|
|
2165
|
-
"words",
|
|
2166
|
-
"lines"
|
|
2167
|
-
]);
|
|
2168
|
-
const SelectorUnitsSchema = z.enum(["percentage", "index"]);
|
|
2169
|
-
const SelectorShapeSchema = z.enum([
|
|
2170
|
-
"square",
|
|
2171
|
-
"ramp_up",
|
|
2172
|
-
"ramp_down",
|
|
2173
|
-
"triangle",
|
|
2174
|
-
"round",
|
|
2175
|
-
"smooth"
|
|
2176
|
-
]);
|
|
2177
|
-
const SelectorModeSchema = z.enum([
|
|
2178
|
-
"add",
|
|
2179
|
-
"subtract",
|
|
2180
|
-
"intersect",
|
|
2181
|
-
"min",
|
|
2182
|
-
"max",
|
|
2183
|
-
"difference"
|
|
2184
|
-
]);
|
|
2185
|
-
const TextRangeSelectorSchema = z.object({
|
|
2186
|
-
type: z.literal("range"),
|
|
2187
|
-
start: z.number().default(0),
|
|
2188
|
-
end: z.number().default(1),
|
|
2189
|
-
offset: z.number().default(0),
|
|
2190
|
-
units: SelectorUnitsSchema.default("percentage"),
|
|
2191
|
-
basedOn: SelectorBasedOnSchema.default("characters"),
|
|
2192
|
-
shape: SelectorShapeSchema.default("square"),
|
|
2193
|
-
mode: SelectorModeSchema.default("add"),
|
|
2194
|
-
amount: z.number().min(-1).max(1).default(1),
|
|
2195
|
-
easeHigh: z.number().min(-1).max(1).default(0),
|
|
2196
|
-
easeLow: z.number().min(-1).max(1).default(0),
|
|
2197
|
-
randomizeOrder: z.boolean().default(false),
|
|
2198
|
-
randomSeed: z.number().int().default(12345)
|
|
2199
|
-
});
|
|
2200
|
-
const TextWigglySelectorSchema = z.object({
|
|
2201
|
-
type: z.literal("wiggly"),
|
|
2202
|
-
wigglesPerSecond: z.number().positive().default(2),
|
|
2203
|
-
correlation: z.number().min(0).max(1).default(.5),
|
|
2204
|
-
temporalPhaseDeg: z.number().default(0),
|
|
2205
|
-
spatialPhaseDeg: z.number().default(0),
|
|
2206
|
-
minAmount: z.number().min(-1).max(1).default(-1),
|
|
2207
|
-
maxAmount: z.number().min(-1).max(1).default(1),
|
|
2208
|
-
randomSeed: z.number().int().default(42),
|
|
2209
|
-
basedOn: SelectorBasedOnSchema.default("characters"),
|
|
2210
|
-
mode: SelectorModeSchema.default("intersect")
|
|
2211
|
-
});
|
|
2212
|
-
const TextSignalSelectorSchema = z.object({
|
|
2213
|
-
type: z.literal("signal"),
|
|
2214
|
-
signalId: z.string(),
|
|
2215
|
-
multiplier: z.number().default(1),
|
|
2216
|
-
offset: z.number().default(0),
|
|
2217
|
-
phaseSpread: z.number().default(0),
|
|
2218
|
-
basedOn: SelectorBasedOnSchema.default("characters"),
|
|
2219
|
-
mode: SelectorModeSchema.default("add")
|
|
2220
|
-
});
|
|
2221
|
-
const TextSelectorSchema = z.discriminatedUnion("type", [
|
|
2222
|
-
TextRangeSelectorSchema,
|
|
2223
|
-
TextWigglySelectorSchema,
|
|
2224
|
-
TextSignalSelectorSchema
|
|
2225
|
-
]);
|
|
2226
|
-
const AnimatableGlyphPropsSchema = z.object({
|
|
2227
|
-
x: z.number().optional(),
|
|
2228
|
-
y: z.number().optional(),
|
|
2229
|
-
z: z.number().optional(),
|
|
2230
|
-
scale: z.number().optional(),
|
|
2231
|
-
scaleX: z.number().optional(),
|
|
2232
|
-
scaleY: z.number().optional(),
|
|
2233
|
-
rotation: z.number().optional(),
|
|
2234
|
-
rotationX: z.number().optional(),
|
|
2235
|
-
rotationY: z.number().optional(),
|
|
2236
|
-
skew: z.number().optional(),
|
|
2237
|
-
skewAxis: z.number().optional(),
|
|
2238
|
-
tracking: z.number().optional(),
|
|
2239
|
-
lineSpacing: z.number().optional(),
|
|
2240
|
-
opacity: z.number().min(0).max(1).optional(),
|
|
2241
|
-
fillColor: z.string().optional(),
|
|
2242
|
-
strokeColor: z.string().optional(),
|
|
2243
|
-
strokeWidth: z.number().min(0).optional(),
|
|
2244
|
-
blur: z.number().min(0).optional(),
|
|
2245
|
-
characterOffset: z.number().int().optional()
|
|
2246
|
-
});
|
|
2247
|
-
const GlyphAnchorGroupingSchema = z.enum([
|
|
2248
|
-
"character",
|
|
2249
|
-
"word",
|
|
2250
|
-
"line",
|
|
2251
|
-
"all"
|
|
1679
|
+
"group"
|
|
2252
1680
|
]);
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
const
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
]
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
1681
|
+
/** Whether a layer puts pixels behind whatever is drawn after it (text over text aside). */
|
|
1682
|
+
function paints(node) {
|
|
1683
|
+
if (node.kind === "text" || node.kind === "light" || node.kind === "camera") return false;
|
|
1684
|
+
if (!CONTAINERS.has(String(node.kind))) return true;
|
|
1685
|
+
const bg = node.background;
|
|
1686
|
+
if (typeof bg === "string" && bg !== "" && bg !== "transparent") return true;
|
|
1687
|
+
return (node.children ?? []).some(paints);
|
|
1688
|
+
}
|
|
1689
|
+
const byZ = (nodes) => [...nodes].sort((a, b) => (Number(a.zIndex) || 0) - (Number(b.zIndex) || 0));
|
|
1690
|
+
function solidColor(value) {
|
|
1691
|
+
if (typeof value !== "string" || value.includes("gradient(")) return null;
|
|
1692
|
+
const c = parseCssColor(value);
|
|
1693
|
+
return c && c[3] > .99 ? value : null;
|
|
1694
|
+
}
|
|
1695
|
+
function lintComposition(config) {
|
|
1696
|
+
const out = [];
|
|
1697
|
+
const push = (severity, code, message, layerId) => out.push({
|
|
1698
|
+
severity,
|
|
1699
|
+
code,
|
|
1700
|
+
message,
|
|
1701
|
+
...layerId && { layerId }
|
|
1702
|
+
});
|
|
1703
|
+
const W = config.width;
|
|
1704
|
+
const H = config.height;
|
|
1705
|
+
let hasEnvironment = false;
|
|
1706
|
+
const ambientLights = [];
|
|
1707
|
+
let has3D = false;
|
|
1708
|
+
const pbrNodes = [];
|
|
1709
|
+
const shadowLights = [];
|
|
1710
|
+
const visit = (node, backdrop, atRoot) => {
|
|
1711
|
+
const id = String(node.id ?? "?");
|
|
1712
|
+
for (const prop of COLOR_PROPS) {
|
|
1713
|
+
const v = node[prop];
|
|
1714
|
+
if (typeof v !== "string" || v === "" || v === "transparent") continue;
|
|
1715
|
+
if (v.includes("gradient(")) {
|
|
1716
|
+
if (!parseCssGradient(v)) push("error", "invalid_gradient", `\`${prop}\` on '${id}' is not a gradient this renderer reads: ${v}. It draws nothing.`, id);
|
|
1717
|
+
} else if (!parseCssColor(v)) push("warning", "unknown_color", `\`${prop}: "${v}"\` on '${id}' is not a color (hex, rgb(), hsl(), oklch() or a CSS name). It draws transparent.`, id);
|
|
1718
|
+
}
|
|
1719
|
+
if (node.kind === "light") {
|
|
1720
|
+
const type = node.lightType ?? "directional";
|
|
1721
|
+
if (type === "environment") hasEnvironment = true;
|
|
1722
|
+
if (type === "ambient") ambientLights.push(id);
|
|
1723
|
+
if (node.castShadow) if (type === "directional" || type === "spot") shadowLights.push(id);
|
|
1724
|
+
else push("warning", "shadow_unsupported_light", `'${id}' is a ${String(type)} light: only directional and spot lights cast shadows.`, id);
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
if (node.kind === "camera") return;
|
|
1728
|
+
if (node.kind === "media") {
|
|
1729
|
+
const src = node.inputHandleId;
|
|
1730
|
+
if (typeof src === "string") {
|
|
1731
|
+
if ((node.dataType ?? "Video") === "Image") {
|
|
1732
|
+
if (/\.(json|lottie)(\?.*)?$/i.test(src)) push("error", "unsupported_image_format", `'${id}' is an image layer with source '${src}', which is a Lottie vector animation. Use Layer.lottie() instead.`, id);
|
|
1733
|
+
else if (/\.(mp4|mov|webm|mkv)(\?.*)?$/i.test(src)) push("error", "unsupported_image_format", `'${id}' is an image layer with video source '${src}'. Use Layer.video() instead.`, id);
|
|
1734
|
+
else if (/\.(mp3|wav|ogg|m4a|aac)(\?.*)?$/i.test(src)) push("error", "unsupported_image_format", `'${id}' is an image layer with audio source '${src}'. Use Layer.audio() instead.`, id);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
const is3D = Boolean(node.is3D) || typeof node.z === "number" && node.z !== 0;
|
|
1739
|
+
if (is3D || node.kind === "model3d") has3D = true;
|
|
1740
|
+
if (node.roughness !== void 0 || node.metallic !== void 0) pbrNodes.push(id);
|
|
1741
|
+
if (node.kind === "text" && backdrop && !animates(node, ["fill", "color"])) {
|
|
1742
|
+
const fg = solidColor(node.fill ?? node.color);
|
|
1743
|
+
const behind = solidColor(node.background) ?? backdrop;
|
|
1744
|
+
if (fg) {
|
|
1745
|
+
const ratio = Color.contrast(fg, behind);
|
|
1746
|
+
if (ratio < MIN_TEXT_CONTRAST) push("warning", "low_contrast_text", `Text '${id}' (${fg}) on ${behind} has contrast ${ratio.toFixed(2)}:1 (aim for ≥ ${MIN_TEXT_CONTRAST}; ${Color.readableOn(behind)} reads well).`, id);
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
if (atRoot && !is3D && node.position === "absolute" && typeof node.x === "number" && typeof node.y === "number" && typeof node.width === "number" && typeof node.height === "number" && !animates(node, [
|
|
1750
|
+
"x",
|
|
1751
|
+
"y",
|
|
1752
|
+
"translateX",
|
|
1753
|
+
"translateY",
|
|
1754
|
+
"scale",
|
|
1755
|
+
"rotation"
|
|
1756
|
+
])) {
|
|
1757
|
+
const { x, y, width, height } = node;
|
|
1758
|
+
if (x + width <= 0 || y + height <= 0 || x >= W || y >= H) push("warning", "offscreen_layer", `'${id}' sits entirely outside the ${W}×${H} canvas (x ${x}, y ${y}) and never moves in.`, id);
|
|
1759
|
+
}
|
|
1760
|
+
for (const t of tracksOf(node)) {
|
|
1761
|
+
const kfs = t.keyframes ?? [];
|
|
1762
|
+
if ((!t.source || t.source.type === "keyframe") && kfs.length >= 2 && kfs.every((k) => JSON.stringify(k.value) === JSON.stringify(kfs[0].value))) push("info", "static_track", `'${id}' animates \`${t.prop}\` but every keyframe holds ${JSON.stringify(kfs[0].value)}.`, id);
|
|
1763
|
+
}
|
|
1764
|
+
const ownBackdrop = solidColor(node.background) ?? backdrop;
|
|
1765
|
+
const children = node.children;
|
|
1766
|
+
const fullFrame = node.x === 0 && node.y === 0 && node.width === W && node.height === H;
|
|
1767
|
+
visitLevel(children ?? [], ownBackdrop, atRoot && fullFrame);
|
|
2302
1768
|
};
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
}
|
|
2309
|
-
return builder;
|
|
2310
|
-
}
|
|
2311
|
-
static fromBezier(segments) {
|
|
2312
|
-
const builder = new TextPathBuilder$1();
|
|
2313
|
-
builder.options.path = {
|
|
2314
|
-
type: "bezier",
|
|
2315
|
-
segments
|
|
2316
|
-
};
|
|
2317
|
-
return builder;
|
|
2318
|
-
}
|
|
2319
|
-
static fromCurve(curve) {
|
|
2320
|
-
return TextPathBuilder$1.fromBezier([curve]);
|
|
2321
|
-
}
|
|
2322
|
-
static circularBadge(cx, cy, radius) {
|
|
2323
|
-
const builder = new TextPathBuilder$1();
|
|
2324
|
-
builder.options.path = {
|
|
2325
|
-
type: "ellipse",
|
|
2326
|
-
cx,
|
|
2327
|
-
cy,
|
|
2328
|
-
rx: radius,
|
|
2329
|
-
ry: radius,
|
|
2330
|
-
startAngleDeg: 0,
|
|
2331
|
-
endAngleDeg: 360
|
|
2332
|
-
};
|
|
2333
|
-
builder.options.loop = true;
|
|
2334
|
-
return builder;
|
|
2335
|
-
}
|
|
2336
|
-
static ellipse(cx, cy, rx, ry, startAngleDeg = 0, endAngleDeg = 360) {
|
|
2337
|
-
const builder = new TextPathBuilder$1();
|
|
2338
|
-
builder.options.path = {
|
|
2339
|
-
type: "ellipse",
|
|
2340
|
-
cx,
|
|
2341
|
-
cy,
|
|
2342
|
-
rx,
|
|
2343
|
-
ry,
|
|
2344
|
-
startAngleDeg,
|
|
2345
|
-
endAngleDeg
|
|
2346
|
-
};
|
|
2347
|
-
builder.options.loop = Math.abs(endAngleDeg - startAngleDeg) >= 360;
|
|
2348
|
-
return builder;
|
|
2349
|
-
}
|
|
2350
|
-
static wave(startX, startY, length, amplitude, frequency, phaseDeg = 0) {
|
|
2351
|
-
const builder = new TextPathBuilder$1();
|
|
2352
|
-
builder.options.path = {
|
|
2353
|
-
type: "wave",
|
|
2354
|
-
startX,
|
|
2355
|
-
startY,
|
|
2356
|
-
length,
|
|
2357
|
-
amplitude,
|
|
2358
|
-
frequency,
|
|
2359
|
-
phaseDeg
|
|
2360
|
-
};
|
|
2361
|
-
return builder;
|
|
2362
|
-
}
|
|
2363
|
-
firstMargin(margin) {
|
|
2364
|
-
this.options.firstMargin = margin;
|
|
2365
|
-
return this;
|
|
2366
|
-
}
|
|
2367
|
-
lastMargin(margin) {
|
|
2368
|
-
this.options.lastMargin = margin;
|
|
2369
|
-
return this;
|
|
2370
|
-
}
|
|
2371
|
-
reversePath(reverse) {
|
|
2372
|
-
this.options.reversePath = reverse;
|
|
2373
|
-
return this;
|
|
2374
|
-
}
|
|
2375
|
-
perpendicularToPath(perpendicular) {
|
|
2376
|
-
this.options.perpendicularToPath = perpendicular;
|
|
2377
|
-
return this;
|
|
2378
|
-
}
|
|
2379
|
-
forceAlignment(force) {
|
|
2380
|
-
this.options.forceAlignment = force;
|
|
2381
|
-
return this;
|
|
2382
|
-
}
|
|
2383
|
-
loop(isLoop) {
|
|
2384
|
-
this.options.loop = isLoop;
|
|
2385
|
-
return this;
|
|
2386
|
-
}
|
|
2387
|
-
baselineOffset(offset) {
|
|
2388
|
-
this.options.baselineOffset = offset;
|
|
2389
|
-
return this;
|
|
2390
|
-
}
|
|
2391
|
-
baselineShift(shiftPixels) {
|
|
2392
|
-
this.options.baselineShift = shiftPixels;
|
|
2393
|
-
return this;
|
|
2394
|
-
}
|
|
2395
|
-
build() {
|
|
2396
|
-
return TextPathOptionsSchema.parse(this.options);
|
|
2397
|
-
}
|
|
2398
|
-
};
|
|
2399
|
-
/**
|
|
2400
|
-
* Fluent builder for After Effects Range, Wiggly, and Signal Animators.
|
|
2401
|
-
*/
|
|
2402
|
-
var TextAnimatorBuilder = class TextAnimatorBuilder$1 {
|
|
2403
|
-
name = "Animator";
|
|
2404
|
-
selectors = [];
|
|
2405
|
-
props = {};
|
|
2406
|
-
anchor = {
|
|
2407
|
-
grouping: "character",
|
|
2408
|
-
anchorX: .5,
|
|
2409
|
-
anchorY: .8
|
|
1769
|
+
const visitLevel = (nodes, backdrop, atRoot) => {
|
|
1770
|
+
let known = backdrop;
|
|
1771
|
+
for (const n of byZ(nodes)) {
|
|
1772
|
+
visit(n, known, atRoot);
|
|
1773
|
+
if (paints(n)) known = null;
|
|
1774
|
+
}
|
|
2410
1775
|
};
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
}
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
}
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
this.selectors.push({
|
|
2442
|
-
type: "wiggly",
|
|
2443
|
-
wigglesPerSecond: config.wigglesPerSecond ?? 2,
|
|
2444
|
-
correlation: config.correlation ?? .5,
|
|
2445
|
-
temporalPhaseDeg: 0,
|
|
2446
|
-
spatialPhaseDeg: 0,
|
|
2447
|
-
minAmount: config.minAmount ?? -1,
|
|
2448
|
-
maxAmount: config.maxAmount ?? 1,
|
|
2449
|
-
randomSeed: config.randomSeed ?? 42,
|
|
2450
|
-
basedOn: "characters",
|
|
2451
|
-
mode: config.mode ?? "intersect"
|
|
2452
|
-
});
|
|
2453
|
-
return this;
|
|
2454
|
-
}
|
|
2455
|
-
/** Adds a reactive signal selector */
|
|
2456
|
-
addSignalSelector(signalId, multiplier = 1, phaseSpread = 0, offset = 0, mode = "add") {
|
|
2457
|
-
this.selectors.push({
|
|
2458
|
-
type: "signal",
|
|
2459
|
-
signalId,
|
|
2460
|
-
multiplier,
|
|
2461
|
-
offset,
|
|
2462
|
-
phaseSpread,
|
|
2463
|
-
basedOn: "characters",
|
|
2464
|
-
mode
|
|
2465
|
-
});
|
|
2466
|
-
return this;
|
|
2467
|
-
}
|
|
2468
|
-
x(pixels) {
|
|
2469
|
-
this.props.x = pixels;
|
|
2470
|
-
return this;
|
|
1776
|
+
const rootBackdrop = solidColor(config.backgroundColor) ?? null;
|
|
1777
|
+
visitLevel(config.layout, rootBackdrop, true);
|
|
1778
|
+
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).`);
|
|
1779
|
+
if (shadowLights.length > 1) push("info", "multiple_shadow_lights", `${shadowLights.length} lights cast shadows (${shadowLights.join(", ")}); only the first one does.`);
|
|
1780
|
+
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.`);
|
|
1781
|
+
return out;
|
|
1782
|
+
}
|
|
1783
|
+
const GEOMETRY = [
|
|
1784
|
+
"x",
|
|
1785
|
+
"y",
|
|
1786
|
+
"width",
|
|
1787
|
+
"height"
|
|
1788
|
+
];
|
|
1789
|
+
function hoistOne(owner) {
|
|
1790
|
+
const matte = owner.matte;
|
|
1791
|
+
const { matte: _drop, ...rest } = owner;
|
|
1792
|
+
const self = { ...rest };
|
|
1793
|
+
if (Array.isArray(self.children)) self.children = hoistMattes(self.children);
|
|
1794
|
+
if (!matte?.node) return [self];
|
|
1795
|
+
const src = matte.node;
|
|
1796
|
+
const id = src.id ?? `${String(owner.id)}__matte`;
|
|
1797
|
+
const node = {
|
|
1798
|
+
position: "absolute",
|
|
1799
|
+
...src,
|
|
1800
|
+
id,
|
|
1801
|
+
matteOf: String(owner.id),
|
|
1802
|
+
matteMode: matte.mode ?? "alpha"
|
|
1803
|
+
};
|
|
1804
|
+
if (GEOMETRY.every((k) => src[k] === void 0)) {
|
|
1805
|
+
for (const k of GEOMETRY) if (typeof owner[k] === "number") node[k] = owner[k];
|
|
2471
1806
|
}
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
this.props.z = pixels;
|
|
2478
|
-
return this;
|
|
2479
|
-
}
|
|
2480
|
-
scale(scaleValue) {
|
|
2481
|
-
this.props.scale = scaleValue;
|
|
2482
|
-
return this;
|
|
2483
|
-
}
|
|
2484
|
-
scaleX(scaleValue) {
|
|
2485
|
-
this.props.scaleX = scaleValue;
|
|
2486
|
-
return this;
|
|
2487
|
-
}
|
|
2488
|
-
scaleY(scaleValue) {
|
|
2489
|
-
this.props.scaleY = scaleValue;
|
|
2490
|
-
return this;
|
|
2491
|
-
}
|
|
2492
|
-
rotation(degrees) {
|
|
2493
|
-
this.props.rotation = degrees;
|
|
2494
|
-
return this;
|
|
2495
|
-
}
|
|
2496
|
-
rotationX(degrees) {
|
|
2497
|
-
this.props.rotationX = degrees;
|
|
2498
|
-
return this;
|
|
2499
|
-
}
|
|
2500
|
-
rotationY(degrees) {
|
|
2501
|
-
this.props.rotationY = degrees;
|
|
2502
|
-
return this;
|
|
2503
|
-
}
|
|
2504
|
-
skew(degrees) {
|
|
2505
|
-
this.props.skew = degrees;
|
|
2506
|
-
return this;
|
|
2507
|
-
}
|
|
2508
|
-
skewAxis(degrees) {
|
|
2509
|
-
this.props.skewAxis = degrees;
|
|
2510
|
-
return this;
|
|
2511
|
-
}
|
|
2512
|
-
opacity(value) {
|
|
2513
|
-
this.props.opacity = value;
|
|
2514
|
-
return this;
|
|
2515
|
-
}
|
|
2516
|
-
blur(pixels) {
|
|
2517
|
-
this.props.blur = pixels;
|
|
2518
|
-
return this;
|
|
2519
|
-
}
|
|
2520
|
-
fill(colorHex) {
|
|
2521
|
-
return this.fillColor(colorHex);
|
|
2522
|
-
}
|
|
2523
|
-
fillColor(colorHex) {
|
|
2524
|
-
this.props.fillColor = colorHex;
|
|
2525
|
-
return this;
|
|
2526
|
-
}
|
|
2527
|
-
strokeColor(colorHex) {
|
|
2528
|
-
this.props.strokeColor = colorHex;
|
|
2529
|
-
return this;
|
|
2530
|
-
}
|
|
2531
|
-
strokeWidth(pixels) {
|
|
2532
|
-
this.props.strokeWidth = pixels;
|
|
2533
|
-
return this;
|
|
2534
|
-
}
|
|
2535
|
-
tracking(spacingPixels) {
|
|
2536
|
-
this.props.tracking = spacingPixels;
|
|
2537
|
-
return this;
|
|
2538
|
-
}
|
|
2539
|
-
lineSpacing(spacingPixels) {
|
|
2540
|
-
this.props.lineSpacing = spacingPixels;
|
|
2541
|
-
return this;
|
|
2542
|
-
}
|
|
2543
|
-
characterOffset(offset) {
|
|
2544
|
-
this.props.characterOffset = offset;
|
|
2545
|
-
return this;
|
|
2546
|
-
}
|
|
2547
|
-
anchorGrouping(grouping, anchorX = .5, anchorY = .8) {
|
|
2548
|
-
this.anchor = {
|
|
2549
|
-
grouping,
|
|
2550
|
-
anchorX,
|
|
2551
|
-
anchorY
|
|
2552
|
-
};
|
|
2553
|
-
return this;
|
|
2554
|
-
}
|
|
2555
|
-
build() {
|
|
2556
|
-
return AETextAnimatorSchema.parse({
|
|
2557
|
-
name: this.name,
|
|
2558
|
-
selectors: this.selectors,
|
|
2559
|
-
props: this.props,
|
|
2560
|
-
anchor: this.anchor
|
|
2561
|
-
});
|
|
2562
|
-
}
|
|
2563
|
-
};
|
|
2564
|
-
/**
|
|
2565
|
-
* Evaluates closed-form underdamped harmonic oscillator for spring physics:
|
|
2566
|
-
*
|
|
2567
|
-
* x(t) = target + (x0 - target) * exp(-zeta * omega_n * t) *
|
|
2568
|
-
* [ cos(omega_d * t) + (zeta / sqrt(1 - zeta^2)) * sin(omega_d * t) ]
|
|
2569
|
-
*
|
|
2570
|
-
* @param t Time in seconds since excitation
|
|
2571
|
-
* @param stiffness Spring stiffness (k)
|
|
2572
|
-
* @param damping Damping coefficient (c)
|
|
2573
|
-
* @param mass Mass of glyph (m)
|
|
2574
|
-
* @param initialVelocity Initial velocity (v0)
|
|
2575
|
-
* @returns Settled scalar progress in [0, 1] with overshoot
|
|
2576
|
-
*/
|
|
2577
|
-
function evaluateSpringProgress(t, stiffness = 180, damping = 12, mass = 1, initialVelocity = 0) {
|
|
2578
|
-
if (t <= 0) return 0;
|
|
2579
|
-
const omega_n = Math.sqrt(Math.max(1e-4, stiffness) / Math.max(1e-4, mass));
|
|
2580
|
-
const zeta = damping / (2 * Math.sqrt(Math.max(1e-4, stiffness * mass)));
|
|
2581
|
-
if (zeta < 1) {
|
|
2582
|
-
const omega_d = omega_n * Math.sqrt(1 - zeta * zeta);
|
|
2583
|
-
const decay = Math.exp(-zeta * omega_n * t);
|
|
2584
|
-
const c1 = -1;
|
|
2585
|
-
const c2 = (initialVelocity - zeta * omega_n * -1) / Math.max(1e-6, omega_d);
|
|
2586
|
-
const displacement = decay * (c1 * Math.cos(omega_d * t) + c2 * Math.sin(omega_d * t));
|
|
2587
|
-
return Math.min(2, Math.max(-1, 1 + displacement));
|
|
2588
|
-
} else if (Math.abs(zeta - 1) < 1e-4) {
|
|
2589
|
-
const decay = Math.exp(-omega_n * t);
|
|
2590
|
-
return 1 + (-1 + (initialVelocity - omega_n) * t) * decay;
|
|
2591
|
-
} else {
|
|
2592
|
-
const s1 = -omega_n * (zeta - Math.sqrt(zeta * zeta - 1));
|
|
2593
|
-
const s2 = -omega_n * (zeta + Math.sqrt(zeta * zeta - 1));
|
|
2594
|
-
const c1 = (initialVelocity + s2) / Math.max(1e-6, s1 - s2);
|
|
2595
|
-
const c2 = -1 - c1;
|
|
2596
|
-
return 1 + (c1 * Math.exp(s1 * t) + c2 * Math.exp(s2 * t));
|
|
2597
|
-
}
|
|
2598
|
-
}
|
|
2599
|
-
/**
|
|
2600
|
-
* Evaluates 2D Directional Skew matrix components:
|
|
2601
|
-
*
|
|
2602
|
-
* S(theta, phi) = R(phi) * [ 1 tan(theta) ] * R(-phi)
|
|
2603
|
-
* [ 0 1 ]
|
|
2604
|
-
*
|
|
2605
|
-
* @param skewDeg Skew angle in degrees
|
|
2606
|
-
* @param skewAxisDeg Skew axis in degrees
|
|
2607
|
-
* @returns 2x2 affine shear matrix components [m00, m01, m10, m11]
|
|
2608
|
-
*/
|
|
2609
|
-
function evaluateSkewMatrix(skewDeg, skewAxisDeg = 0) {
|
|
2610
|
-
if (skewDeg === 0) return [
|
|
2611
|
-
1,
|
|
2612
|
-
0,
|
|
2613
|
-
0,
|
|
2614
|
-
1
|
|
2615
|
-
];
|
|
2616
|
-
const theta = skewDeg * Math.PI / 180;
|
|
2617
|
-
const phi = skewAxisDeg * Math.PI / 180;
|
|
2618
|
-
const cosPhi = Math.cos(phi);
|
|
2619
|
-
const sinPhi = Math.sin(phi);
|
|
2620
|
-
const tanTheta = Math.tan(theta);
|
|
2621
|
-
return [
|
|
2622
|
-
1 - tanTheta * cosPhi * sinPhi,
|
|
2623
|
-
tanTheta * cosPhi * cosPhi,
|
|
2624
|
-
-tanTheta * sinPhi * sinPhi,
|
|
2625
|
-
1 + tanTheta * sinPhi * cosPhi
|
|
2626
|
-
];
|
|
2627
|
-
}
|
|
2628
|
-
/**
|
|
2629
|
-
* Computes anchor pivot coordinates relative to glyph bounding box:
|
|
2630
|
-
*
|
|
2631
|
-
* @param bbox Glyph bounding box { width, height, ascender, descender }
|
|
2632
|
-
* @param config Text anchor configuration
|
|
2633
|
-
* @returns Pivot offset (px, py) relative to glyph quad center
|
|
2634
|
-
*/
|
|
2635
|
-
function computeAnchorPivotOffset(bbox, config) {
|
|
2636
|
-
let normX = config.anchorX;
|
|
2637
|
-
let normY = config.anchorY;
|
|
2638
|
-
switch (config.preset) {
|
|
2639
|
-
case "center":
|
|
2640
|
-
normX = .5;
|
|
2641
|
-
normY = .5;
|
|
2642
|
-
break;
|
|
2643
|
-
case "baseline":
|
|
2644
|
-
normX = .5;
|
|
2645
|
-
normY = bbox.height > 0 ? bbox.ascender / bbox.height : .8;
|
|
2646
|
-
break;
|
|
2647
|
-
case "bottom_left":
|
|
2648
|
-
normX = 0;
|
|
2649
|
-
normY = 1;
|
|
2650
|
-
break;
|
|
2651
|
-
case "bottom_center":
|
|
2652
|
-
normX = .5;
|
|
2653
|
-
normY = 1;
|
|
2654
|
-
break;
|
|
2655
|
-
case "bottom_right":
|
|
2656
|
-
normX = 1;
|
|
2657
|
-
normY = 1;
|
|
2658
|
-
break;
|
|
2659
|
-
case "top_left":
|
|
2660
|
-
normX = 0;
|
|
2661
|
-
normY = 0;
|
|
2662
|
-
break;
|
|
2663
|
-
case "top_center":
|
|
2664
|
-
normX = .5;
|
|
2665
|
-
normY = 0;
|
|
2666
|
-
break;
|
|
2667
|
-
case "top_right":
|
|
2668
|
-
normX = 1;
|
|
2669
|
-
normY = 0;
|
|
2670
|
-
break;
|
|
2671
|
-
default:
|
|
2672
|
-
normX = .5;
|
|
2673
|
-
normY = .5;
|
|
2674
|
-
break;
|
|
2675
|
-
}
|
|
2676
|
-
return {
|
|
2677
|
-
px: (normX - .5) * bbox.width + config.offsetX,
|
|
2678
|
-
py: (normY - .5) * bbox.height + config.offsetY
|
|
2679
|
-
};
|
|
2680
|
-
}
|
|
2681
|
-
/**
|
|
2682
|
-
* Computes leading displacement per line based on lineAnchor:
|
|
2683
|
-
*
|
|
2684
|
-
* @param lineIndex 0-based index of current line
|
|
2685
|
-
* @param lineCount Total lines in paragraph
|
|
2686
|
-
* @param lineSpacing Additional leading in pixels
|
|
2687
|
-
* @param lineAnchor Pivot line anchor in [0, 1]
|
|
2688
|
-
* @returns Y displacement in pixels
|
|
2689
|
-
*/
|
|
2690
|
-
function computeLineLeadingDisplacement(lineIndex, lineCount, lineSpacing, lineAnchor = 0) {
|
|
2691
|
-
if (lineSpacing === 0 || lineCount <= 1) return 0;
|
|
2692
|
-
return (lineIndex - lineAnchor * (lineCount - 1)) * lineSpacing;
|
|
2693
|
-
}
|
|
2694
|
-
/**
|
|
2695
|
-
* Evaluates an Expression Selector formula safely in a sandboxed numeric scope.
|
|
2696
|
-
*
|
|
2697
|
-
* @param expression Formula string (e.g. "Math.sin(time * 4 + textIndex * 0.2)")
|
|
2698
|
-
* @param ctx Glyph evaluation context
|
|
2699
|
-
* @returns Numeric selector weight clamped to [-1, 1]
|
|
2700
|
-
*/
|
|
2701
|
-
function evaluateExpressionSelector(expression, ctx) {
|
|
2702
|
-
try {
|
|
2703
|
-
const scope = {
|
|
2704
|
-
textIndex: ctx.charIndex,
|
|
2705
|
-
textTotal: Math.max(1, ctx.totalChars),
|
|
2706
|
-
wordIndex: ctx.wordIndex,
|
|
2707
|
-
wordTotal: Math.max(1, ctx.totalWords),
|
|
2708
|
-
lineIndex: ctx.lineIndex,
|
|
2709
|
-
lineTotal: Math.max(1, ctx.totalLines),
|
|
2710
|
-
time: ctx.time,
|
|
2711
|
-
frame: ctx.frame,
|
|
2712
|
-
fps: ctx.fps,
|
|
2713
|
-
sin: Math.sin,
|
|
2714
|
-
cos: Math.cos,
|
|
2715
|
-
tan: Math.tan,
|
|
2716
|
-
exp: Math.exp,
|
|
2717
|
-
log: Math.log,
|
|
2718
|
-
abs: Math.abs,
|
|
2719
|
-
min: Math.min,
|
|
2720
|
-
max: Math.max,
|
|
2721
|
-
sqrt: Math.sqrt,
|
|
2722
|
-
pow: Math.pow,
|
|
2723
|
-
floor: Math.floor,
|
|
2724
|
-
ceil: Math.ceil,
|
|
2725
|
-
round: Math.round,
|
|
2726
|
-
PI: Math.PI,
|
|
2727
|
-
clamp: (v, lo, hi) => Math.max(lo, Math.min(hi, v)),
|
|
2728
|
-
noise: (seed) => {
|
|
2729
|
-
const n = Math.sin(seed * 12.9898 + ctx.frame * .1) * 43758.5453;
|
|
2730
|
-
return (n - Math.floor(n)) * 2 - 1;
|
|
2731
|
-
},
|
|
2732
|
-
signals: ctx.signals ?? {}
|
|
2733
|
-
};
|
|
2734
|
-
const keys = Object.keys(scope);
|
|
2735
|
-
const values = Object.values(scope);
|
|
2736
|
-
const fn = new Function(...keys, `return (${expression});`);
|
|
2737
|
-
const result = Number(fn(...values));
|
|
2738
|
-
return Number.isFinite(result) ? Math.max(-1, Math.min(1, result)) : 0;
|
|
2739
|
-
} catch {
|
|
2740
|
-
return 0;
|
|
2741
|
-
}
|
|
2742
|
-
}
|
|
2743
|
-
/**
|
|
2744
|
-
* Evaluates 3D Volumetric Formation parametric coordinates.
|
|
2745
|
-
*/
|
|
2746
|
-
function evaluateVolumetricFormation(glyphIndex, totalGlyphs, config) {
|
|
2747
|
-
const n = Math.max(1, totalGlyphs);
|
|
2748
|
-
const norm = n > 1 ? glyphIndex / (n - 1) : 0;
|
|
2749
|
-
const totalAngleRad = config.totalAngle * Math.PI / 180;
|
|
2750
|
-
const phi = norm * totalAngleRad;
|
|
2751
|
-
let x = 0;
|
|
2752
|
-
let y = 0;
|
|
2753
|
-
let z$1$1 = 0;
|
|
2754
|
-
let rotX = 0;
|
|
2755
|
-
let rotY = 0;
|
|
2756
|
-
let rotZ = 0;
|
|
2757
|
-
let depthOpacity = 1;
|
|
2758
|
-
switch (config.mode) {
|
|
2759
|
-
case "cylinder": {
|
|
2760
|
-
const theta = config.totalAngle < 360 ? (norm - .5) * totalAngleRad : phi;
|
|
2761
|
-
if (config.axis === "y") {
|
|
2762
|
-
x = config.radius * Math.sin(theta);
|
|
2763
|
-
z$1$1 = config.radius * Math.cos(theta) - config.radius;
|
|
2764
|
-
rotY = theta * 180 / Math.PI;
|
|
2765
|
-
} else if (config.axis === "x") {
|
|
2766
|
-
y = config.radius * Math.sin(theta);
|
|
2767
|
-
z$1$1 = config.radius * Math.cos(theta) - config.radius;
|
|
2768
|
-
rotX = theta * 180 / Math.PI;
|
|
2769
|
-
} else {
|
|
2770
|
-
x = config.radius * Math.sin(theta);
|
|
2771
|
-
y = config.radius * Math.cos(theta);
|
|
2772
|
-
rotZ = theta * 180 / Math.PI;
|
|
2773
|
-
}
|
|
2774
|
-
const facing = Math.cos(theta);
|
|
2775
|
-
depthOpacity = Math.max(.25, (facing + 1) * .5);
|
|
2776
|
-
break;
|
|
2777
|
-
}
|
|
2778
|
-
case "vortex": {
|
|
2779
|
-
const spiralPhi = -Math.PI / 2 + phi;
|
|
2780
|
-
const r = config.radius * (1 - norm * .35);
|
|
2781
|
-
x = r * Math.cos(spiralPhi);
|
|
2782
|
-
y = r * Math.sin(spiralPhi);
|
|
2783
|
-
z$1$1 = -glyphIndex * config.pitch || 0;
|
|
2784
|
-
const dr = -.35 * config.radius / (totalAngleRad || 1);
|
|
2785
|
-
const dx = dr * Math.cos(spiralPhi) - r * Math.sin(spiralPhi);
|
|
2786
|
-
const dy = dr * Math.sin(spiralPhi) + r * Math.cos(spiralPhi);
|
|
2787
|
-
rotZ = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
2788
|
-
depthOpacity = Math.max(.65, 1 - norm * .35);
|
|
2789
|
-
break;
|
|
2790
|
-
}
|
|
2791
|
-
case "helix":
|
|
2792
|
-
if (config.axis === "x") {
|
|
2793
|
-
const pitchX = config.pitch > 10 ? config.pitch : 28;
|
|
2794
|
-
x = (glyphIndex - (n - 1) / 2) * pitchX;
|
|
2795
|
-
y = config.radius * Math.sin(phi);
|
|
2796
|
-
z$1$1 = config.radius * Math.cos(phi) - config.radius;
|
|
2797
|
-
rotX = Math.sin(phi) * 22;
|
|
2798
|
-
depthOpacity = .75 + .25 * ((Math.cos(phi) + 1) * .5);
|
|
2799
|
-
} else {
|
|
2800
|
-
const theta = (norm - .5) * totalAngleRad;
|
|
2801
|
-
x = config.radius * Math.sin(theta);
|
|
2802
|
-
y = (glyphIndex - (n - 1) / 2) * config.pitch;
|
|
2803
|
-
z$1$1 = config.radius * Math.cos(theta) - config.radius;
|
|
2804
|
-
rotY = theta * 180 / Math.PI;
|
|
2805
|
-
const facing = Math.cos(theta);
|
|
2806
|
-
depthOpacity = Math.max(.65, (facing + 1) * .5);
|
|
2807
|
-
}
|
|
2808
|
-
break;
|
|
2809
|
-
default:
|
|
2810
|
-
z$1$1 = 0;
|
|
2811
|
-
break;
|
|
2812
|
-
}
|
|
2813
|
-
const perspective = Math.max(100, config.perspective ?? 1200);
|
|
2814
|
-
const depthDist = perspective - z$1$1;
|
|
2815
|
-
const scaleMult = depthDist > 1 ? perspective / depthDist : 1;
|
|
2816
|
-
return {
|
|
2817
|
-
x: x * scaleMult,
|
|
2818
|
-
y: y * scaleMult,
|
|
2819
|
-
z: z$1$1,
|
|
2820
|
-
rotX,
|
|
2821
|
-
rotY,
|
|
2822
|
-
rotZ,
|
|
2823
|
-
scaleMult: Math.max(.1, scaleMult),
|
|
2824
|
-
depthOpacity
|
|
2825
|
-
};
|
|
2826
|
-
}
|
|
2827
|
-
/**
|
|
2828
|
-
* Evaluates infinite kinetic marquee translation and snapping.
|
|
2829
|
-
*/
|
|
2830
|
-
function evaluateMarqueeOffset(baseX, containerWidth, contentWidth, config, elapsedSec) {
|
|
2831
|
-
const totalSpan = (containerWidth > 0 ? Math.max(containerWidth, contentWidth) : contentWidth) + config.repeatGap;
|
|
2832
|
-
if (totalSpan <= 0) return baseX;
|
|
2833
|
-
let travel = config.velocity * elapsedSec;
|
|
2834
|
-
if (config.snap?.enabled) {
|
|
2835
|
-
const targetPos = (config.snap.stopIndex ?? 0) * (config.snap.granularity === "character" ? 40 : 120);
|
|
2836
|
-
const decelFactor = Math.min(1, elapsedSec * 1.5);
|
|
2837
|
-
travel = travel * (1 - decelFactor) + targetPos * decelFactor;
|
|
2838
|
-
}
|
|
2839
|
-
if (config.direction === "right" || config.direction === "down") travel = -travel;
|
|
2840
|
-
if (config.loop) {
|
|
2841
|
-
const wrapped = (baseX - travel) % totalSpan;
|
|
2842
|
-
return wrapped < -contentWidth ? wrapped + totalSpan : wrapped;
|
|
2843
|
-
}
|
|
2844
|
-
return baseX - travel;
|
|
2845
|
-
}
|
|
2846
|
-
/**
|
|
2847
|
-
* Samples audio FFT frequency bin and computes scale factor for Audio Spectrum Typography.
|
|
2848
|
-
*/
|
|
2849
|
-
function sampleAudioSpectrumScale(glyphIndex, totalGlyphs, config, signals, frame, fps) {
|
|
2850
|
-
const n = Math.max(1, totalGlyphs);
|
|
2851
|
-
const norm = n > 1 ? glyphIndex / (n - 1) : .5;
|
|
2852
|
-
const minFreq = Math.max(20, config.minFreqHz);
|
|
2853
|
-
const targetFreq = minFreq * (Math.max(minFreq + 100, config.maxFreqHz) / minFreq) ** norm;
|
|
2854
|
-
let magnitude = 0;
|
|
2855
|
-
if (signals) {
|
|
2856
|
-
const sig = signals[config.signalChannel];
|
|
2857
|
-
if (typeof sig === "number") magnitude = sig;
|
|
2858
|
-
else if (typeof sig === "function") magnitude = Number(sig(frame, fps, targetFreq)) || 0;
|
|
2859
|
-
else if (typeof sig === "object" && sig !== null) {
|
|
2860
|
-
const sObj = sig;
|
|
2861
|
-
if (typeof sObj.get === "function") magnitude = Number(sObj.get({
|
|
2862
|
-
frame,
|
|
2863
|
-
fps,
|
|
2864
|
-
freq: targetFreq
|
|
2865
|
-
})) || 0;
|
|
2866
|
-
else if (Array.isArray(sObj.samples) || ArrayBuffer.isView(sObj.samples)) {
|
|
2867
|
-
const arr = sObj.samples;
|
|
2868
|
-
const binIdx = Math.floor(norm * (arr.length - 1));
|
|
2869
|
-
magnitude = Number(arr[binIdx]) || 0;
|
|
2870
|
-
}
|
|
2871
|
-
}
|
|
2872
|
-
}
|
|
2873
|
-
const clampedMag = Math.max(0, Math.min(1, magnitude));
|
|
2874
|
-
return config.minScale + clampedMag * (config.maxScale - config.minScale);
|
|
2875
|
-
}
|
|
2876
|
-
/**
|
|
2877
|
-
* Evaluates a point on a cubic Bezier curve at parameter t in [0, 1].
|
|
2878
|
-
*/
|
|
2879
|
-
function evaluateCubicBezier(segment, t) {
|
|
2880
|
-
const u = 1 - t;
|
|
2881
|
-
const tt = t * t;
|
|
2882
|
-
const uu = u * u;
|
|
2883
|
-
const uuu = uu * u;
|
|
2884
|
-
const ttt = tt * t;
|
|
2885
|
-
return {
|
|
2886
|
-
x: uuu * segment.p0.x + 3 * uu * t * segment.p1.x + 3 * u * tt * segment.p2.x + ttt * segment.p3.x,
|
|
2887
|
-
y: uuu * segment.p0.y + 3 * uu * t * segment.p1.y + 3 * u * tt * segment.p2.y + ttt * segment.p3.y
|
|
2888
|
-
};
|
|
2889
|
-
}
|
|
2890
|
-
/**
|
|
2891
|
-
* Evaluates the first derivative (tangent velocity vector) of a cubic Bezier curve at parameter t.
|
|
2892
|
-
*/
|
|
2893
|
-
function evaluateCubicBezierDerivative(segment, t) {
|
|
2894
|
-
const u = 1 - t;
|
|
2895
|
-
return {
|
|
2896
|
-
x: 3 * u * u * (segment.p1.x - segment.p0.x) + 6 * u * t * (segment.p2.x - segment.p1.x) + 3 * t * t * (segment.p3.x - segment.p2.x),
|
|
2897
|
-
y: 3 * u * u * (segment.p1.y - segment.p0.y) + 6 * u * t * (segment.p2.y - segment.p1.y) + 3 * t * t * (segment.p3.y - segment.p2.y)
|
|
2898
|
-
};
|
|
2899
|
-
}
|
|
2900
|
-
/**
|
|
2901
|
-
* Generates an arc-length parameterization lookup table (LUT) for a cubic Bezier segment.
|
|
2902
|
-
* Ensures glyphs travel with uniform speed and do not bunch up on tight curve bends.
|
|
2903
|
-
*/
|
|
2904
|
-
function generateArcLengthLUT(segment, samples = 100) {
|
|
2905
|
-
const lut = [{
|
|
2906
|
-
distance: 0,
|
|
2907
|
-
t: 0
|
|
2908
|
-
}];
|
|
2909
|
-
let accumulatedDist = 0;
|
|
2910
|
-
let prevPoint = segment.p0;
|
|
2911
|
-
for (let i = 1; i <= samples; i++) {
|
|
2912
|
-
const t = i / samples;
|
|
2913
|
-
const currentPoint = evaluateCubicBezier(segment, t);
|
|
2914
|
-
const dx = currentPoint.x - prevPoint.x;
|
|
2915
|
-
const dy = currentPoint.y - prevPoint.y;
|
|
2916
|
-
accumulatedDist += Math.hypot(dx, dy);
|
|
2917
|
-
lut.push({
|
|
2918
|
-
distance: accumulatedDist,
|
|
2919
|
-
t
|
|
2920
|
-
});
|
|
2921
|
-
prevPoint = currentPoint;
|
|
2922
|
-
}
|
|
2923
|
-
return {
|
|
2924
|
-
lut,
|
|
2925
|
-
totalLength: accumulatedDist
|
|
2926
|
-
};
|
|
2927
|
-
}
|
|
2928
|
-
/**
|
|
2929
|
-
* Maps a distance along the curve (in pixels) to normalized curve parameter t via binary search on the LUT.
|
|
2930
|
-
*/
|
|
2931
|
-
function distanceToCurveParameter(lut, distance, totalLength) {
|
|
2932
|
-
if (distance <= 0) return 0;
|
|
2933
|
-
if (distance >= totalLength) return 1;
|
|
2934
|
-
let low = 0;
|
|
2935
|
-
let high = lut.length - 1;
|
|
2936
|
-
while (low <= high) {
|
|
2937
|
-
const mid = low + high >> 1;
|
|
2938
|
-
if (lut[mid].distance < distance) low = mid + 1;
|
|
2939
|
-
else high = mid - 1;
|
|
2940
|
-
}
|
|
2941
|
-
const index = Math.max(1, Math.min(low, lut.length - 1));
|
|
2942
|
-
const prev = lut[index - 1];
|
|
2943
|
-
const curr = lut[index];
|
|
2944
|
-
const segmentDist = curr.distance - prev.distance;
|
|
2945
|
-
if (segmentDist <= 1e-6) return prev.t;
|
|
2946
|
-
const ratio = (distance - prev.distance) / segmentDist;
|
|
2947
|
-
return prev.t + ratio * (curr.t - prev.t);
|
|
2948
|
-
}
|
|
2949
|
-
/**
|
|
2950
|
-
* Samples position and baseline tangent orientation angle along a curve at distance `dist`.
|
|
2951
|
-
*/
|
|
2952
|
-
function sampleCurveGeometry(segment, lut, totalLength, distance) {
|
|
2953
|
-
const t = distanceToCurveParameter(lut, distance, totalLength);
|
|
2954
|
-
const pos = evaluateCubicBezier(segment, t);
|
|
2955
|
-
const deriv = evaluateCubicBezierDerivative(segment, t);
|
|
2956
|
-
const length = Math.hypot(deriv.x, deriv.y);
|
|
2957
|
-
const nx = length > 1e-6 ? -deriv.y / length : 0;
|
|
2958
|
-
const ny = length > 1e-6 ? deriv.x / length : 1;
|
|
2959
|
-
return {
|
|
2960
|
-
position: pos,
|
|
2961
|
-
tangentAngleDeg: Math.atan2(deriv.y, deriv.x) * 180 / Math.PI,
|
|
2962
|
-
normal: {
|
|
2963
|
-
x: nx,
|
|
2964
|
-
y: ny
|
|
2965
|
-
}
|
|
2966
|
-
};
|
|
2967
|
-
}
|
|
2968
|
-
/**
|
|
2969
|
-
* Builds a cumulative Arc-Length LUT across a chain of Cubic Bezier segments.
|
|
2970
|
-
*/
|
|
2971
|
-
function buildPathLUT(segments, samplesPerSegment = 50) {
|
|
2972
|
-
if (segments.length === 0) return {
|
|
2973
|
-
totalLength: 0,
|
|
2974
|
-
entries: [{
|
|
2975
|
-
distance: 0,
|
|
2976
|
-
segmentIndex: 0,
|
|
2977
|
-
t: 0
|
|
2978
|
-
}],
|
|
2979
|
-
segments: []
|
|
2980
|
-
};
|
|
2981
|
-
const segLuts = [];
|
|
2982
|
-
const entries = [];
|
|
2983
|
-
let accumulatedDist = 0;
|
|
2984
|
-
for (let segIdx = 0; segIdx < segments.length; segIdx++) {
|
|
2985
|
-
const seg = segments[segIdx];
|
|
2986
|
-
const { lut: segLut, totalLength: segLength } = generateArcLengthLUT(seg, samplesPerSegment);
|
|
2987
|
-
segLuts.push({
|
|
2988
|
-
segmentIndex: segIdx,
|
|
2989
|
-
startDistance: accumulatedDist,
|
|
2990
|
-
length: segLength,
|
|
2991
|
-
lut: segLut
|
|
2992
|
-
});
|
|
2993
|
-
for (let i = 0; i < segLut.length; i++) entries.push({
|
|
2994
|
-
distance: accumulatedDist + segLut[i].distance,
|
|
2995
|
-
segmentIndex: segIdx,
|
|
2996
|
-
t: segLut[i].t
|
|
2997
|
-
});
|
|
2998
|
-
accumulatedDist += segLength;
|
|
2999
|
-
}
|
|
3000
|
-
return {
|
|
3001
|
-
totalLength: accumulatedDist,
|
|
3002
|
-
entries,
|
|
3003
|
-
segments: segLuts
|
|
3004
|
-
};
|
|
3005
|
-
}
|
|
3006
|
-
/**
|
|
3007
|
-
* Samples position, tangent angle, and normal across a chain of Cubic Bezier segments.
|
|
3008
|
-
*/
|
|
3009
|
-
function samplePathChainGeometry(segments, chainLUT, distance) {
|
|
3010
|
-
if (segments.length === 0) return {
|
|
3011
|
-
position: {
|
|
3012
|
-
x: 0,
|
|
3013
|
-
y: 0
|
|
3014
|
-
},
|
|
3015
|
-
tangentAngleDeg: 0,
|
|
3016
|
-
normal: {
|
|
3017
|
-
x: 0,
|
|
3018
|
-
y: 1
|
|
3019
|
-
}
|
|
3020
|
-
};
|
|
3021
|
-
const totalLength = chainLUT.totalLength;
|
|
3022
|
-
if (distance <= 0) {
|
|
3023
|
-
const seg = segments[0];
|
|
3024
|
-
const deriv$1 = evaluateCubicBezierDerivative(seg, 0);
|
|
3025
|
-
const length$1 = Math.hypot(deriv$1.x, deriv$1.y);
|
|
3026
|
-
const ux = length$1 > 1e-6 ? deriv$1.x / length$1 : 1;
|
|
3027
|
-
const uy = length$1 > 1e-6 ? deriv$1.y / length$1 : 0;
|
|
3028
|
-
const pos$1 = {
|
|
3029
|
-
x: seg.p0.x + ux * distance,
|
|
3030
|
-
y: seg.p0.y + uy * distance
|
|
3031
|
-
};
|
|
3032
|
-
const nx$1 = length$1 > 1e-6 ? -deriv$1.y / length$1 : 0;
|
|
3033
|
-
const ny$1 = length$1 > 1e-6 ? deriv$1.x / length$1 : 1;
|
|
3034
|
-
return {
|
|
3035
|
-
position: pos$1,
|
|
3036
|
-
tangentAngleDeg: Math.atan2(deriv$1.y, deriv$1.x) * 180 / Math.PI,
|
|
3037
|
-
normal: {
|
|
3038
|
-
x: nx$1,
|
|
3039
|
-
y: ny$1
|
|
3040
|
-
}
|
|
3041
|
-
};
|
|
3042
|
-
}
|
|
3043
|
-
if (distance >= totalLength) {
|
|
3044
|
-
const lastSeg = segments[segments.length - 1];
|
|
3045
|
-
const deriv$1 = evaluateCubicBezierDerivative(lastSeg, 1);
|
|
3046
|
-
const length$1 = Math.hypot(deriv$1.x, deriv$1.y);
|
|
3047
|
-
const ux = length$1 > 1e-6 ? deriv$1.x / length$1 : 1;
|
|
3048
|
-
const uy = length$1 > 1e-6 ? deriv$1.y / length$1 : 0;
|
|
3049
|
-
const overflow = distance - totalLength;
|
|
3050
|
-
const pos$1 = {
|
|
3051
|
-
x: lastSeg.p3.x + ux * overflow,
|
|
3052
|
-
y: lastSeg.p3.y + uy * overflow
|
|
3053
|
-
};
|
|
3054
|
-
const nx$1 = length$1 > 1e-6 ? -deriv$1.y / length$1 : 0;
|
|
3055
|
-
const ny$1 = length$1 > 1e-6 ? deriv$1.x / length$1 : 1;
|
|
3056
|
-
return {
|
|
3057
|
-
position: pos$1,
|
|
3058
|
-
tangentAngleDeg: Math.atan2(deriv$1.y, deriv$1.x) * 180 / Math.PI,
|
|
3059
|
-
normal: {
|
|
3060
|
-
x: nx$1,
|
|
3061
|
-
y: ny$1
|
|
3062
|
-
}
|
|
3063
|
-
};
|
|
3064
|
-
}
|
|
3065
|
-
let segIdx = 0;
|
|
3066
|
-
let t = 0;
|
|
3067
|
-
if (chainLUT.segments && chainLUT.segments.length > 0) {
|
|
3068
|
-
let low = 0;
|
|
3069
|
-
let high = chainLUT.segments.length - 1;
|
|
3070
|
-
while (low <= high) {
|
|
3071
|
-
const mid = low + high >> 1;
|
|
3072
|
-
const segLUT$1 = chainLUT.segments[mid];
|
|
3073
|
-
if (distance < segLUT$1.startDistance) high = mid - 1;
|
|
3074
|
-
else if (distance > segLUT$1.startDistance + segLUT$1.length) low = mid + 1;
|
|
3075
|
-
else {
|
|
3076
|
-
low = mid;
|
|
3077
|
-
break;
|
|
3078
|
-
}
|
|
3079
|
-
}
|
|
3080
|
-
const sIdx = Math.max(0, Math.min(low, chainLUT.segments.length - 1));
|
|
3081
|
-
const segLUT = chainLUT.segments[sIdx];
|
|
3082
|
-
segIdx = segLUT.segmentIndex;
|
|
3083
|
-
const localDist = distance - segLUT.startDistance;
|
|
3084
|
-
t = distanceToCurveParameter(segLUT.lut, localDist, segLUT.length);
|
|
3085
|
-
} else {
|
|
3086
|
-
let low = 0;
|
|
3087
|
-
let high = chainLUT.entries.length - 1;
|
|
3088
|
-
while (low <= high) {
|
|
3089
|
-
const mid = low + high >> 1;
|
|
3090
|
-
if (chainLUT.entries[mid].distance < distance) low = mid + 1;
|
|
3091
|
-
else high = mid - 1;
|
|
3092
|
-
}
|
|
3093
|
-
const index = Math.max(1, Math.min(low, chainLUT.entries.length - 1));
|
|
3094
|
-
const prev = chainLUT.entries[index - 1];
|
|
3095
|
-
const curr = chainLUT.entries[index];
|
|
3096
|
-
const segmentDist = curr.distance - prev.distance;
|
|
3097
|
-
const ratio = segmentDist > 1e-6 ? (distance - prev.distance) / segmentDist : 0;
|
|
3098
|
-
segIdx = curr.segmentIndex;
|
|
3099
|
-
t = prev.segmentIndex === curr.segmentIndex ? prev.t + ratio * (curr.t - prev.t) : curr.t;
|
|
3100
|
-
}
|
|
3101
|
-
const segment = segments[segIdx] ?? segments[0];
|
|
3102
|
-
const pos = evaluateCubicBezier(segment, t);
|
|
3103
|
-
const deriv = evaluateCubicBezierDerivative(segment, t);
|
|
3104
|
-
const length = Math.hypot(deriv.x, deriv.y);
|
|
3105
|
-
const nx = length > 1e-6 ? -deriv.y / length : 0;
|
|
3106
|
-
const ny = length > 1e-6 ? deriv.x / length : 1;
|
|
3107
|
-
return {
|
|
3108
|
-
position: pos,
|
|
3109
|
-
tangentAngleDeg: Math.atan2(deriv.y, deriv.x) * 180 / Math.PI,
|
|
3110
|
-
normal: {
|
|
3111
|
-
x: nx,
|
|
3112
|
-
y: ny
|
|
3113
|
-
}
|
|
3114
|
-
};
|
|
3115
|
-
}
|
|
3116
|
-
/**
|
|
3117
|
-
* Converts an ellipse arc into cubic Bezier segments (up to 90 degrees per segment).
|
|
3118
|
-
*/
|
|
3119
|
-
function ellipseToCubicBeziers(cx, cy, rx, ry, startAngleDeg = 0, endAngleDeg = 360) {
|
|
3120
|
-
const startRad = startAngleDeg * Math.PI / 180;
|
|
3121
|
-
const totalSweep = endAngleDeg * Math.PI / 180 - startRad;
|
|
3122
|
-
const numSegments = Math.max(1, Math.ceil(Math.abs(totalSweep) / (Math.PI / 2)));
|
|
3123
|
-
const sweepStep = totalSweep / numSegments;
|
|
3124
|
-
const segments = [];
|
|
3125
|
-
for (let i = 0; i < numSegments; i++) {
|
|
3126
|
-
const a0 = startRad + i * sweepStep;
|
|
3127
|
-
const a1 = a0 + sweepStep;
|
|
3128
|
-
const halfSweep = sweepStep / 2;
|
|
3129
|
-
const k = 4 / 3 * Math.tan(halfSweep / 2);
|
|
3130
|
-
const cos0 = Math.cos(a0);
|
|
3131
|
-
const sin0 = Math.sin(a0);
|
|
3132
|
-
const cos1 = Math.cos(a1);
|
|
3133
|
-
const sin1 = Math.sin(a1);
|
|
3134
|
-
const p0 = {
|
|
3135
|
-
x: cx + rx * cos0,
|
|
3136
|
-
y: cy + ry * sin0
|
|
3137
|
-
};
|
|
3138
|
-
const p1 = {
|
|
3139
|
-
x: p0.x - k * rx * sin0,
|
|
3140
|
-
y: p0.y + k * ry * cos0
|
|
3141
|
-
};
|
|
3142
|
-
const p3 = {
|
|
3143
|
-
x: cx + rx * cos1,
|
|
3144
|
-
y: cy + ry * sin1
|
|
3145
|
-
};
|
|
3146
|
-
const p2 = {
|
|
3147
|
-
x: p3.x + k * rx * sin1,
|
|
3148
|
-
y: p3.y - k * ry * cos1
|
|
3149
|
-
};
|
|
3150
|
-
segments.push({
|
|
3151
|
-
p0,
|
|
3152
|
-
p1,
|
|
3153
|
-
p2,
|
|
3154
|
-
p3
|
|
3155
|
-
});
|
|
3156
|
-
}
|
|
3157
|
-
return segments;
|
|
3158
|
-
}
|
|
3159
|
-
/**
|
|
3160
|
-
* Converts a sinusoidal wave into cubic Bezier segments per half-cycle.
|
|
3161
|
-
*/
|
|
3162
|
-
function waveToCubicBeziers(startX, startY, length, amplitude, frequency, phaseDeg = 0) {
|
|
3163
|
-
const phaseRad = phaseDeg * Math.PI / 180;
|
|
3164
|
-
const totalCycles = frequency < .1 && frequency * length >= .25 ? frequency * length : Math.max(.5, frequency);
|
|
3165
|
-
const halfCycles = Math.max(1, Math.round(totalCycles * 2));
|
|
3166
|
-
const dx = length / halfCycles;
|
|
3167
|
-
const segments = [];
|
|
3168
|
-
for (let i = 0; i < halfCycles; i++) {
|
|
3169
|
-
const t0 = i / halfCycles * (2 * Math.PI * totalCycles) + phaseRad;
|
|
3170
|
-
const t1 = (i + 1) / halfCycles * (2 * Math.PI * totalCycles) + phaseRad;
|
|
3171
|
-
const x0 = startX + i * dx;
|
|
3172
|
-
const x3 = startX + (i + 1) * dx;
|
|
3173
|
-
const y0 = startY + amplitude * Math.sin(t0);
|
|
3174
|
-
const y3 = startY + amplitude * Math.sin(t1);
|
|
3175
|
-
const slope0 = amplitude * Math.cos(t0) * (Math.PI / 3);
|
|
3176
|
-
const slope1 = amplitude * Math.cos(t1) * (Math.PI / 3);
|
|
3177
|
-
const p0 = {
|
|
3178
|
-
x: x0,
|
|
3179
|
-
y: y0
|
|
3180
|
-
};
|
|
3181
|
-
const p1 = {
|
|
3182
|
-
x: x0 + dx / 3,
|
|
3183
|
-
y: y0 + slope0
|
|
3184
|
-
};
|
|
3185
|
-
const p2 = {
|
|
3186
|
-
x: x3 - dx / 3,
|
|
3187
|
-
y: y3 - slope1
|
|
3188
|
-
};
|
|
3189
|
-
const p3 = {
|
|
3190
|
-
x: x3,
|
|
3191
|
-
y: y3
|
|
3192
|
-
};
|
|
3193
|
-
segments.push({
|
|
3194
|
-
p0,
|
|
3195
|
-
p1,
|
|
3196
|
-
p2,
|
|
3197
|
-
p3
|
|
3198
|
-
});
|
|
3199
|
-
}
|
|
3200
|
-
return segments;
|
|
3201
|
-
}
|
|
3202
|
-
/**
|
|
3203
|
-
* An SVG elliptical arc (endpoint form, SVG 1.1 F.6.5) as cubic Bezier
|
|
3204
|
-
* segments of at most 90° each.
|
|
3205
|
-
*/
|
|
3206
|
-
function svgArcToCubicBeziers(x1, y1, rxIn, ryIn, rotationDeg, largeArc, sweep, x2, y2) {
|
|
3207
|
-
if (x1 === x2 && y1 === y2) return [];
|
|
3208
|
-
let rx = Math.abs(rxIn);
|
|
3209
|
-
let ry = Math.abs(ryIn);
|
|
3210
|
-
if (rx === 0 || ry === 0) return [{
|
|
3211
|
-
p0: {
|
|
3212
|
-
x: x1,
|
|
3213
|
-
y: y1
|
|
3214
|
-
},
|
|
3215
|
-
p1: {
|
|
3216
|
-
x: x1 + (x2 - x1) / 3,
|
|
3217
|
-
y: y1 + (y2 - y1) / 3
|
|
3218
|
-
},
|
|
3219
|
-
p2: {
|
|
3220
|
-
x: x1 + 2 * (x2 - x1) / 3,
|
|
3221
|
-
y: y1 + 2 * (y2 - y1) / 3
|
|
3222
|
-
},
|
|
3223
|
-
p3: {
|
|
3224
|
-
x: x2,
|
|
3225
|
-
y: y2
|
|
3226
|
-
}
|
|
3227
|
-
}];
|
|
3228
|
-
const phi = rotationDeg * Math.PI / 180;
|
|
3229
|
-
const cosPhi = Math.cos(phi);
|
|
3230
|
-
const sinPhi = Math.sin(phi);
|
|
3231
|
-
const dx = (x1 - x2) / 2;
|
|
3232
|
-
const dy = (y1 - y2) / 2;
|
|
3233
|
-
const x1p = cosPhi * dx + sinPhi * dy;
|
|
3234
|
-
const y1p = -sinPhi * dx + cosPhi * dy;
|
|
3235
|
-
const lambda = x1p * x1p / (rx * rx) + y1p * y1p / (ry * ry);
|
|
3236
|
-
if (lambda > 1) {
|
|
3237
|
-
rx *= Math.sqrt(lambda);
|
|
3238
|
-
ry *= Math.sqrt(lambda);
|
|
3239
|
-
}
|
|
3240
|
-
const num = rx * rx * ry * ry - rx * rx * y1p * y1p - ry * ry * x1p * x1p;
|
|
3241
|
-
const den = rx * rx * y1p * y1p + ry * ry * x1p * x1p;
|
|
3242
|
-
const coef = (largeArc !== sweep ? 1 : -1) * Math.sqrt(Math.max(0, num / den));
|
|
3243
|
-
const cxp = coef * rx * y1p / ry;
|
|
3244
|
-
const cyp = -coef * ry * x1p / rx;
|
|
3245
|
-
const cx = cosPhi * cxp - sinPhi * cyp + (x1 + x2) / 2;
|
|
3246
|
-
const cy = sinPhi * cxp + cosPhi * cyp + (y1 + y2) / 2;
|
|
3247
|
-
const angle = (ux, uy, vx, vy) => Math.atan2(ux * vy - uy * vx, ux * vx + uy * vy);
|
|
3248
|
-
const theta1 = angle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
|
|
3249
|
-
let delta = angle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx, (-y1p - cyp) / ry);
|
|
3250
|
-
if (!sweep && delta > 0) delta -= 2 * Math.PI;
|
|
3251
|
-
if (sweep && delta < 0) delta += 2 * Math.PI;
|
|
3252
|
-
const n = Math.max(1, Math.ceil(Math.abs(delta) / (Math.PI / 2)));
|
|
3253
|
-
const step = delta / n;
|
|
3254
|
-
const k = 4 / 3 * Math.tan(step / 4);
|
|
3255
|
-
const point = (a) => ({
|
|
3256
|
-
x: cx + rx * Math.cos(a) * cosPhi - ry * Math.sin(a) * sinPhi,
|
|
3257
|
-
y: cy + rx * Math.cos(a) * sinPhi + ry * Math.sin(a) * cosPhi
|
|
3258
|
-
});
|
|
3259
|
-
const tangent = (a) => ({
|
|
3260
|
-
x: -rx * Math.sin(a) * cosPhi - ry * Math.cos(a) * sinPhi,
|
|
3261
|
-
y: -rx * Math.sin(a) * sinPhi + ry * Math.cos(a) * cosPhi
|
|
3262
|
-
});
|
|
3263
|
-
const segments = [];
|
|
3264
|
-
for (let s = 0; s < n; s++) {
|
|
3265
|
-
const a0 = theta1 + s * step;
|
|
3266
|
-
const a1 = a0 + step;
|
|
3267
|
-
const p0 = point(a0);
|
|
3268
|
-
const p3 = point(a1);
|
|
3269
|
-
const t0 = tangent(a0);
|
|
3270
|
-
const t1 = tangent(a1);
|
|
3271
|
-
segments.push({
|
|
3272
|
-
p0,
|
|
3273
|
-
p1: {
|
|
3274
|
-
x: p0.x + k * t0.x,
|
|
3275
|
-
y: p0.y + k * t0.y
|
|
3276
|
-
},
|
|
3277
|
-
p2: {
|
|
3278
|
-
x: p3.x - k * t1.x,
|
|
3279
|
-
y: p3.y - k * t1.y
|
|
3280
|
-
},
|
|
3281
|
-
p3
|
|
3282
|
-
});
|
|
3283
|
-
}
|
|
3284
|
-
segments[segments.length - 1].p3 = {
|
|
3285
|
-
x: x2,
|
|
3286
|
-
y: y2
|
|
3287
|
-
};
|
|
3288
|
-
return segments;
|
|
3289
|
-
}
|
|
3290
|
-
/**
|
|
3291
|
-
* Converts SVG path data string into a chain of Cubic Bezier segments.
|
|
3292
|
-
*/
|
|
3293
|
-
function parseSvgPathToCubicBeziers(d) {
|
|
3294
|
-
const segments = [];
|
|
3295
|
-
const tokens = d.match(/[a-df-z]|[-+]?(?:\d*\.\d+|\d+)(?:[eE][-+]?\d+)?/gi);
|
|
3296
|
-
if (!tokens || tokens.length === 0) return segments;
|
|
3297
|
-
let currentX = 0;
|
|
3298
|
-
let currentY = 0;
|
|
3299
|
-
let startX = 0;
|
|
3300
|
-
let startY = 0;
|
|
3301
|
-
let lastControlX = 0;
|
|
3302
|
-
let lastControlY = 0;
|
|
3303
|
-
let lastCommand = "";
|
|
3304
|
-
let i = 0;
|
|
3305
|
-
const nextNum = () => {
|
|
3306
|
-
if (i >= tokens.length) return 0;
|
|
3307
|
-
return Number.parseFloat(tokens[i++]);
|
|
3308
|
-
};
|
|
3309
|
-
while (i < tokens.length) {
|
|
3310
|
-
const token = tokens[i++];
|
|
3311
|
-
const isCommand = /^[a-df-z]$/i.test(token);
|
|
3312
|
-
const cmd = isCommand ? token : lastCommand;
|
|
3313
|
-
if (!isCommand) i--;
|
|
3314
|
-
switch (cmd) {
|
|
3315
|
-
case "M":
|
|
3316
|
-
currentX = nextNum();
|
|
3317
|
-
currentY = nextNum();
|
|
3318
|
-
startX = currentX;
|
|
3319
|
-
startY = currentY;
|
|
3320
|
-
lastCommand = "L";
|
|
3321
|
-
break;
|
|
3322
|
-
case "m":
|
|
3323
|
-
currentX += nextNum();
|
|
3324
|
-
currentY += nextNum();
|
|
3325
|
-
startX = currentX;
|
|
3326
|
-
startY = currentY;
|
|
3327
|
-
lastCommand = "l";
|
|
3328
|
-
break;
|
|
3329
|
-
case "L": {
|
|
3330
|
-
const x = nextNum();
|
|
3331
|
-
const y = nextNum();
|
|
3332
|
-
segments.push({
|
|
3333
|
-
p0: {
|
|
3334
|
-
x: currentX,
|
|
3335
|
-
y: currentY
|
|
3336
|
-
},
|
|
3337
|
-
p1: {
|
|
3338
|
-
x: currentX + (x - currentX) / 3,
|
|
3339
|
-
y: currentY + (y - currentY) / 3
|
|
3340
|
-
},
|
|
3341
|
-
p2: {
|
|
3342
|
-
x: currentX + 2 * (x - currentX) / 3,
|
|
3343
|
-
y: currentY + 2 * (y - currentY) / 3
|
|
3344
|
-
},
|
|
3345
|
-
p3: {
|
|
3346
|
-
x,
|
|
3347
|
-
y
|
|
3348
|
-
}
|
|
3349
|
-
});
|
|
3350
|
-
currentX = x;
|
|
3351
|
-
currentY = y;
|
|
3352
|
-
lastCommand = "L";
|
|
3353
|
-
break;
|
|
3354
|
-
}
|
|
3355
|
-
case "l": {
|
|
3356
|
-
const dx = nextNum();
|
|
3357
|
-
const dy = nextNum();
|
|
3358
|
-
const x = currentX + dx;
|
|
3359
|
-
const y = currentY + dy;
|
|
3360
|
-
segments.push({
|
|
3361
|
-
p0: {
|
|
3362
|
-
x: currentX,
|
|
3363
|
-
y: currentY
|
|
3364
|
-
},
|
|
3365
|
-
p1: {
|
|
3366
|
-
x: currentX + dx / 3,
|
|
3367
|
-
y: currentY + dy / 3
|
|
3368
|
-
},
|
|
3369
|
-
p2: {
|
|
3370
|
-
x: currentX + 2 * dx / 3,
|
|
3371
|
-
y: currentY + 2 * dy / 3
|
|
3372
|
-
},
|
|
3373
|
-
p3: {
|
|
3374
|
-
x,
|
|
3375
|
-
y
|
|
3376
|
-
}
|
|
3377
|
-
});
|
|
3378
|
-
currentX = x;
|
|
3379
|
-
currentY = y;
|
|
3380
|
-
lastCommand = "l";
|
|
3381
|
-
break;
|
|
3382
|
-
}
|
|
3383
|
-
case "H": {
|
|
3384
|
-
const x = nextNum();
|
|
3385
|
-
segments.push({
|
|
3386
|
-
p0: {
|
|
3387
|
-
x: currentX,
|
|
3388
|
-
y: currentY
|
|
3389
|
-
},
|
|
3390
|
-
p1: {
|
|
3391
|
-
x: currentX + (x - currentX) / 3,
|
|
3392
|
-
y: currentY
|
|
3393
|
-
},
|
|
3394
|
-
p2: {
|
|
3395
|
-
x: currentX + 2 * (x - currentX) / 3,
|
|
3396
|
-
y: currentY
|
|
3397
|
-
},
|
|
3398
|
-
p3: {
|
|
3399
|
-
x,
|
|
3400
|
-
y: currentY
|
|
3401
|
-
}
|
|
3402
|
-
});
|
|
3403
|
-
currentX = x;
|
|
3404
|
-
lastCommand = "H";
|
|
3405
|
-
break;
|
|
3406
|
-
}
|
|
3407
|
-
case "h": {
|
|
3408
|
-
const dx = nextNum();
|
|
3409
|
-
const x = currentX + dx;
|
|
3410
|
-
segments.push({
|
|
3411
|
-
p0: {
|
|
3412
|
-
x: currentX,
|
|
3413
|
-
y: currentY
|
|
3414
|
-
},
|
|
3415
|
-
p1: {
|
|
3416
|
-
x: currentX + dx / 3,
|
|
3417
|
-
y: currentY
|
|
3418
|
-
},
|
|
3419
|
-
p2: {
|
|
3420
|
-
x: currentX + 2 * dx / 3,
|
|
3421
|
-
y: currentY
|
|
3422
|
-
},
|
|
3423
|
-
p3: {
|
|
3424
|
-
x,
|
|
3425
|
-
y: currentY
|
|
3426
|
-
}
|
|
3427
|
-
});
|
|
3428
|
-
currentX = x;
|
|
3429
|
-
lastCommand = "h";
|
|
3430
|
-
break;
|
|
3431
|
-
}
|
|
3432
|
-
case "V": {
|
|
3433
|
-
const y = nextNum();
|
|
3434
|
-
segments.push({
|
|
3435
|
-
p0: {
|
|
3436
|
-
x: currentX,
|
|
3437
|
-
y: currentY
|
|
3438
|
-
},
|
|
3439
|
-
p1: {
|
|
3440
|
-
x: currentX,
|
|
3441
|
-
y: currentY + (y - currentY) / 3
|
|
3442
|
-
},
|
|
3443
|
-
p2: {
|
|
3444
|
-
x: currentX,
|
|
3445
|
-
y: currentY + 2 * (y - currentY) / 3
|
|
3446
|
-
},
|
|
3447
|
-
p3: {
|
|
3448
|
-
x: currentX,
|
|
3449
|
-
y
|
|
3450
|
-
}
|
|
3451
|
-
});
|
|
3452
|
-
currentY = y;
|
|
3453
|
-
lastCommand = "V";
|
|
3454
|
-
break;
|
|
3455
|
-
}
|
|
3456
|
-
case "v": {
|
|
3457
|
-
const dy = nextNum();
|
|
3458
|
-
const y = currentY + dy;
|
|
3459
|
-
segments.push({
|
|
3460
|
-
p0: {
|
|
3461
|
-
x: currentX,
|
|
3462
|
-
y: currentY
|
|
3463
|
-
},
|
|
3464
|
-
p1: {
|
|
3465
|
-
x: currentX,
|
|
3466
|
-
y: currentY + dy / 3
|
|
3467
|
-
},
|
|
3468
|
-
p2: {
|
|
3469
|
-
x: currentX,
|
|
3470
|
-
y: currentY + 2 * dy / 3
|
|
3471
|
-
},
|
|
3472
|
-
p3: {
|
|
3473
|
-
x: currentX,
|
|
3474
|
-
y
|
|
3475
|
-
}
|
|
3476
|
-
});
|
|
3477
|
-
currentY = y;
|
|
3478
|
-
lastCommand = "v";
|
|
3479
|
-
break;
|
|
3480
|
-
}
|
|
3481
|
-
case "C": {
|
|
3482
|
-
const x1 = nextNum();
|
|
3483
|
-
const y1 = nextNum();
|
|
3484
|
-
const x2 = nextNum();
|
|
3485
|
-
const y2 = nextNum();
|
|
3486
|
-
const x = nextNum();
|
|
3487
|
-
const y = nextNum();
|
|
3488
|
-
segments.push({
|
|
3489
|
-
p0: {
|
|
3490
|
-
x: currentX,
|
|
3491
|
-
y: currentY
|
|
3492
|
-
},
|
|
3493
|
-
p1: {
|
|
3494
|
-
x: x1,
|
|
3495
|
-
y: y1
|
|
3496
|
-
},
|
|
3497
|
-
p2: {
|
|
3498
|
-
x: x2,
|
|
3499
|
-
y: y2
|
|
3500
|
-
},
|
|
3501
|
-
p3: {
|
|
3502
|
-
x,
|
|
3503
|
-
y
|
|
3504
|
-
}
|
|
3505
|
-
});
|
|
3506
|
-
lastControlX = x2;
|
|
3507
|
-
lastControlY = y2;
|
|
3508
|
-
currentX = x;
|
|
3509
|
-
currentY = y;
|
|
3510
|
-
lastCommand = "C";
|
|
3511
|
-
break;
|
|
3512
|
-
}
|
|
3513
|
-
case "c": {
|
|
3514
|
-
const dx1 = nextNum();
|
|
3515
|
-
const dy1 = nextNum();
|
|
3516
|
-
const dx2 = nextNum();
|
|
3517
|
-
const dy2 = nextNum();
|
|
3518
|
-
const dx = nextNum();
|
|
3519
|
-
const dy = nextNum();
|
|
3520
|
-
const x1 = currentX + dx1;
|
|
3521
|
-
const y1 = currentY + dy1;
|
|
3522
|
-
const x2 = currentX + dx2;
|
|
3523
|
-
const y2 = currentY + dy2;
|
|
3524
|
-
const x = currentX + dx;
|
|
3525
|
-
const y = currentY + dy;
|
|
3526
|
-
segments.push({
|
|
3527
|
-
p0: {
|
|
3528
|
-
x: currentX,
|
|
3529
|
-
y: currentY
|
|
3530
|
-
},
|
|
3531
|
-
p1: {
|
|
3532
|
-
x: x1,
|
|
3533
|
-
y: y1
|
|
3534
|
-
},
|
|
3535
|
-
p2: {
|
|
3536
|
-
x: x2,
|
|
3537
|
-
y: y2
|
|
3538
|
-
},
|
|
3539
|
-
p3: {
|
|
3540
|
-
x,
|
|
3541
|
-
y
|
|
3542
|
-
}
|
|
3543
|
-
});
|
|
3544
|
-
lastControlX = x2;
|
|
3545
|
-
lastControlY = y2;
|
|
3546
|
-
currentX = x;
|
|
3547
|
-
currentY = y;
|
|
3548
|
-
lastCommand = "c";
|
|
3549
|
-
break;
|
|
3550
|
-
}
|
|
3551
|
-
case "S":
|
|
3552
|
-
case "s": {
|
|
3553
|
-
const isRel = cmd === "s";
|
|
3554
|
-
const dx2 = nextNum();
|
|
3555
|
-
const dy2 = nextNum();
|
|
3556
|
-
const dx = nextNum();
|
|
3557
|
-
const dy = nextNum();
|
|
3558
|
-
const x2 = isRel ? currentX + dx2 : dx2;
|
|
3559
|
-
const y2 = isRel ? currentY + dy2 : dy2;
|
|
3560
|
-
const x = isRel ? currentX + dx : dx;
|
|
3561
|
-
const y = isRel ? currentY + dy : dy;
|
|
3562
|
-
let x1 = currentX;
|
|
3563
|
-
let y1 = currentY;
|
|
3564
|
-
if (/^[cs]$/i.test(lastCommand)) {
|
|
3565
|
-
x1 = 2 * currentX - lastControlX;
|
|
3566
|
-
y1 = 2 * currentY - lastControlY;
|
|
3567
|
-
}
|
|
3568
|
-
segments.push({
|
|
3569
|
-
p0: {
|
|
3570
|
-
x: currentX,
|
|
3571
|
-
y: currentY
|
|
3572
|
-
},
|
|
3573
|
-
p1: {
|
|
3574
|
-
x: x1,
|
|
3575
|
-
y: y1
|
|
3576
|
-
},
|
|
3577
|
-
p2: {
|
|
3578
|
-
x: x2,
|
|
3579
|
-
y: y2
|
|
3580
|
-
},
|
|
3581
|
-
p3: {
|
|
3582
|
-
x,
|
|
3583
|
-
y
|
|
3584
|
-
}
|
|
3585
|
-
});
|
|
3586
|
-
lastControlX = x2;
|
|
3587
|
-
lastControlY = y2;
|
|
3588
|
-
currentX = x;
|
|
3589
|
-
currentY = y;
|
|
3590
|
-
lastCommand = cmd;
|
|
3591
|
-
break;
|
|
3592
|
-
}
|
|
3593
|
-
case "Q":
|
|
3594
|
-
case "q": {
|
|
3595
|
-
const isRel = cmd === "q";
|
|
3596
|
-
const qx = nextNum();
|
|
3597
|
-
const qy = nextNum();
|
|
3598
|
-
const x = nextNum();
|
|
3599
|
-
const y = nextNum();
|
|
3600
|
-
const cx1 = isRel ? currentX + qx : qx;
|
|
3601
|
-
const cy1 = isRel ? currentY + qy : qy;
|
|
3602
|
-
const ex = isRel ? currentX + x : x;
|
|
3603
|
-
const ey = isRel ? currentY + y : y;
|
|
3604
|
-
const p1x = currentX + 2 / 3 * (cx1 - currentX);
|
|
3605
|
-
const p1y = currentY + 2 / 3 * (cy1 - currentY);
|
|
3606
|
-
const p2x = ex + 2 / 3 * (cx1 - ex);
|
|
3607
|
-
const p2y = ey + 2 / 3 * (cy1 - ey);
|
|
3608
|
-
segments.push({
|
|
3609
|
-
p0: {
|
|
3610
|
-
x: currentX,
|
|
3611
|
-
y: currentY
|
|
3612
|
-
},
|
|
3613
|
-
p1: {
|
|
3614
|
-
x: p1x,
|
|
3615
|
-
y: p1y
|
|
3616
|
-
},
|
|
3617
|
-
p2: {
|
|
3618
|
-
x: p2x,
|
|
3619
|
-
y: p2y
|
|
3620
|
-
},
|
|
3621
|
-
p3: {
|
|
3622
|
-
x: ex,
|
|
3623
|
-
y: ey
|
|
3624
|
-
}
|
|
3625
|
-
});
|
|
3626
|
-
lastControlX = cx1;
|
|
3627
|
-
lastControlY = cy1;
|
|
3628
|
-
currentX = ex;
|
|
3629
|
-
currentY = ey;
|
|
3630
|
-
lastCommand = cmd;
|
|
3631
|
-
break;
|
|
3632
|
-
}
|
|
3633
|
-
case "A":
|
|
3634
|
-
case "a": {
|
|
3635
|
-
const rx = nextNum();
|
|
3636
|
-
const ry = nextNum();
|
|
3637
|
-
const rotation = nextNum();
|
|
3638
|
-
const largeArc = nextNum() !== 0;
|
|
3639
|
-
const sweep = nextNum() !== 0;
|
|
3640
|
-
let x = nextNum();
|
|
3641
|
-
let y = nextNum();
|
|
3642
|
-
if (cmd === "a") {
|
|
3643
|
-
x += currentX;
|
|
3644
|
-
y += currentY;
|
|
3645
|
-
}
|
|
3646
|
-
segments.push(...svgArcToCubicBeziers(currentX, currentY, rx, ry, rotation, largeArc, sweep, x, y));
|
|
3647
|
-
currentX = x;
|
|
3648
|
-
currentY = y;
|
|
3649
|
-
lastControlX = x;
|
|
3650
|
-
lastControlY = y;
|
|
3651
|
-
lastCommand = cmd;
|
|
3652
|
-
break;
|
|
3653
|
-
}
|
|
3654
|
-
case "Z":
|
|
3655
|
-
case "z":
|
|
3656
|
-
if (currentX !== startX || currentY !== startY) {
|
|
3657
|
-
segments.push({
|
|
3658
|
-
p0: {
|
|
3659
|
-
x: currentX,
|
|
3660
|
-
y: currentY
|
|
3661
|
-
},
|
|
3662
|
-
p1: {
|
|
3663
|
-
x: currentX + (startX - currentX) / 3,
|
|
3664
|
-
y: currentY + (startY - currentY) / 3
|
|
3665
|
-
},
|
|
3666
|
-
p2: {
|
|
3667
|
-
x: currentX + 2 * (startX - currentX) / 3,
|
|
3668
|
-
y: currentY + 2 * (startY - currentY) / 3
|
|
3669
|
-
},
|
|
3670
|
-
p3: {
|
|
3671
|
-
x: startX,
|
|
3672
|
-
y: startY
|
|
3673
|
-
}
|
|
3674
|
-
});
|
|
3675
|
-
currentX = startX;
|
|
3676
|
-
currentY = startY;
|
|
3677
|
-
}
|
|
3678
|
-
lastCommand = cmd;
|
|
3679
|
-
break;
|
|
3680
|
-
default: break;
|
|
3681
|
-
}
|
|
3682
|
-
}
|
|
3683
|
-
return segments;
|
|
1807
|
+
node.startFrame = (typeof owner.startFrame === "number" ? owner.startFrame : 0) + (typeof src.startFrame === "number" ? src.startFrame : 0);
|
|
1808
|
+
if (src.durationFrames === void 0 && owner.durationFrames !== void 0) node.durationFrames = owner.durationFrames;
|
|
1809
|
+
if (Array.isArray(node.children)) node.children = hoistMattes(node.children);
|
|
1810
|
+
self.matteId = id;
|
|
1811
|
+
return [self, node];
|
|
3684
1812
|
}
|
|
3685
|
-
/**
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
function generatePathSegments(source) {
|
|
3689
|
-
switch (source.type) {
|
|
3690
|
-
case "bezier": return source.segments;
|
|
3691
|
-
case "svg": return parseSvgPathToCubicBeziers(source.d);
|
|
3692
|
-
case "ellipse": return ellipseToCubicBeziers(source.cx, source.cy, source.rx, source.ry, source.startAngleDeg ?? 0, source.endAngleDeg ?? 360);
|
|
3693
|
-
case "wave": return waveToCubicBeziers(source.startX, source.startY, source.length, source.amplitude, source.frequency, source.phaseDeg ?? 0);
|
|
3694
|
-
}
|
|
3695
|
-
}
|
|
3696
|
-
/**
|
|
3697
|
-
* Computes After Effects Range Selector weight for a single glyph index.
|
|
3698
|
-
*
|
|
3699
|
-
* @param index Normalized position of the glyph in the string (0.0 to 1.0)
|
|
3700
|
-
* @param start Start boundary (0.0 to 1.0)
|
|
3701
|
-
* @param end End boundary (0.0 to 1.0)
|
|
3702
|
-
* @param offset Window shift (-1.0 to 1.0)
|
|
3703
|
-
* @param shape Falloff curve
|
|
3704
|
-
* @param easeHigh Non-linear easing for high values
|
|
3705
|
-
* @param easeLow Non-linear easing for low values
|
|
3706
|
-
* @returns Weight in [0.0, 1.0]
|
|
3707
|
-
*/
|
|
3708
|
-
function computeRangeSelectorWeight(index, start, end, offset, shape, easeHigh = 0, easeLow = 0) {
|
|
3709
|
-
const effStart = start + offset;
|
|
3710
|
-
const effEnd = end + offset;
|
|
3711
|
-
if (effEnd <= effStart) return 0;
|
|
3712
|
-
const relativePos = (index - effStart) / (effEnd - effStart);
|
|
3713
|
-
let baseWeight = 0;
|
|
3714
|
-
switch (shape) {
|
|
3715
|
-
case "square":
|
|
3716
|
-
baseWeight = relativePos >= 0 && relativePos <= 1 ? 1 : 0;
|
|
3717
|
-
break;
|
|
3718
|
-
case "ramp_up":
|
|
3719
|
-
baseWeight = Math.max(0, Math.min(1, relativePos));
|
|
3720
|
-
break;
|
|
3721
|
-
case "ramp_down":
|
|
3722
|
-
baseWeight = 1 - Math.max(0, Math.min(1, relativePos));
|
|
3723
|
-
break;
|
|
3724
|
-
case "triangle":
|
|
3725
|
-
if (relativePos < 0 || relativePos > 1) baseWeight = 0;
|
|
3726
|
-
else if (relativePos < .5) baseWeight = relativePos * 2;
|
|
3727
|
-
else baseWeight = (1 - relativePos) * 2;
|
|
3728
|
-
break;
|
|
3729
|
-
case "round":
|
|
3730
|
-
if (relativePos < 0 || relativePos > 1) baseWeight = 0;
|
|
3731
|
-
else baseWeight = .5 - .5 * Math.cos(relativePos * 2 * Math.PI);
|
|
3732
|
-
break;
|
|
3733
|
-
case "smooth":
|
|
3734
|
-
if (relativePos <= 0) baseWeight = 0;
|
|
3735
|
-
else if (relativePos >= 1) baseWeight = 1;
|
|
3736
|
-
else baseWeight = relativePos * relativePos * (3 - 2 * relativePos);
|
|
3737
|
-
break;
|
|
3738
|
-
}
|
|
3739
|
-
if (baseWeight > 0 && baseWeight < 1) {
|
|
3740
|
-
if (easeHigh !== 0 && baseWeight > .5) baseWeight = .5 + .5 * ((baseWeight - .5) * 2) ** (easeHigh > 0 ? 1 + easeHigh * 3 : 1 / (1 - easeHigh * 3));
|
|
3741
|
-
if (easeLow !== 0 && baseWeight <= .5) baseWeight = .5 * (baseWeight * 2) ** (easeLow > 0 ? 1 + easeLow * 3 : 1 / (1 - easeLow * 3));
|
|
3742
|
-
}
|
|
3743
|
-
return Math.max(0, Math.min(1, baseWeight));
|
|
3744
|
-
}
|
|
3745
|
-
/**
|
|
3746
|
-
* 1D Gradient deterministic hash noise for Wiggly Selectors.
|
|
3747
|
-
*/
|
|
3748
|
-
function deterministicWigglyNoise(seed, glyphIndex, phase, correlation) {
|
|
3749
|
-
const coord = (glyphIndex * (1 - correlation) + correlation) * 12.9898 + phase + seed * 78.233;
|
|
3750
|
-
const raw = Math.sin(coord) * 43758.5453;
|
|
3751
|
-
return (raw - Math.floor(raw)) * 2 - 1;
|
|
3752
|
-
}
|
|
3753
|
-
/**
|
|
3754
|
-
* Deterministic pseudo-random number generator for seeded order shuffling.
|
|
3755
|
-
*/
|
|
3756
|
-
function getShuffledOrder(count, seed) {
|
|
3757
|
-
let s = seed;
|
|
3758
|
-
const nextRand = () => {
|
|
3759
|
-
s = (s * 9301 + 49297) % 233280;
|
|
3760
|
-
return s / 233280;
|
|
3761
|
-
};
|
|
3762
|
-
const arr = Array.from({ length: count }, (_, i) => i);
|
|
3763
|
-
for (let i = arr.length - 1; i > 0; i--) {
|
|
3764
|
-
const j = Math.floor(nextRand() * (i + 1));
|
|
3765
|
-
const temp = arr[i];
|
|
3766
|
-
arr[i] = arr[j];
|
|
3767
|
-
arr[j] = temp;
|
|
3768
|
-
}
|
|
3769
|
-
return arr;
|
|
3770
|
-
}
|
|
3771
|
-
/**
|
|
3772
|
-
* Combines consecutive selector weights using After Effects Selector Mode logic.
|
|
3773
|
-
*/
|
|
3774
|
-
function evaluateSelectorCombination(prevWeight, currWeight, mode) {
|
|
3775
|
-
switch (mode) {
|
|
3776
|
-
case "add": return Math.max(0, Math.min(1, prevWeight + currWeight));
|
|
3777
|
-
case "subtract": return Math.max(0, Math.min(1, prevWeight - currWeight));
|
|
3778
|
-
case "intersect": return prevWeight * currWeight;
|
|
3779
|
-
case "min": return Math.min(prevWeight, currWeight);
|
|
3780
|
-
case "max": return Math.max(prevWeight, currWeight);
|
|
3781
|
-
case "difference": return Math.abs(prevWeight - currWeight);
|
|
3782
|
-
}
|
|
3783
|
-
}
|
|
3784
|
-
const SCRAMBLE_POOLS = {
|
|
3785
|
-
ascii: "!@#$%^&*()_+{}[]:;<>,.?",
|
|
3786
|
-
alphanumeric: "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
|
|
3787
|
-
matrix: "010101<>[]{}+=*~#%&!?/\\:;|X0123456789",
|
|
3788
|
-
binary: "01",
|
|
3789
|
-
hex: "0123456789ABCDEF"
|
|
3790
|
-
};
|
|
3791
|
-
function getScramblePool(charset, customCharset) {
|
|
3792
|
-
if (charset === "custom" && customCharset && customCharset.length > 0) return customCharset;
|
|
3793
|
-
return SCRAMBLE_POOLS[charset] ?? SCRAMBLE_POOLS.alphanumeric;
|
|
3794
|
-
}
|
|
3795
|
-
/**
|
|
3796
|
-
* Evaluates typewriter visible character count and scramble state for frame `currentFrame`.
|
|
3797
|
-
*/
|
|
3798
|
-
function evaluateTypewriterState(fullText, currentFrame, startFrame, durationFrames, cadence = {
|
|
3799
|
-
mode: "human",
|
|
3800
|
-
jitter: .35,
|
|
3801
|
-
commaPauseMultiplier: 3,
|
|
3802
|
-
sentencePauseMultiplier: 5.5,
|
|
3803
|
-
paragraphPauseMultiplier: 7
|
|
3804
|
-
}, scramble = {
|
|
3805
|
-
enabled: false,
|
|
3806
|
-
charset: "alphanumeric",
|
|
3807
|
-
scrambleFramesPerChar: 8,
|
|
3808
|
-
highlightProbability: .25
|
|
3809
|
-
}, blinkFrequency = 2, granularity = "character", progressOverride) {
|
|
3810
|
-
if (progressOverride === void 0 && currentFrame < startFrame) return {
|
|
3811
|
-
visibleChars: 0,
|
|
3812
|
-
currentDisplayString: "",
|
|
3813
|
-
isCursorVisible: false
|
|
3814
|
-
};
|
|
3815
|
-
const progress = progressOverride !== void 0 ? Math.max(0, Math.min(1, progressOverride)) : Math.min(1, (currentFrame - startFrame) / Math.max(1, durationFrames));
|
|
3816
|
-
const elapsed = progressOverride !== void 0 ? progress * durationFrames : currentFrame - startFrame;
|
|
3817
|
-
const totalChars = fullText.length;
|
|
3818
|
-
let visibleCount = Math.floor(progress * totalChars);
|
|
3819
|
-
if (granularity === "word") {
|
|
3820
|
-
const tokens = fullText.split(/(\s+)/);
|
|
3821
|
-
const wordIndices = [];
|
|
3822
|
-
tokens.forEach((t, i) => {
|
|
3823
|
-
if (t.trim().length > 0) wordIndices.push(i);
|
|
3824
|
-
});
|
|
3825
|
-
const visibleWords = Math.min(wordIndices.length, Math.floor(progress * (wordIndices.length + 1)));
|
|
3826
|
-
if (visibleWords <= 0) visibleCount = 0;
|
|
3827
|
-
else {
|
|
3828
|
-
const lastIdx = wordIndices[Math.min(wordIndices.length - 1, visibleWords - 1)];
|
|
3829
|
-
visibleCount = tokens.slice(0, lastIdx + 1).join("").length;
|
|
3830
|
-
}
|
|
3831
|
-
} else if (granularity === "line") {
|
|
3832
|
-
const lines = fullText.split("\n");
|
|
3833
|
-
const visibleLines = Math.min(lines.length, Math.floor(progress * (lines.length + 1)));
|
|
3834
|
-
visibleCount = lines.slice(0, visibleLines).join("\n").length;
|
|
3835
|
-
} else if (cadence.mode === "human" && progress < 1) {
|
|
3836
|
-
let simulatedCharIndex = 0;
|
|
3837
|
-
let simulatedElapsed = 0;
|
|
3838
|
-
const baseFramesPerChar = durationFrames / Math.max(1, totalChars);
|
|
3839
|
-
for (let i = 0; i < totalChars; i++) {
|
|
3840
|
-
const char = fullText[i];
|
|
3841
|
-
let multiplier = 1;
|
|
3842
|
-
const commaMult = cadence.commaPauseMultiplier ?? 3;
|
|
3843
|
-
const sentenceMult = cadence.sentencePauseMultiplier ?? 5.5;
|
|
3844
|
-
const paraMult = cadence.paragraphPauseMultiplier ?? 7;
|
|
3845
|
-
const jitter = cadence.jitter ?? .35;
|
|
3846
|
-
if (char === "," || char === ";") multiplier = commaMult;
|
|
3847
|
-
else if (char === "." || char === "!" || char === "?") multiplier = sentenceMult;
|
|
3848
|
-
else if (char === "\n") multiplier = paraMult;
|
|
3849
|
-
const jitterVal = 1 + Math.sin(i * 17.3 + 42) * .5 * jitter;
|
|
3850
|
-
const charDuration = baseFramesPerChar * multiplier * jitterVal;
|
|
3851
|
-
simulatedElapsed += charDuration;
|
|
3852
|
-
if (simulatedElapsed <= elapsed) simulatedCharIndex = i + 1;
|
|
3853
|
-
else break;
|
|
3854
|
-
}
|
|
3855
|
-
visibleCount = Math.min(totalChars, simulatedCharIndex);
|
|
3856
|
-
}
|
|
3857
|
-
let displayStr = fullText.slice(0, visibleCount);
|
|
3858
|
-
if (scramble.enabled && visibleCount < totalChars && visibleCount > 0) {
|
|
3859
|
-
const pool = getScramblePool(scramble.charset, scramble.customCharset);
|
|
3860
|
-
const trailCount = Math.min(visibleCount, Math.max(1, scramble.scrambleFramesPerChar > 4 ? 3 : 2));
|
|
3861
|
-
let scrambledTail = "";
|
|
3862
|
-
for (let t = 0; t < trailCount; t++) {
|
|
3863
|
-
const idx = Math.floor(Math.abs(Math.sin(currentFrame * 7 + t * 13)) * pool.length) % pool.length;
|
|
3864
|
-
scrambledTail += pool[idx];
|
|
3865
|
-
}
|
|
3866
|
-
displayStr = displayStr.slice(0, displayStr.length - trailCount) + scrambledTail;
|
|
3867
|
-
}
|
|
3868
|
-
let isCursorVisible = true;
|
|
3869
|
-
if (blinkFrequency > 0) {
|
|
3870
|
-
const halfPeriodFrames = Math.max(1, Math.round(30 / (2 * blinkFrequency)));
|
|
3871
|
-
isCursorVisible = Math.floor(elapsed / halfPeriodFrames) % 2 === 0;
|
|
3872
|
-
}
|
|
3873
|
-
return {
|
|
3874
|
-
visibleChars: visibleCount,
|
|
3875
|
-
currentDisplayString: displayStr,
|
|
3876
|
-
isCursorVisible
|
|
3877
|
-
};
|
|
1813
|
+
/** Returns the tree with every `matte` turned into a sibling matte layer. */
|
|
1814
|
+
function hoistMattes(nodes) {
|
|
1815
|
+
return nodes.flatMap((n) => hoistOne(n));
|
|
3878
1816
|
}
|
|
3879
1817
|
/** number px | "auto" (intrinsic) | "fit" (shrink-wrap) | "fill" (parent extent). */
|
|
3880
1818
|
const SizeSpecSchema = z.union([
|
|
@@ -3984,7 +1922,16 @@ const AnimatablePropSchema = z.enum([
|
|
|
3984
1922
|
"animationSpeed",
|
|
3985
1923
|
"wireframe",
|
|
3986
1924
|
"scaleX",
|
|
3987
|
-
"scaleY"
|
|
1925
|
+
"scaleY",
|
|
1926
|
+
"emissive",
|
|
1927
|
+
"emissiveIntensity",
|
|
1928
|
+
"exposure"
|
|
1929
|
+
]);
|
|
1930
|
+
const MatteModeSchema = z.enum([
|
|
1931
|
+
"alpha",
|
|
1932
|
+
"alpha-inverted",
|
|
1933
|
+
"luma",
|
|
1934
|
+
"luma-inverted"
|
|
3988
1935
|
]);
|
|
3989
1936
|
const MaterialTypeSchema = z.enum([
|
|
3990
1937
|
"lit",
|
|
@@ -4283,6 +2230,16 @@ const BaseNodeFields = {
|
|
|
4283
2230
|
dispersion: z.number().min(0).max(1).optional(),
|
|
4284
2231
|
fresnelPower: z.number().min(1).max(10).optional(),
|
|
4285
2232
|
envIntensity: z.number().min(0).max(10).optional(),
|
|
2233
|
+
emissive: ColorSchema.optional(),
|
|
2234
|
+
emissiveIntensity: z.number().min(0).optional(),
|
|
2235
|
+
castShadow: z.boolean().optional(),
|
|
2236
|
+
matte: z.object({
|
|
2237
|
+
node: z.custom((v) => typeof v === "object" && v !== null),
|
|
2238
|
+
mode: MatteModeSchema.optional()
|
|
2239
|
+
}).optional(),
|
|
2240
|
+
matteId: z.string().optional(),
|
|
2241
|
+
matteOf: z.string().optional(),
|
|
2242
|
+
matteMode: MatteModeSchema.optional(),
|
|
4286
2243
|
animation: LayerAnimationSchema.default({ tracks: [] }),
|
|
4287
2244
|
vision: z.unknown().optional(),
|
|
4288
2245
|
relighting: z.unknown().optional()
|
|
@@ -4445,8 +2402,34 @@ const LightTypeSchema = z.enum([
|
|
|
4445
2402
|
"ambient",
|
|
4446
2403
|
"directional",
|
|
4447
2404
|
"point",
|
|
4448
|
-
"spot"
|
|
2405
|
+
"spot",
|
|
2406
|
+
"environment"
|
|
4449
2407
|
]);
|
|
2408
|
+
const EnvironmentPresetSchema = z.enum([
|
|
2409
|
+
"studio",
|
|
2410
|
+
"soft",
|
|
2411
|
+
"sunset",
|
|
2412
|
+
"night",
|
|
2413
|
+
"neutral"
|
|
2414
|
+
]);
|
|
2415
|
+
const ToneMappingSchema = z.enum([
|
|
2416
|
+
"neutral",
|
|
2417
|
+
"agx",
|
|
2418
|
+
"aces",
|
|
2419
|
+
"none"
|
|
2420
|
+
]);
|
|
2421
|
+
const EnvironmentFogSchema = z.object({
|
|
2422
|
+
color: ColorSchema,
|
|
2423
|
+
start: z.number().min(0),
|
|
2424
|
+
end: z.number().min(0),
|
|
2425
|
+
opacity: z.number().min(0).max(1).optional()
|
|
2426
|
+
}).strict();
|
|
2427
|
+
const BloomConfigSchema = z.object({
|
|
2428
|
+
intensity: z.number().min(0).max(10).optional(),
|
|
2429
|
+
threshold: z.number().min(0).max(16).optional(),
|
|
2430
|
+
knee: z.number().min(0).max(1).optional(),
|
|
2431
|
+
radius: z.number().min(1).max(8).optional()
|
|
2432
|
+
}).strict();
|
|
4450
2433
|
const LightNodeSchema = z.object({
|
|
4451
2434
|
id: z.string().min(1),
|
|
4452
2435
|
kind: z.literal("light"),
|
|
@@ -4468,6 +2451,20 @@ const LightNodeSchema = z.object({
|
|
|
4468
2451
|
decay: z.number().min(0).default(2),
|
|
4469
2452
|
angle: z.number().min(0).max(180).default(45),
|
|
4470
2453
|
penumbra: z.number().min(0).max(1).default(.2),
|
|
2454
|
+
castShadow: z.boolean().optional(),
|
|
2455
|
+
shadowSoftness: z.number().min(0).max(64).optional(),
|
|
2456
|
+
shadowDarkness: z.number().min(0).max(1).optional(),
|
|
2457
|
+
shadowMapSize: z.number().int().min(256).max(8192).optional(),
|
|
2458
|
+
preset: EnvironmentPresetSchema.optional(),
|
|
2459
|
+
top: ColorSchema.optional(),
|
|
2460
|
+
horizon: ColorSchema.optional(),
|
|
2461
|
+
bottom: ColorSchema.optional(),
|
|
2462
|
+
softboxes: z.number().min(0).optional(),
|
|
2463
|
+
rotation: z.number().optional(),
|
|
2464
|
+
exposure: z.number().min(-16).max(16).optional(),
|
|
2465
|
+
toneMapping: ToneMappingSchema.optional(),
|
|
2466
|
+
fog: EnvironmentFogSchema.optional(),
|
|
2467
|
+
bloom: z.union([z.boolean(), BloomConfigSchema]).optional(),
|
|
4471
2468
|
startFrame: z.number().int().min(0).default(0),
|
|
4472
2469
|
durationFrames: z.number().int().min(1).optional(),
|
|
4473
2470
|
animation: LayerAnimationSchema.default({ tracks: [] })
|
|
@@ -4596,6 +2593,11 @@ const TextFields = {
|
|
|
4596
2593
|
"center",
|
|
4597
2594
|
"end"
|
|
4598
2595
|
]).optional(),
|
|
2596
|
+
direction: z.enum([
|
|
2597
|
+
"ltr",
|
|
2598
|
+
"rtl",
|
|
2599
|
+
"auto"
|
|
2600
|
+
]).optional(),
|
|
4599
2601
|
verticalAlign: z.enum([
|
|
4600
2602
|
"top",
|
|
4601
2603
|
"middle",
|
|
@@ -4640,6 +2642,7 @@ const MediaNodeSchema = z.object({
|
|
|
4640
2642
|
"fill",
|
|
4641
2643
|
"none"
|
|
4642
2644
|
]).default("contain"),
|
|
2645
|
+
dpr: z.number().min(1).max(4).optional(),
|
|
4643
2646
|
borderRadius: z.number().min(0).optional(),
|
|
4644
2647
|
borderColor: ColorSchema.optional(),
|
|
4645
2648
|
borderWidth: z.number().min(0).optional(),
|
|
@@ -4662,6 +2665,11 @@ const MediaNodeSchema = z.object({
|
|
|
4662
2665
|
"center",
|
|
4663
2666
|
"end"
|
|
4664
2667
|
]).optional(),
|
|
2668
|
+
direction: z.enum([
|
|
2669
|
+
"ltr",
|
|
2670
|
+
"rtl",
|
|
2671
|
+
"auto"
|
|
2672
|
+
]).optional(),
|
|
4665
2673
|
verticalAlign: z.enum([
|
|
4666
2674
|
"top",
|
|
4667
2675
|
"middle",
|
|
@@ -4761,7 +2769,10 @@ const Model3DNodeSchema = z.object({
|
|
|
4761
2769
|
scaleX: z.number().default(1),
|
|
4762
2770
|
scaleY: z.number().default(1),
|
|
4763
2771
|
audioDeform: z.record(z.string(), z.unknown()).optional(),
|
|
4764
|
-
|
|
2772
|
+
color: ColorSchema.optional(),
|
|
2773
|
+
colorTint: ColorSchema.optional(),
|
|
2774
|
+
text3dOptions: z.unknown().optional(),
|
|
2775
|
+
primitive3d: z.unknown().optional()
|
|
4765
2776
|
}).strict();
|
|
4766
2777
|
const LayoutNodeSchema = z.lazy(() => z.union([
|
|
4767
2778
|
FlexNodeSchema,
|
|
@@ -4798,6 +2809,10 @@ const CompositorProgramSchema = z.object({
|
|
|
4798
2809
|
*/
|
|
4799
2810
|
/**
|
|
4800
2811
|
* Camera Transition Type across scene boundaries.
|
|
2812
|
+
*
|
|
2813
|
+
* @deprecated Recorded on scenes but not rendered. Use framefields'
|
|
2814
|
+
* `Layer.sequence([...])` with `Transition.push` / `wipe` / `iris` /
|
|
2815
|
+
* `crossfade` / `zoom` / `whip`, which render as keyframes and mattes.
|
|
4801
2816
|
*/
|
|
4802
2817
|
const SceneTransitionTypeSchema = z.enum([
|
|
4803
2818
|
"cut",
|
|
@@ -5014,11 +3029,12 @@ function applyStaggerToChildren(children, staggerFrames, direction = "forward",
|
|
|
5014
3029
|
function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDurationMs, inheritedDurationFrames) {
|
|
5015
3030
|
let children = [];
|
|
5016
3031
|
const sourceRef = node.src ?? node.inputHandleId;
|
|
5017
|
-
const isDirectMediaSource = (s) => typeof s === "string" && (s.startsWith("http://") || s.startsWith("https://") || s.startsWith("file://") || s.startsWith("/") || s.startsWith("./") || s.startsWith("blob:") || s.startsWith("data:") || /\.(png|jpe?g|webp|gif|svg|mp4|webm|mov|mkv|mp3|wav|ogg|m4a|srt|vtt)$/i.test(s));
|
|
3032
|
+
const isDirectMediaSource = (s) => typeof s === "string" && (s.startsWith("http://") || s.startsWith("https://") || s.startsWith("file://") || s.startsWith("/") || s.startsWith("./") || s.startsWith("blob:") || s.startsWith("data:") || /\.(png|jpe?g|webp|gif|svg|mp4|webm|mov|mkv|mp3|wav|ogg|m4a|srt|vtt|json|lottie)$/i.test(s));
|
|
5018
3033
|
let media;
|
|
5019
3034
|
if (node.kind === "media") {
|
|
5020
3035
|
if (resolveMedia) media = resolveMedia(node.inputHandleId);
|
|
5021
3036
|
if (!media && sourceRef && (isDirectMediaSource(sourceRef) || node.src)) media = createVirtualMedia(sourceRef, node.dataType ?? "Video");
|
|
3037
|
+
if (!media && !resolveMedia && sourceRef && (sourceRef.includes(".") || sourceRef.includes("/"))) console.warn(`[Compositor] Media layer '${node.id ?? "?"}' source '${sourceRef}' could not be resolved.`);
|
|
5022
3038
|
if (media && node.crop) {
|
|
5023
3039
|
const cropRaw = node.crop;
|
|
5024
3040
|
const cropOp = typeof cropRaw.toOperation === "function" ? cropRaw.toOperation() : cropRaw;
|
|
@@ -5143,7 +3159,7 @@ function compositorToProgram(config, options) {
|
|
|
5143
3159
|
},
|
|
5144
3160
|
...(config.onRequestFrame || options.onRequestFrame) && { onRequestFrame: config.onRequestFrame ?? options.onRequestFrame }
|
|
5145
3161
|
},
|
|
5146
|
-
children: config.layout.map((n) => nodeToVirtualMedia(n, resolveMedia, fps, 0, durationMs))
|
|
3162
|
+
children: hoistMattes(config.layout).map((n) => nodeToVirtualMedia(n, resolveMedia, fps, 0, durationMs))
|
|
5147
3163
|
};
|
|
5148
3164
|
const effectsList = Array.isArray(options.effects) ? options.effects : Array.isArray(config.effects) ? config.effects : [];
|
|
5149
3165
|
for (const eff of effectsList) {
|
|
@@ -5184,5 +3200,5 @@ function collectNodeOps(nodes) {
|
|
|
5184
3200
|
}
|
|
5185
3201
|
|
|
5186
3202
|
//#endregion
|
|
5187
|
-
export {
|
|
5188
|
-
//# sourceMappingURL=program-
|
|
3203
|
+
export { applyStaggerToChildren as A, hoistMattes as B, ShapeNodeSchema as C, TextSpanMarkSchema as D, TextNodeSchema as E, computeLayout as F, lintComposition as H, computeLayoutSync as I, computeStaggerDelay as L, collectNodeOps as M, compositorToProgram as N, TextSpanSchema as O, computeCarrierContinuity as P, evaluateAnimationAtFrame as R, Sequence as S, TextAnimatorSchema as T, mergeAnimationTracks as U, initLayout as V, MediaNodeSchema as _, CarrierHandoffConfigSchema as a, SceneDefinitionSchema as b, EnvironmentFogSchema as c, LayerAnimation as d, LayoutNodeSchema as f, MatteModeSchema as g, MaterialTypeSchema as h, CameraNodeSchema as i, calculateSequenceTimeline as j, ToneMappingSchema as k, EnvironmentPresetSchema as l, LightTypeSchema as m, BoxNodeSchema as n, ColorStopSchema as o, LightNodeSchema as p, CameraAnimation as r, CompositorProgramSchema as s, BloomConfigSchema as t, FlexNodeSchema as u, Model3DNodeSchema as v, TextAnimator as w, SceneTransitionTypeSchema as x, Scene as y, evaluateTrackAtFrame as z };
|
|
3204
|
+
//# sourceMappingURL=program-BqFVw5Mu.mjs.map
|