agentvfx 0.0.0-stage → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (483) hide show
  1. package/AGENTS.md +8 -0
  2. package/GEMINI.md +1 -0
  3. package/LICENSE +172 -0
  4. package/README.md +236 -2
  5. package/package.json +35 -4
  6. package/skills/agentvfx/LICENSE +172 -0
  7. package/skills/agentvfx/NOTICE +44 -0
  8. package/skills/agentvfx/SKILL.md +90 -0
  9. package/skills/agentvfx/engine/core/constants.mjs +84 -0
  10. package/skills/agentvfx/engine/core/flash-constants.mjs +23 -0
  11. package/skills/agentvfx/engine/core/flash.mjs +240 -0
  12. package/skills/agentvfx/engine/core/mark.mjs +28 -0
  13. package/skills/agentvfx/engine/core/palettes.mjs +36 -0
  14. package/skills/agentvfx/engine/core/schedule.mjs +85 -0
  15. package/skills/agentvfx/engine/core/templates.mjs +43 -0
  16. package/skills/agentvfx/engine/core/util.mjs +167 -0
  17. package/skills/agentvfx/engine/core/validate.mjs +334 -0
  18. package/skills/agentvfx/engine/node/analysis.mjs +172 -0
  19. package/skills/agentvfx/engine/node/audio.mjs +621 -0
  20. package/skills/agentvfx/engine/node/board.mjs +24 -0
  21. package/skills/agentvfx/engine/node/chrome.mjs +349 -0
  22. package/skills/agentvfx/engine/node/encode.mjs +110 -0
  23. package/skills/agentvfx/engine/node/eye.mjs +77 -0
  24. package/skills/agentvfx/engine/node/footage.mjs +129 -0
  25. package/skills/agentvfx/engine/node/frame-worker.mjs +39 -0
  26. package/skills/agentvfx/engine/node/host.mjs +31 -0
  27. package/skills/agentvfx/engine/node/job.mjs +181 -0
  28. package/skills/agentvfx/engine/node/png.mjs +112 -0
  29. package/skills/agentvfx/engine/node/render.mjs +161 -0
  30. package/skills/agentvfx/engine/node/stage-capture.mjs +187 -0
  31. package/skills/agentvfx/engine/node/stage-serve.mjs +72 -0
  32. package/skills/agentvfx/engine/node/stills.mjs +100 -0
  33. package/skills/agentvfx/engine/node/ws-server.mjs +132 -0
  34. package/skills/agentvfx/engine/web/gl.mjs +319 -0
  35. package/skills/agentvfx/engine/web/glsl-common.mjs +78 -0
  36. package/skills/agentvfx/engine/web/init.js +23 -0
  37. package/skills/agentvfx/engine/web/prelude.mjs +150 -0
  38. package/skills/agentvfx/engine/web/render.html +11 -0
  39. package/skills/agentvfx/engine/web/render.mjs +388 -0
  40. package/skills/agentvfx/engine/web/scale.mjs +15 -0
  41. package/skills/agentvfx/engine/web/text.mjs +158 -0
  42. package/skills/agentvfx/plates/terminalcore/README.md +61 -0
  43. package/skills/agentvfx/plates/terminalcore/__pycache__/crt.cpython-313.pyc +0 -0
  44. package/skills/agentvfx/plates/terminalcore/__pycache__/font.cpython-313.pyc +0 -0
  45. package/skills/agentvfx/plates/terminalcore/__pycache__/gallery.cpython-313.pyc +0 -0
  46. package/skills/agentvfx/plates/terminalcore/__pycache__/gallery_mats.cpython-313.pyc +0 -0
  47. package/skills/agentvfx/plates/terminalcore/__pycache__/gallery_room.cpython-313.pyc +0 -0
  48. package/skills/agentvfx/plates/terminalcore/__pycache__/materials.cpython-313.pyc +0 -0
  49. package/skills/agentvfx/plates/terminalcore/__pycache__/nodekit.cpython-313.pyc +0 -0
  50. package/skills/agentvfx/plates/terminalcore/__pycache__/room.cpython-313.pyc +0 -0
  51. package/skills/agentvfx/plates/terminalcore/__pycache__/shots.cpython-313.pyc +0 -0
  52. package/skills/agentvfx/plates/terminalcore/__pycache__/textures.cpython-313.pyc +0 -0
  53. package/skills/agentvfx/plates/terminalcore/__pycache__/wall.cpython-313.pyc +0 -0
  54. package/skills/agentvfx/plates/terminalcore/crt.py +143 -0
  55. package/skills/agentvfx/plates/terminalcore/font.py +80 -0
  56. package/skills/agentvfx/plates/terminalcore/gallery.py +61 -0
  57. package/skills/agentvfx/plates/terminalcore/gallery_mats.py +144 -0
  58. package/skills/agentvfx/plates/terminalcore/gallery_room.py +126 -0
  59. package/skills/agentvfx/plates/terminalcore/materials.py +170 -0
  60. package/skills/agentvfx/plates/terminalcore/nodekit.py +87 -0
  61. package/skills/agentvfx/plates/terminalcore/room.py +82 -0
  62. package/skills/agentvfx/plates/terminalcore/scene.py +219 -0
  63. package/skills/agentvfx/plates/terminalcore/shots.py +48 -0
  64. package/skills/agentvfx/plates/terminalcore/textures.py +79 -0
  65. package/skills/agentvfx/plates/terminalcore/wall.py +103 -0
  66. package/skills/agentvfx/references/plates.md +22 -0
  67. package/skills/agentvfx/references/template-format.md +149 -0
  68. package/skills/agentvfx/references/web.md +63 -0
  69. package/skills/agentvfx/runtime/agentvfx.js +708 -0
  70. package/skills/agentvfx/schemas/fx-score.schema.json +98 -0
  71. package/skills/agentvfx/scripts/export-web.mjs +155 -0
  72. package/skills/agentvfx/scripts/loop.mjs +129 -0
  73. package/skills/agentvfx/scripts/make-beat.mjs +133 -0
  74. package/skills/agentvfx/scripts/plate.mjs +82 -0
  75. package/skills/agentvfx/scripts/vfx.mjs +173 -0
  76. package/skills/agentvfx/templates/_test/feedback-counter/fx.json +11 -0
  77. package/skills/agentvfx/templates/_test/feedback-counter/main.frag +4 -0
  78. package/skills/agentvfx/templates/_test/feedback-counter/pass0.frag +4 -0
  79. package/skills/agentvfx/templates/_test/gradient/fx.json +23 -0
  80. package/skills/agentvfx/templates/_test/gradient/main.frag +5 -0
  81. package/skills/agentvfx/templates/_test/identity/fx.json +10 -0
  82. package/skills/agentvfx/templates/_test/identity/main.frag +4 -0
  83. package/skills/agentvfx/templates/_test/strobe/fx.json +14 -0
  84. package/skills/agentvfx/templates/_test/strobe/main.frag +6 -0
  85. package/skills/agentvfx/templates/_test/text-probe/fx.json +15 -0
  86. package/skills/agentvfx/templates/_test/text-probe/main.frag +6 -0
  87. package/skills/agentvfx/templates/brutal/NOTES.md +14 -0
  88. package/skills/agentvfx/templates/brutal/_src/boot-log/def.mjs +57 -0
  89. package/skills/agentvfx/templates/brutal/_src/boot-log/main.src.frag +129 -0
  90. package/skills/agentvfx/templates/brutal/_src/build.mjs +33 -0
  91. package/skills/agentvfx/templates/brutal/_src/halftone-field/def.mjs +72 -0
  92. package/skills/agentvfx/templates/brutal/_src/halftone-field/main.src.frag +94 -0
  93. package/skills/agentvfx/templates/brutal/_src/hud-deck/deck-left.src.glsl +100 -0
  94. package/skills/agentvfx/templates/brutal/_src/hud-deck/deck-right.src.glsl +61 -0
  95. package/skills/agentvfx/templates/brutal/_src/hud-deck/deck-tiles.src.glsl +153 -0
  96. package/skills/agentvfx/templates/brutal/_src/hud-deck/def.mjs +82 -0
  97. package/skills/agentvfx/templates/brutal/_src/hud-deck/main.src.frag +110 -0
  98. package/skills/agentvfx/templates/brutal/_src/hud-deck/pass0.src.frag +38 -0
  99. package/skills/agentvfx/templates/brutal/_src/shared/defs.mjs +28 -0
  100. package/skills/agentvfx/templates/brutal/_src/shared/icons.glsl +72 -0
  101. package/skills/agentvfx/templates/brutal/_src/shared/lib.glsl +115 -0
  102. package/skills/agentvfx/templates/brutal/_src/shared/screen.glsl +43 -0
  103. package/skills/agentvfx/templates/brutal/boot-log/demo-acid.json +1 -0
  104. package/skills/agentvfx/templates/brutal/boot-log/demo-phosphor.json +1 -0
  105. package/skills/agentvfx/templates/brutal/boot-log/demo-ultramarine.json +1 -0
  106. package/skills/agentvfx/templates/brutal/boot-log/fx.json +257 -0
  107. package/skills/agentvfx/templates/brutal/boot-log/main.frag +242 -0
  108. package/skills/agentvfx/templates/brutal/collage/_src/00-lib.glsl +73 -0
  109. package/skills/agentvfx/templates/brutal/collage/_src/10-spectrum-scope.glsl +73 -0
  110. package/skills/agentvfx/templates/brutal/collage/_src/20-meter-readout-cross.glsl +87 -0
  111. package/skills/agentvfx/templates/brutal/collage/_src/30-footage-fillers.glsl +92 -0
  112. package/skills/agentvfx/templates/brutal/collage/_src/40-editorial.glsl +232 -0
  113. package/skills/agentvfx/templates/brutal/collage/_src/50-typefx.glsl +163 -0
  114. package/skills/agentvfx/templates/brutal/collage/_src/60-scene-lib.glsl +104 -0
  115. package/skills/agentvfx/templates/brutal/collage/_src/61-scene-specimen.glsl +71 -0
  116. package/skills/agentvfx/templates/brutal/collage/_src/62-scene-wiring.glsl +96 -0
  117. package/skills/agentvfx/templates/brutal/collage/_src/63-scene-fieldcut.glsl +119 -0
  118. package/skills/agentvfx/templates/brutal/collage/_src/64-scene-pattern.glsl +64 -0
  119. package/skills/agentvfx/templates/brutal/collage/_src/641-scene-anatomy.glsl +49 -0
  120. package/skills/agentvfx/templates/brutal/collage/_src/642-scene-deck.glsl +78 -0
  121. package/skills/agentvfx/templates/brutal/collage/_src/643-scene-bootlog.glsl +60 -0
  122. package/skills/agentvfx/templates/brutal/collage/_src/644-scene-tunnel.glsl +48 -0
  123. package/skills/agentvfx/templates/brutal/collage/_src/645-scene-runner.glsl +42 -0
  124. package/skills/agentvfx/templates/brutal/collage/_src/646-scene-ascii.glsl +66 -0
  125. package/skills/agentvfx/templates/brutal/collage/_src/647-scene-cubewall.glsl +80 -0
  126. package/skills/agentvfx/templates/brutal/collage/_src/648-scene-vortex.glsl +46 -0
  127. package/skills/agentvfx/templates/brutal/collage/_src/649-scene-sticker.glsl +72 -0
  128. package/skills/agentvfx/templates/brutal/collage/_src/65-scene-main.glsl +1 -0
  129. package/skills/agentvfx/templates/brutal/collage/_src/650-scene-ribbon.glsl +55 -0
  130. package/skills/agentvfx/templates/brutal/collage/_src/651-scene-slab.glsl +38 -0
  131. package/skills/agentvfx/templates/brutal/collage/_src/652-scene-framedial.glsl +79 -0
  132. package/skills/agentvfx/templates/brutal/collage/_src/653-scene-tilt.glsl +40 -0
  133. package/skills/agentvfx/templates/brutal/collage/_src/654-scene-marquee.glsl +45 -0
  134. package/skills/agentvfx/templates/brutal/collage/_src/655-scene-lens.glsl +57 -0
  135. package/skills/agentvfx/templates/brutal/collage/_src/656-scene-liquid.glsl +35 -0
  136. package/skills/agentvfx/templates/brutal/collage/_src/657-scene-panelgrid.glsl +75 -0
  137. package/skills/agentvfx/templates/brutal/collage/_src/658-scene-mirror.glsl +49 -0
  138. package/skills/agentvfx/templates/brutal/collage/_src/66-scene-main.glsl +27 -0
  139. package/skills/agentvfx/templates/brutal/collage/_src/90-main.glsl +120 -0
  140. package/skills/agentvfx/templates/brutal/collage/_src/build.mjs +24 -0
  141. package/skills/agentvfx/templates/brutal/collage/_src/sync-presets.mjs +16 -0
  142. package/skills/agentvfx/templates/brutal/collage/demo-bone-lime.json +1 -0
  143. package/skills/agentvfx/templates/brutal/collage/demo-lime-sparse.json +1 -0
  144. package/skills/agentvfx/templates/brutal/collage/demo-orange-dense.json +1 -0
  145. package/skills/agentvfx/templates/brutal/collage/demo-ultra-slow.json +1 -0
  146. package/skills/agentvfx/templates/brutal/collage/fx.json +4882 -0
  147. package/skills/agentvfx/templates/brutal/collage/layout.mjs +97 -0
  148. package/skills/agentvfx/templates/brutal/collage/layouts.json +366 -0
  149. package/skills/agentvfx/templates/brutal/collage/main.frag +2367 -0
  150. package/skills/agentvfx/templates/brutal/collage/pass0.frag +265 -0
  151. package/skills/agentvfx/templates/brutal/halftone-field/demo-acid.json +1 -0
  152. package/skills/agentvfx/templates/brutal/halftone-field/demo-ascii.json +1 -0
  153. package/skills/agentvfx/templates/brutal/halftone-field/demo-dither.json +1 -0
  154. package/skills/agentvfx/templates/brutal/halftone-field/demo-orange.json +1 -0
  155. package/skills/agentvfx/templates/brutal/halftone-field/demo-phosphor.json +1 -0
  156. package/skills/agentvfx/templates/brutal/halftone-field/demo-ultramarine.json +1 -0
  157. package/skills/agentvfx/templates/brutal/halftone-field/fx.json +474 -0
  158. package/skills/agentvfx/templates/brutal/halftone-field/main.frag +248 -0
  159. package/skills/agentvfx/templates/brutal/hud-deck/demo-acid.json +1 -0
  160. package/skills/agentvfx/templates/brutal/hud-deck/demo-night.json +1 -0
  161. package/skills/agentvfx/templates/brutal/hud-deck/demo-octagon.json +1 -0
  162. package/skills/agentvfx/templates/brutal/hud-deck/demo-ultramarine.json +1 -0
  163. package/skills/agentvfx/templates/brutal/hud-deck/fx.json +601 -0
  164. package/skills/agentvfx/templates/brutal/hud-deck/main.frag +645 -0
  165. package/skills/agentvfx/templates/brutal/hud-deck/pass0.frag +38 -0
  166. package/skills/agentvfx/templates/brutal/lattice/demo-cobalt-fine.json +1 -0
  167. package/skills/agentvfx/templates/brutal/lattice/demo-ink-yellow.json +1 -0
  168. package/skills/agentvfx/templates/brutal/lattice/demo-vermilion.json +1 -0
  169. package/skills/agentvfx/templates/brutal/lattice/demo-violet-slow.json +1 -0
  170. package/skills/agentvfx/templates/brutal/lattice/fx.json +130 -0
  171. package/skills/agentvfx/templates/brutal/lattice/main.frag +175 -0
  172. package/skills/agentvfx/templates/brutal/lattice/pass0.frag +29 -0
  173. package/skills/agentvfx/templates/glitch/block-glitch/demo-mosaic.json +1 -0
  174. package/skills/agentvfx/templates/glitch/block-glitch/demo-onset.json +1 -0
  175. package/skills/agentvfx/templates/glitch/block-glitch/demo-static.json +1 -0
  176. package/skills/agentvfx/templates/glitch/block-glitch/demo-tear.json +1 -0
  177. package/skills/agentvfx/templates/glitch/block-glitch/fx.json +54 -0
  178. package/skills/agentvfx/templates/glitch/block-glitch/main.frag +132 -0
  179. package/skills/agentvfx/templates/glitch/block-glitch/pass0.frag +12 -0
  180. package/skills/agentvfx/templates/glitch/pixel-sort/NOTES.md +13 -0
  181. package/skills/agentvfx/templates/glitch/pixel-sort/build-passes.mjs +162 -0
  182. package/skills/agentvfx/templates/glitch/pixel-sort/demo-chunk.json +1 -0
  183. package/skills/agentvfx/templates/glitch/pixel-sort/demo-hue.json +1 -0
  184. package/skills/agentvfx/templates/glitch/pixel-sort/demo-kick.json +1 -0
  185. package/skills/agentvfx/templates/glitch/pixel-sort/demo-streak.json +1 -0
  186. package/skills/agentvfx/templates/glitch/pixel-sort/demo-vertical.json +1 -0
  187. package/skills/agentvfx/templates/glitch/pixel-sort/fx.json +60 -0
  188. package/skills/agentvfx/templates/glitch/pixel-sort/main.frag +83 -0
  189. package/skills/agentvfx/templates/glitch/pixel-sort/pass0.frag +64 -0
  190. package/skills/agentvfx/templates/glitch/pixel-sort/pass1.frag +66 -0
  191. package/skills/agentvfx/templates/glitch/pixel-sort/pass2.frag +66 -0
  192. package/skills/agentvfx/templates/glitch/pixel-sort/pass3.frag +66 -0
  193. package/skills/agentvfx/templates/glitch/pixel-sort/pass4.frag +66 -0
  194. package/skills/agentvfx/templates/glitch/pixel-sort/pass5.frag +66 -0
  195. package/skills/agentvfx/templates/glitch/pixel-sort/pass6.frag +66 -0
  196. package/skills/agentvfx/templates/glitch/pixel-sort/pass7.frag +66 -0
  197. package/skills/agentvfx/templates/glitch/pixel-sort/pass8.frag +66 -0
  198. package/skills/agentvfx/templates/glitch/rgb-split/demo-diagonal-stutter.json +1 -0
  199. package/skills/agentvfx/templates/glitch/rgb-split/demo-hard.json +1 -0
  200. package/skills/agentvfx/templates/glitch/rgb-split/demo-kick.json +1 -0
  201. package/skills/agentvfx/templates/glitch/rgb-split/demo-radial.json +1 -0
  202. package/skills/agentvfx/templates/glitch/rgb-split/fx.json +46 -0
  203. package/skills/agentvfx/templates/glitch/rgb-split/main.frag +76 -0
  204. package/skills/agentvfx/templates/glitch/vhs/demo-clean.json +1 -0
  205. package/skills/agentvfx/templates/glitch/vhs/demo-crash.json +1 -0
  206. package/skills/agentvfx/templates/glitch/vhs/demo-tape.json +1 -0
  207. package/skills/agentvfx/templates/glitch/vhs/demo-worn.json +1 -0
  208. package/skills/agentvfx/templates/glitch/vhs/fx.json +46 -0
  209. package/skills/agentvfx/templates/glitch/vhs/main.frag +96 -0
  210. package/skills/agentvfx/templates/impact/impact-1bit/demo-onebit-bayer.json +1 -0
  211. package/skills/agentvfx/templates/impact/impact-1bit/fx.json +45 -0
  212. package/skills/agentvfx/templates/impact/impact-1bit/main.frag +64 -0
  213. package/skills/agentvfx/templates/impact/impact-invert/demo-invert-snap.json +1 -0
  214. package/skills/agentvfx/templates/impact/impact-invert/fx.json +37 -0
  215. package/skills/agentvfx/templates/impact/impact-invert/main.frag +44 -0
  216. package/skills/agentvfx/templates/impact/punch-shake/demo-punch-hard.json +1 -0
  217. package/skills/agentvfx/templates/impact/punch-shake/fx.json +36 -0
  218. package/skills/agentvfx/templates/impact/punch-shake/main.frag +62 -0
  219. package/skills/agentvfx/templates/impact/rgb-hit/demo-rgb-slam.json +1 -0
  220. package/skills/agentvfx/templates/impact/rgb-hit/fx.json +39 -0
  221. package/skills/agentvfx/templates/impact/rgb-hit/main.frag +62 -0
  222. package/skills/agentvfx/templates/impact/signal-cut/demo-lime-hold.json +1 -0
  223. package/skills/agentvfx/templates/impact/signal-cut/demo-lime.json +1 -0
  224. package/skills/agentvfx/templates/impact/signal-cut/demo-orange.json +1 -0
  225. package/skills/agentvfx/templates/impact/signal-cut/demo-ultramarine.json +1 -0
  226. package/skills/agentvfx/templates/impact/signal-cut/fx.json +83 -0
  227. package/skills/agentvfx/templates/impact/signal-cut/main.frag +101 -0
  228. package/skills/agentvfx/templates/impact/signal-cut/pass0.frag +68 -0
  229. package/skills/agentvfx/templates/impact/speedline-burst/demo-speed-white.json +1 -0
  230. package/skills/agentvfx/templates/impact/speedline-burst/fx.json +44 -0
  231. package/skills/agentvfx/templates/impact/speedline-burst/main.frag +68 -0
  232. package/skills/agentvfx/templates/impact/strobe-burst/demo-strobe-white-16.json +1 -0
  233. package/skills/agentvfx/templates/impact/strobe-burst/fx.json +42 -0
  234. package/skills/agentvfx/templates/impact/strobe-burst/main.frag +43 -0
  235. package/skills/agentvfx/templates/light/anamorphic-streak/demo-anamorphic-cinema.json +10 -0
  236. package/skills/agentvfx/templates/light/anamorphic-streak/demo-data.json +10 -0
  237. package/skills/agentvfx/templates/light/anamorphic-streak/fx.json +47 -0
  238. package/skills/agentvfx/templates/light/anamorphic-streak/main.frag +45 -0
  239. package/skills/agentvfx/templates/light/anamorphic-streak/pass0.frag +22 -0
  240. package/skills/agentvfx/templates/light/anamorphic-streak/pass1.frag +16 -0
  241. package/skills/agentvfx/templates/light/anamorphic-streak/pass2.frag +16 -0
  242. package/skills/agentvfx/templates/light/anamorphic-streak/pass3.frag +16 -0
  243. package/skills/agentvfx/templates/light/bloom-glow/demo-clip01-low.json +11 -0
  244. package/skills/agentvfx/templates/light/bloom-glow/demo-neon-night.json +10 -0
  245. package/skills/agentvfx/templates/light/bloom-glow/demo-phosphor.json +11 -0
  246. package/skills/agentvfx/templates/light/bloom-glow/fx.json +53 -0
  247. package/skills/agentvfx/templates/light/bloom-glow/main.frag +85 -0
  248. package/skills/agentvfx/templates/light/bloom-glow/pass0.frag +21 -0
  249. package/skills/agentvfx/templates/light/bloom-glow/pass1.frag +50 -0
  250. package/skills/agentvfx/templates/light/bloom-glow/pass2.frag +44 -0
  251. package/skills/agentvfx/templates/light/bloom-glow/pass3.frag +32 -0
  252. package/skills/agentvfx/templates/light/bloom-glow/pass4.frag +48 -0
  253. package/skills/agentvfx/templates/light/bloom-glow/pass5.frag +46 -0
  254. package/skills/agentvfx/templates/light/god-rays/demo-golden-hour.json +10 -0
  255. package/skills/agentvfx/templates/light/god-rays/demo-point-lamp.json +10 -0
  256. package/skills/agentvfx/templates/light/god-rays/fx.json +39 -0
  257. package/skills/agentvfx/templates/light/god-rays/main.frag +54 -0
  258. package/skills/agentvfx/templates/light/lens-flare/demo-clip01-bar.json +11 -0
  259. package/skills/agentvfx/templates/light/lens-flare/demo-eye-bar.json +10 -0
  260. package/skills/agentvfx/templates/light/lens-flare/demo-sun-ghosts.json +10 -0
  261. package/skills/agentvfx/templates/light/lens-flare/fx.json +49 -0
  262. package/skills/agentvfx/templates/light/lens-flare/main.frag +86 -0
  263. package/skills/agentvfx/templates/light/lens-flare/pass0.frag +24 -0
  264. package/skills/agentvfx/templates/light/light-leak/demo-slit.json +10 -0
  265. package/skills/agentvfx/templates/light/light-leak/demo-vintage-burn.json +10 -0
  266. package/skills/agentvfx/templates/light/light-leak/fx.json +40 -0
  267. package/skills/agentvfx/templates/light/light-leak/main.frag +46 -0
  268. package/skills/agentvfx/templates/light/light-stage/fx.json +29 -0
  269. package/skills/agentvfx/templates/light/light-stage/main.frag +56 -0
  270. package/skills/agentvfx/templates/light/light-sweep/demo-hard-bar.json +12 -0
  271. package/skills/agentvfx/templates/light/light-sweep/demo-logo-sweep.json +10 -0
  272. package/skills/agentvfx/templates/light/light-sweep/demo-onset.json +11 -0
  273. package/skills/agentvfx/templates/light/light-sweep/fx.json +45 -0
  274. package/skills/agentvfx/templates/light/light-sweep/main.frag +29 -0
  275. package/skills/agentvfx/templates/light/light-sweep/pass0.frag +17 -0
  276. package/skills/agentvfx/templates/light/light-sweep/pass1.frag +15 -0
  277. package/skills/agentvfx/templates/light/neon-saber/demo-hairline.json +10 -0
  278. package/skills/agentvfx/templates/light/neon-saber/demo-saber-laser.json +10 -0
  279. package/skills/agentvfx/templates/light/neon-saber/fx.json +48 -0
  280. package/skills/agentvfx/templates/light/neon-saber/main.frag +27 -0
  281. package/skills/agentvfx/templates/light/neon-saber/pass0.frag +46 -0
  282. package/skills/agentvfx/templates/light/neon-saber/pass1.frag +15 -0
  283. package/skills/agentvfx/templates/psychedelic/echo-flow/demo-trail.json +1 -0
  284. package/skills/agentvfx/templates/psychedelic/echo-flow/fx.json +38 -0
  285. package/skills/agentvfx/templates/psychedelic/echo-flow/main.frag +19 -0
  286. package/skills/agentvfx/templates/psychedelic/echo-flow/pass0.frag +16 -0
  287. package/skills/agentvfx/templates/psychedelic/echo-flow/pass1.frag +20 -0
  288. package/skills/agentvfx/templates/psychedelic/echo-flow/pass2.frag +11 -0
  289. package/skills/agentvfx/templates/psychedelic/echo-flow/pass3.frag +4 -0
  290. package/skills/agentvfx/templates/psychedelic/hologram-scan/demo-cyan.json +1 -0
  291. package/skills/agentvfx/templates/psychedelic/hologram-scan/fx.json +36 -0
  292. package/skills/agentvfx/templates/psychedelic/hologram-scan/main.frag +30 -0
  293. package/skills/agentvfx/templates/psychedelic/kaleido-fold/demo-six.json +1 -0
  294. package/skills/agentvfx/templates/psychedelic/kaleido-fold/fx.json +37 -0
  295. package/skills/agentvfx/templates/psychedelic/kaleido-fold/main.frag +10 -0
  296. package/skills/agentvfx/templates/psychedelic/kaleido-fold/pass0.frag +34 -0
  297. package/skills/agentvfx/templates/psychedelic/mosh-melt/demo-classic.json +1 -0
  298. package/skills/agentvfx/templates/psychedelic/mosh-melt/fx.json +38 -0
  299. package/skills/agentvfx/templates/psychedelic/mosh-melt/main.frag +20 -0
  300. package/skills/agentvfx/templates/psychedelic/mosh-melt/pass0.frag +22 -0
  301. package/skills/agentvfx/templates/psychedelic/sacred/NOTES.md +13 -0
  302. package/skills/agentvfx/templates/psychedelic/sacred/demo-classic.json +1 -0
  303. package/skills/agentvfx/templates/psychedelic/sacred/demo-halo.json +1 -0
  304. package/skills/agentvfx/templates/psychedelic/sacred/demo-slow-tide.json +1 -0
  305. package/skills/agentvfx/templates/psychedelic/sacred/demo-thermal.json +1 -0
  306. package/skills/agentvfx/templates/psychedelic/sacred/fx.json +263 -0
  307. package/skills/agentvfx/templates/psychedelic/sacred/main.frag +109 -0
  308. package/skills/agentvfx/templates/psychedelic/sacred/pass0.frag +25 -0
  309. package/skills/agentvfx/templates/psychedelic/sacred/pass1.frag +23 -0
  310. package/skills/agentvfx/templates/psychedelic/tidal-bands/demo-classic.json +1 -0
  311. package/skills/agentvfx/templates/psychedelic/tidal-bands/fx.json +37 -0
  312. package/skills/agentvfx/templates/psychedelic/tidal-bands/main.frag +54 -0
  313. package/skills/agentvfx/templates/scope/_chrome.glsl +242 -0
  314. package/skills/agentvfx/templates/scope/goniometer/demo-boot-green.json +1 -0
  315. package/skills/agentvfx/templates/scope/goniometer/demo-field-lime.json +1 -0
  316. package/skills/agentvfx/templates/scope/goniometer/demo-field-ultramarine.json +1 -0
  317. package/skills/agentvfx/templates/scope/goniometer/demo-glow-phosphor.json +1 -0
  318. package/skills/agentvfx/templates/scope/goniometer/demo-hud-black.json +1 -0
  319. package/skills/agentvfx/templates/scope/goniometer/fx.json +635 -0
  320. package/skills/agentvfx/templates/scope/goniometer/main.frag +33 -0
  321. package/skills/agentvfx/templates/scope/goniometer/pass0.frag +58 -0
  322. package/skills/agentvfx/templates/scope/goniometer/pass1.frag +43 -0
  323. package/skills/agentvfx/templates/scope/goniometer/pass2.frag +12 -0
  324. package/skills/agentvfx/templates/scope/goniometer/pass3.frag +12 -0
  325. package/skills/agentvfx/templates/scope/goniometer/pass4.frag +12 -0
  326. package/skills/agentvfx/templates/scope/goniometer/pass5.frag +12 -0
  327. package/skills/agentvfx/templates/scope/goniometer/pass6.frag +251 -0
  328. package/skills/agentvfx/templates/scope/scope-polar/demo-boot-green.json +1 -0
  329. package/skills/agentvfx/templates/scope/scope-polar/demo-field-lime.json +1 -0
  330. package/skills/agentvfx/templates/scope/scope-polar/demo-field-ultramarine.json +1 -0
  331. package/skills/agentvfx/templates/scope/scope-polar/demo-glow-phosphor.json +1 -0
  332. package/skills/agentvfx/templates/scope/scope-polar/demo-hud-black.json +1 -0
  333. package/skills/agentvfx/templates/scope/scope-polar/fx.json +686 -0
  334. package/skills/agentvfx/templates/scope/scope-polar/main.frag +39 -0
  335. package/skills/agentvfx/templates/scope/scope-polar/pass0.frag +84 -0
  336. package/skills/agentvfx/templates/scope/scope-polar/pass1.frag +49 -0
  337. package/skills/agentvfx/templates/scope/scope-polar/pass2.frag +12 -0
  338. package/skills/agentvfx/templates/scope/scope-polar/pass3.frag +12 -0
  339. package/skills/agentvfx/templates/scope/scope-polar/pass4.frag +12 -0
  340. package/skills/agentvfx/templates/scope/scope-polar/pass5.frag +12 -0
  341. package/skills/agentvfx/templates/scope/scope-polar/pass6.frag +251 -0
  342. package/skills/agentvfx/templates/scope/scope-triggered/demo-boot-green.json +1 -0
  343. package/skills/agentvfx/templates/scope/scope-triggered/demo-field-lime.json +1 -0
  344. package/skills/agentvfx/templates/scope/scope-triggered/demo-field-ultramarine.json +1 -0
  345. package/skills/agentvfx/templates/scope/scope-triggered/demo-glow-phosphor.json +1 -0
  346. package/skills/agentvfx/templates/scope/scope-triggered/demo-hud-black.json +1 -0
  347. package/skills/agentvfx/templates/scope/scope-triggered/fx.json +712 -0
  348. package/skills/agentvfx/templates/scope/scope-triggered/main.frag +36 -0
  349. package/skills/agentvfx/templates/scope/scope-triggered/pass0.frag +78 -0
  350. package/skills/agentvfx/templates/scope/scope-triggered/pass1.frag +50 -0
  351. package/skills/agentvfx/templates/scope/scope-triggered/pass2.frag +12 -0
  352. package/skills/agentvfx/templates/scope/scope-triggered/pass3.frag +12 -0
  353. package/skills/agentvfx/templates/scope/scope-triggered/pass4.frag +12 -0
  354. package/skills/agentvfx/templates/scope/scope-triggered/pass5.frag +12 -0
  355. package/skills/agentvfx/templates/scope/scope-triggered/pass6.frag +251 -0
  356. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-boot-green.json +1 -0
  357. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-field-lime.json +1 -0
  358. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-field-ultramarine.json +1 -0
  359. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-glow-phosphor.json +1 -0
  360. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-hud-black.json +1 -0
  361. package/skills/agentvfx/templates/scope/spectrogram-scroll/fx.json +595 -0
  362. package/skills/agentvfx/templates/scope/spectrogram-scroll/main.frag +83 -0
  363. package/skills/agentvfx/templates/scope/spectrogram-scroll/pass0.frag +52 -0
  364. package/skills/agentvfx/templates/scope/spectrogram-scroll/pass1.frag +251 -0
  365. package/skills/agentvfx/templates/scope/xy-phosphor/demo-boot-green.json +1 -0
  366. package/skills/agentvfx/templates/scope/xy-phosphor/demo-field-lime.json +1 -0
  367. package/skills/agentvfx/templates/scope/xy-phosphor/demo-field-ultramarine.json +1 -0
  368. package/skills/agentvfx/templates/scope/xy-phosphor/demo-glow-phosphor.json +1 -0
  369. package/skills/agentvfx/templates/scope/xy-phosphor/demo-hud-black.json +1 -0
  370. package/skills/agentvfx/templates/scope/xy-phosphor/fx.json +642 -0
  371. package/skills/agentvfx/templates/scope/xy-phosphor/main.frag +33 -0
  372. package/skills/agentvfx/templates/scope/xy-phosphor/pass0.frag +56 -0
  373. package/skills/agentvfx/templates/scope/xy-phosphor/pass1.frag +44 -0
  374. package/skills/agentvfx/templates/scope/xy-phosphor/pass2.frag +12 -0
  375. package/skills/agentvfx/templates/scope/xy-phosphor/pass3.frag +12 -0
  376. package/skills/agentvfx/templates/scope/xy-phosphor/pass4.frag +12 -0
  377. package/skills/agentvfx/templates/scope/xy-phosphor/pass5.frag +12 -0
  378. package/skills/agentvfx/templates/scope/xy-phosphor/pass6.frag +251 -0
  379. package/skills/agentvfx/templates/spectrum/_src/bars-linear/fx.src.json +61 -0
  380. package/skills/agentvfx/templates/spectrum/_src/bars-linear/main.src.frag +112 -0
  381. package/skills/agentvfx/templates/spectrum/_src/bars-linear/pass0.src.frag +2 -0
  382. package/skills/agentvfx/templates/spectrum/_src/bars-mirror/fx.src.json +51 -0
  383. package/skills/agentvfx/templates/spectrum/_src/bars-mirror/main.src.frag +72 -0
  384. package/skills/agentvfx/templates/spectrum/_src/bars-mirror/pass0.src.frag +2 -0
  385. package/skills/agentvfx/templates/spectrum/_src/bass-circle/fx.src.json +56 -0
  386. package/skills/agentvfx/templates/spectrum/_src/bass-circle/main.src.frag +136 -0
  387. package/skills/agentvfx/templates/spectrum/_src/bass-circle/pass0.src.frag +2 -0
  388. package/skills/agentvfx/templates/spectrum/_src/build.mjs +68 -0
  389. package/skills/agentvfx/templates/spectrum/_src/label-bars/fx.src.json +54 -0
  390. package/skills/agentvfx/templates/spectrum/_src/label-bars/main.src.frag +102 -0
  391. package/skills/agentvfx/templates/spectrum/_src/label-bars/pass0.src.frag +2 -0
  392. package/skills/agentvfx/templates/spectrum/_src/shared/bars-fn.glsl +64 -0
  393. package/skills/agentvfx/templates/spectrum/_src/shared/bars-pass.glsl +22 -0
  394. package/skills/agentvfx/templates/spectrum/_src/shared/clock.glsl +7 -0
  395. package/skills/agentvfx/templates/spectrum/_src/shared/hud.glsl +50 -0
  396. package/skills/agentvfx/templates/spectrum/_src/shared/stage.glsl +74 -0
  397. package/skills/agentvfx/templates/spectrum/_src/spectrum-particles/fx.src.json +58 -0
  398. package/skills/agentvfx/templates/spectrum/_src/spectrum-particles/main.src.frag +119 -0
  399. package/skills/agentvfx/templates/spectrum/_src/spectrum-particles/pass0.src.frag +33 -0
  400. package/skills/agentvfx/templates/spectrum/_src/spectrum-radial/fx.src.json +56 -0
  401. package/skills/agentvfx/templates/spectrum/_src/spectrum-radial/main.src.frag +95 -0
  402. package/skills/agentvfx/templates/spectrum/_src/spectrum-radial/pass0.src.frag +2 -0
  403. package/skills/agentvfx/templates/spectrum/_src/waveform-line/fx.src.json +60 -0
  404. package/skills/agentvfx/templates/spectrum/_src/waveform-line/main.src.frag +98 -0
  405. package/skills/agentvfx/templates/spectrum/_src/waveform-line/pass0.src.frag +43 -0
  406. package/skills/agentvfx/templates/spectrum/bars-linear/demo-graph-acid.json +1 -0
  407. package/skills/agentvfx/templates/spectrum/bars-linear/demo-graph-black.json +1 -0
  408. package/skills/agentvfx/templates/spectrum/bars-linear/fx.json +632 -0
  409. package/skills/agentvfx/templates/spectrum/bars-linear/main.frag +233 -0
  410. package/skills/agentvfx/templates/spectrum/bars-linear/pass0.frag +91 -0
  411. package/skills/agentvfx/templates/spectrum/bars-mirror/demo-field-acid.json +1 -0
  412. package/skills/agentvfx/templates/spectrum/bars-mirror/demo-field-ultramarine.json +1 -0
  413. package/skills/agentvfx/templates/spectrum/bars-mirror/fx.json +539 -0
  414. package/skills/agentvfx/templates/spectrum/bars-mirror/main.frag +193 -0
  415. package/skills/agentvfx/templates/spectrum/bars-mirror/pass0.frag +91 -0
  416. package/skills/agentvfx/templates/spectrum/bass-circle/demo-bracket-black.json +1 -0
  417. package/skills/agentvfx/templates/spectrum/bass-circle/demo-bracket-ultramarine.json +1 -0
  418. package/skills/agentvfx/templates/spectrum/bass-circle/fx.json +552 -0
  419. package/skills/agentvfx/templates/spectrum/bass-circle/main.frag +258 -0
  420. package/skills/agentvfx/templates/spectrum/bass-circle/pass0.frag +91 -0
  421. package/skills/agentvfx/templates/spectrum/label-bars/demo-deck-black.json +1 -0
  422. package/skills/agentvfx/templates/spectrum/label-bars/demo-deck-ultramarine.json +1 -0
  423. package/skills/agentvfx/templates/spectrum/label-bars/fx.json +552 -0
  424. package/skills/agentvfx/templates/spectrum/label-bars/main.frag +223 -0
  425. package/skills/agentvfx/templates/spectrum/label-bars/pass0.frag +91 -0
  426. package/skills/agentvfx/templates/spectrum/spectrum-particles/demo-cloud-black.json +1 -0
  427. package/skills/agentvfx/templates/spectrum/spectrum-particles/demo-cloud-ultramarine.json +1 -0
  428. package/skills/agentvfx/templates/spectrum/spectrum-particles/fx.json +584 -0
  429. package/skills/agentvfx/templates/spectrum/spectrum-particles/main.frag +240 -0
  430. package/skills/agentvfx/templates/spectrum/spectrum-particles/pass0.frag +101 -0
  431. package/skills/agentvfx/templates/spectrum/spectrum-radial/demo-starburst-black.json +1 -0
  432. package/skills/agentvfx/templates/spectrum/spectrum-radial/demo-starburst-ultramarine.json +1 -0
  433. package/skills/agentvfx/templates/spectrum/spectrum-radial/fx.json +566 -0
  434. package/skills/agentvfx/templates/spectrum/spectrum-radial/main.frag +217 -0
  435. package/skills/agentvfx/templates/spectrum/spectrum-radial/pass0.frag +91 -0
  436. package/skills/agentvfx/templates/spectrum/waveform-line/demo-strip-acid.json +1 -0
  437. package/skills/agentvfx/templates/spectrum/waveform-line/demo-strip-black.json +1 -0
  438. package/skills/agentvfx/templates/spectrum/waveform-line/fx.json +481 -0
  439. package/skills/agentvfx/templates/spectrum/waveform-line/main.frag +219 -0
  440. package/skills/agentvfx/templates/spectrum/waveform-line/pass0.frag +48 -0
  441. package/skills/agentvfx/templates/spectrum/waveform-line/pass1.frag +86 -0
  442. package/skills/agentvfx/test/_render_light.mjs +38 -0
  443. package/skills/agentvfx/test/audio-stereo.test.mjs +45 -0
  444. package/skills/agentvfx/test/audio.test.mjs +257 -0
  445. package/skills/agentvfx/test/brutal.test.mjs +190 -0
  446. package/skills/agentvfx/test/concept-collage-layout.test.mjs +236 -0
  447. package/skills/agentvfx/test/concept-collage-scenes.test.mjs +305 -0
  448. package/skills/agentvfx/test/concept-collage-typefx.test.mjs +153 -0
  449. package/skills/agentvfx/test/concept-collage.test.mjs +84 -0
  450. package/skills/agentvfx/test/concept-lattice.test.mjs +133 -0
  451. package/skills/agentvfx/test/concept-signal-cut.test.mjs +172 -0
  452. package/skills/agentvfx/test/credit-overlay.test.mjs +58 -0
  453. package/skills/agentvfx/test/credit.test.mjs +42 -0
  454. package/skills/agentvfx/test/doctor.test.mjs +31 -0
  455. package/skills/agentvfx/test/encode.test.mjs +22 -0
  456. package/skills/agentvfx/test/fixtures/r7-collage-LAYOUTS.json +5780 -0
  457. package/skills/agentvfx/test/fixtures/score-bad-duration.json +7 -0
  458. package/skills/agentvfx/test/fixtures/score-bad-safety.json +8 -0
  459. package/skills/agentvfx/test/fixtures/score-identity-footage.json +8 -0
  460. package/skills/agentvfx/test/fixtures/score-missing-template.json +7 -0
  461. package/skills/agentvfx/test/fixtures/score-ok.json +8 -0
  462. package/skills/agentvfx/test/fixtures/score-strobe-12hz.json +8 -0
  463. package/skills/agentvfx/test/fixtures/score-text-probe.json +1 -0
  464. package/skills/agentvfx/test/flash-audit.test.mjs +150 -0
  465. package/skills/agentvfx/test/flash.test.mjs +83 -0
  466. package/skills/agentvfx/test/footage.test.mjs +88 -0
  467. package/skills/agentvfx/test/glitch.test.mjs +272 -0
  468. package/skills/agentvfx/test/impact.test.mjs +231 -0
  469. package/skills/agentvfx/test/imports.test.mjs +39 -0
  470. package/skills/agentvfx/test/light.test.mjs +200 -0
  471. package/skills/agentvfx/test/loop.test.mjs +80 -0
  472. package/skills/agentvfx/test/psychedelic.test.mjs +99 -0
  473. package/skills/agentvfx/test/render.test.mjs +73 -0
  474. package/skills/agentvfx/test/sacred.test.mjs +175 -0
  475. package/skills/agentvfx/test/schema.test.mjs +103 -0
  476. package/skills/agentvfx/test/scope.test.mjs +306 -0
  477. package/skills/agentvfx/test/spectrum.test.mjs +165 -0
  478. package/skills/agentvfx/test/text.test.mjs +142 -0
  479. package/skills/agentvfx/test/web.test.mjs +397 -0
  480. package/skills/agentvfx/test-media/SOURCES.md +39 -0
  481. package/skills/agentvfx/test-media/beat-132.mp3 +0 -0
  482. package/skills/agentvfx/test-media/clip-01.mp4 +0 -0
  483. package/skills/agentvfx/test-media/clip-02.mp4 +0 -0
@@ -0,0 +1,28 @@
1
+ // agentvfx (agentvfx licence, see LICENSE). Local replacement for the plugin's lib/mark.mjs: the generator
2
+ // tag and the credit line that ffmpeg writes into every MP4, plus an optional comment (the stage-mode flashing notice).
3
+ // Attribution is a licence condition for published output, so the credit also goes to CREDIT.txt next to the film.
4
+ export const GENERATOR = "agentvfx";
5
+ export const CREDIT_TEXT = "Made with agentvfx by Woojin Go - https://github.com/wjgoarxiv/agentvfx";
6
+ export const CREDIT_SHORT = "VFX: agentvfx (github.com/wjgoarxiv/agentvfx)";
7
+
8
+ export function creditText() {
9
+ return `${CREDIT_TEXT}
10
+
11
+ Publishing this film? The agentvfx licence requires a credit. The film carries a small on-screen credit; keep it
12
+ in the frame. If you switched it off ("credit": { "overlay": false }), put the line above where viewers can find
13
+ it: the description, caption or credits. Where space is short: ${CREDIT_SHORT}
14
+ When you hand the film to someone who will publish it, pass the credit on with it.
15
+ Licence: the agentvfx licence (Additional Terms plus the PolyForm Noncommercial License 1.0.0). Individuals may use
16
+ their own output commercially; companies, client work, paid services and AI training are not covered.
17
+ See LICENSE in https://github.com/wjgoarxiv/agentvfx.
18
+ `;
19
+ }
20
+
21
+ export function ffmpegMetadataArgs({ comment = null } = {}) {
22
+ const args = ["-metadata", `encoder_tool=${GENERATOR}`, "-metadata", `description=${CREDIT_TEXT}`];
23
+ if (comment) args.push("-metadata", `comment=${comment}`);
24
+ return args;
25
+ }
26
+
27
+ // The on-screen credit burned into a corner of every render unless the score sets "credit": { "overlay": false }.
28
+ export const CREDIT_OVERLAY = "made with agentvfx";
@@ -0,0 +1,36 @@
1
+ // agentvfx (agentvfx licence, see LICENSE). Shared palettes, usable by any template that declares a `palette` input.
2
+ // Each palette is a list of sRGB hex stops; templates sample it as a ramp (index 0..1) or as a cyclic
3
+ // ramp. Brutal palettes are black, white and one acid accent, in the spirit of festival HUD
4
+ // colour grammar; the names are neutral and no existing colour system is copied.
5
+
6
+ export const PALETTES = Object.freeze({
7
+ "brutal-acid": ["#000000", "#ffffff", "#c8ff00"],
8
+ "brutal-red": ["#000000", "#ffffff", "#ff2a00"],
9
+ mono: ["#000000", "#ffffff"],
10
+ rainbow: ["#ff0040", "#ff8000", "#ffee00", "#30ff40", "#00e5ff", "#2040ff", "#b000ff", "#ff00c8"],
11
+ thermal: ["#0010ff", "#6a00ff", "#ff00d0", "#ff0030", "#ff7a00", "#ffee00", "#00ffe0"],
12
+ "paper-grey": ["#d9d9d6", "#0a0a0a", "#ff2a6d"],
13
+ "acid-data": ["#000000", "#b6ff00", "#1f4dff"],
14
+ "hazard-orange": ["#141414", "#8c8c88", "#ff5a00"],
15
+ "flesh-pink": ["#ffffff", "#ff3c8e", "#111111"],
16
+ "lilac-terminal": ["#0b0613", "#b69cff", "#ff6ad5"],
17
+ "blood-red": ["#000000", "#d10000", "#ffffff"],
18
+ "clinic-mint": ["#f2f4f1", "#7fe3c1", "#b8a4ff"],
19
+ });
20
+
21
+ export const PALETTE_NAMES = Object.freeze(Object.keys(PALETTES));
22
+
23
+ /** "#rrggbb" -> [r, g, b] in 0..1 (sRGB). */
24
+ export function hexToRgb(hex) {
25
+ const m = /^#([0-9a-f]{6})$/iu.exec(hex);
26
+ if (!m) throw new Error(`not a #rrggbb colour: ${hex}`);
27
+ const n = parseInt(m[1], 16);
28
+ return [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255];
29
+ }
30
+
31
+ /** A palette name or a custom list of 2-8 hex stops -> list of [r, g, b]. */
32
+ export function resolvePalette(value) {
33
+ const stops = typeof value === "string" ? PALETTES[value] : value;
34
+ if (!Array.isArray(stops)) throw new Error(`unknown palette: ${value}`);
35
+ return stops.map(hexToRgb);
36
+ }
@@ -0,0 +1,85 @@
1
+ // agentvfx (agentvfx licence, see LICENSE). The score compositor's timeline: for each frame, which layers are active
2
+ // (base stack, cuts, hits), their parameter values (preset, params, audio bindings) and their local
3
+ // time. Pure and deterministic; the page only draws what this returns.
4
+ import { resolveParams } from "./templates.mjs";
5
+
6
+ const isNum = (v) => typeof v === "number" && Number.isFinite(v);
7
+
8
+ /** Resolve a `t` / `beat` / `onset` reference to a frame index. */
9
+ export function resolveFrame(ref, { fps, features }, path) {
10
+ if (ref.t !== undefined) return Math.round(ref.t * fps);
11
+ const kind = ref.beat !== undefined ? "beat" : "onset";
12
+ const list = kind === "beat" ? features?.meta?.beats : features?.meta?.onsets;
13
+ if (!list) throw Object.assign(new Error(`${path}.${kind}: needs an audio source (input.audio or a video with sound)`), { path: `${path}.${kind}` });
14
+ const idx = ref[kind];
15
+ if (idx >= list.length) throw Object.assign(new Error(`${path}.${kind}: index ${idx} but the track has ${list.length} ${kind}s`), { path: `${path}.${kind}` });
16
+ return list[idx];
17
+ }
18
+
19
+ const layerRef = (l) => (typeof l === "string" ? { template: l } : l);
20
+
21
+ /** Feature value for a binding ("bands.12" or a scalar name) on one frame of features. */
22
+ function featureValue(frame, feature) {
23
+ if (!frame) return 0;
24
+ if (feature.startsWith("bands.")) return Number(frame.bands?.[Number(feature.slice(6))] ?? 0);
25
+ return Number(frame[feature] ?? 0);
26
+ }
27
+
28
+ /**
29
+ * Build the per-frame plan. Returns { frameCount, frames: [{ layers: [{key, template, params, t}] }],
30
+ * templatesUsed: Set, events: [frame...] } where events are the frames of hits and cuts (for strips).
31
+ */
32
+ export function buildSchedule(score, lib, { features = null } = {}) {
33
+ const fps = score.fps;
34
+ const frameCount = Math.round(score.durationSec * fps);
35
+ const ctx = { fps, features };
36
+ const used = new Set();
37
+ const resolve = (ref) => {
38
+ const tpl = lib.get(ref.template);
39
+ used.add(ref.template);
40
+ const text = tpl.fx.X_AGENTVFX.text;
41
+ const labels = text ? Object.fromEntries(text.map((t) => [t.key, score.labels?.[t.key] ?? t.default])) : null;
42
+ const styled = text && score.textStyle ? text.filter((t) => score.textStyle[t.key]) : [];
43
+ const textStyle = styled.length ? Object.fromEntries(styled.map((t) => [t.key, score.textStyle[t.key]])) : null;
44
+ return { template: ref.template, params: resolveParams(tpl.fx, ref), inputs: tpl.fx.INPUTS ?? [], labels, textStyle };
45
+ };
46
+ const initial = [{ template: score.template, preset: score.preset, params: score.params }, ...(score.stack ?? []).map(layerRef)].map(resolve);
47
+ const cuts = (score.cuts ?? []).map((c, i) => ({ frame: resolveFrame(c, ctx, `cuts[${i}]`), index: i, layers: c.layers.map(layerRef).map(resolve) }))
48
+ .sort((a, b) => a.frame - b.frame || a.index - b.index);
49
+ const hits = (score.hits ?? []).map((h, i) => ({ start: resolveFrame(h, ctx, `hits[${i}]`), index: i, duration: h.durationFrames, layer: resolve({ template: h.template, preset: h.preset, params: h.params }) }));
50
+
51
+ const bindings = (score.bindings ?? []).map((b) => ({ ...b, state: 0 }));
52
+ const frames = [];
53
+ for (let f = 0; f < frameCount; f++) {
54
+ let base = { id: "b", layers: initial };
55
+ for (const c of cuts) if (c.frame <= f) base = { id: `c${c.index}`, layers: c.layers };
56
+ const featureFrame = features?.frames?.[f] ?? null;
57
+ const bound = {};
58
+ for (const b of bindings) {
59
+ const raw = featureValue(featureFrame, b.feature);
60
+ const ms = raw > b.state ? b.attackMs : b.releaseMs;
61
+ const k = isNum(ms) && ms > 0 ? Math.exp(-1000 / (fps * ms)) : 0;
62
+ b.state = k * b.state + (1 - k) * raw;
63
+ bound[b.param] = b.offset + b.gain * b.state;
64
+ }
65
+ const applyBindings = (layer) => {
66
+ if (layer.template !== score.template || !bindings.length) return layer.params;
67
+ const params = { ...layer.params };
68
+ for (const input of layer.inputs) {
69
+ if (bound[input.NAME] === undefined) continue;
70
+ let v = bound[input.NAME];
71
+ if (isNum(input.MIN)) v = Math.max(input.MIN, v);
72
+ if (isNum(input.MAX)) v = Math.min(input.MAX, v);
73
+ params[input.NAME] = input.TYPE === "long" ? Math.round(v) : input.TYPE === "bool" ? v > 0.5 : v;
74
+ }
75
+ return params;
76
+ };
77
+ const layers = base.layers.map((l, i) => ({ key: `${base.id}:${i}`, template: l.template, params: applyBindings(l), t: f / fps, ...(l.labels ? { labels: l.labels } : {}), ...(l.textStyle ? { textStyle: l.textStyle } : {}) }));
78
+ for (const h of hits) {
79
+ if (f >= h.start && f < h.start + h.duration) layers.push({ key: `h${h.index}`, template: h.layer.template, params: h.layer.params, t: (f - h.start) / fps, ...(h.layer.labels ? { labels: h.layer.labels } : {}), ...(h.layer.textStyle ? { textStyle: h.layer.textStyle } : {}) });
80
+ }
81
+ frames.push({ layers });
82
+ }
83
+ const events = [...new Set([...cuts.map((c) => c.frame), ...hits.map((h) => h.start)])].filter((f) => f >= 0 && f < frameCount).sort((a, b) => a - b);
84
+ return { frameCount, fps, frames, templatesUsed: used, events };
85
+ }
@@ -0,0 +1,43 @@
1
+ // agentvfx (agentvfx licence, see LICENSE). The template library: every templates/<family>/<id>/fx.json, keyed by
2
+ // X_AGENTVFX.id. Test templates live under templates/_test/ and are loaded only on request.
3
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ export const TEMPLATES_ROOT = fileURLToPath(new URL("../../templates/", import.meta.url));
8
+
9
+ /** Map id -> { id, dir, rel, family, fx, passes: [file...] }. Throws on a duplicate id or unreadable JSON. */
10
+ export function loadLibrary({ root = TEMPLATES_ROOT, includeTest = false } = {}) {
11
+ const lib = new Map();
12
+ if (!existsSync(root)) return lib;
13
+ for (const family of readdirSync(root).sort()) {
14
+ const fdir = path.join(root, family);
15
+ if (!statSync(fdir).isDirectory()) continue;
16
+ if (family === "_test" && !includeTest) continue;
17
+ if (family.startsWith(".") || (family.startsWith("_") && family !== "_test")) continue;
18
+ for (const name of readdirSync(fdir).sort()) {
19
+ const dir = path.join(fdir, name);
20
+ const file = path.join(dir, "fx.json");
21
+ if (!statSync(dir).isDirectory() || !existsSync(file)) continue;
22
+ let fx;
23
+ try {
24
+ fx = JSON.parse(readFileSync(file, "utf8"));
25
+ } catch (error) {
26
+ throw new Error(`${path.relative(root, file)}: invalid JSON (${error.message})`);
27
+ }
28
+ const id = fx?.X_AGENTVFX?.id ?? name;
29
+ if (lib.has(id)) throw new Error(`duplicate template id ${id} (${path.relative(root, lib.get(id).dir)} and ${path.relative(root, dir)})`);
30
+ const passes = readdirSync(dir).filter((f) => /^(main|pass\d+)\.frag$/u.test(f)).sort();
31
+ lib.set(id, { id, dir, rel: path.relative(root, dir).split(path.sep).join("/"), family, fx, passes });
32
+ }
33
+ }
34
+ return lib;
35
+ }
36
+
37
+ /** Defaults from INPUTS, then the named preset, then explicit params. */
38
+ export function resolveParams(fx, { preset = null, params = {} } = {}) {
39
+ const out = {};
40
+ for (const input of fx.INPUTS ?? []) if (input.DEFAULT !== undefined) out[input.NAME] = input.DEFAULT;
41
+ if (preset) Object.assign(out, fx.X_AGENTVFX.presets[preset]);
42
+ return Object.assign(out, params);
43
+ }
@@ -0,0 +1,167 @@
1
+ // Pure math, easing and seeded-randomness helpers shared by the page engine and the Node side.
2
+ // Adapted from mexicat/pdoom-video app/src/engine/util.ts (MIT, see ../NOTICE). Every function is a
3
+ // deterministic function of its arguments: nothing here may read a clock or an unseeded RNG
4
+ // (MO-A-23), because the determinism gate hashes frames rendered by two separate processes.
5
+
6
+ export const clamp = (x, a = 0, b = 1) => (x < a ? a : x > b ? b : x);
7
+ export const lerp = (a, b, t) => a + (b - a) * t;
8
+ export const invLerp = (a, b, x) => (a === b ? 0 : (x - a) / (b - a));
9
+ export const remap = (x, a, b, c, d, clamped = true) => {
10
+ const t = invLerp(a, b, x);
11
+ return lerp(c, d, clamped ? clamp(t) : t);
12
+ };
13
+ export const smoothstep = (a, b, x) => {
14
+ const t = clamp((x - a) / (b - a));
15
+ return t * t * (3 - 2 * t);
16
+ };
17
+ export const fract = (x) => x - Math.floor(x);
18
+ export const mod = (x, m) => ((x % m) + m) % m;
19
+ export const TAU = Math.PI * 2;
20
+
21
+ // Cubic bezier easing, solved by a fixed 40-step bisection so the value never depends on a
22
+ // convergence tolerance.
23
+ function bezier(x1, y1, x2, y2) {
24
+ const coord = (t, a, b) => 3 * a * t * (1 - t) ** 2 + 3 * b * t * t * (1 - t) + t ** 3;
25
+ return (x) => {
26
+ if (x <= 0) return 0;
27
+ if (x >= 1) return 1;
28
+ let lo = 0;
29
+ let hi = 1;
30
+ for (let i = 0; i < 40; i++) {
31
+ const mid = (lo + hi) / 2;
32
+ if (coord(mid, x1, x2) < x) lo = mid;
33
+ else hi = mid;
34
+ }
35
+ return coord((lo + hi) / 2, y1, y2);
36
+ };
37
+ }
38
+
39
+ // The named easing set (MO-A-08). Scenes pick from these names; ad hoc curves are not allowed.
40
+ export const ease = Object.freeze({
41
+ linear: (t) => t,
42
+ outQuad: (t) => 1 - (1 - t) * (1 - t),
43
+ inOutQuad: (t) => (t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2),
44
+ outCubic: (t) => 1 - (1 - t) ** 3,
45
+ inOutCubic: (t) => (t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2),
46
+ outExpo: (t) => (t >= 1 ? 1 : 1 - 2 ** (-10 * t)),
47
+ // Film tokens from the preset bibles (MO-B-01..03).
48
+ slam: bezier(0.16, 1, 0.3, 1),
49
+ drift: bezier(0.37, 0, 0.63, 1),
50
+ surgePunch: bezier(0.16, 1, 0.3, 1),
51
+ });
52
+
53
+ /** Eased progress of x through [a, b], clamped. */
54
+ export const prog = (x, a, b, fn = ease.linear) => fn(clamp((x - a) / (b - a)));
55
+
56
+ /**
57
+ * Piecewise interpolation through keyframes `[[time, value, easeName], ...]`; the ease on key i
58
+ * shapes the segment that ends at key i. Only names from `ease` are accepted.
59
+ */
60
+ export function keys(t, ks) {
61
+ if (ks.length === 0) return 0;
62
+ if (t <= ks[0][0]) return ks[0][1];
63
+ for (let i = 1; i < ks.length; i++) {
64
+ const [time, value, name = "inOutCubic"] = ks[i];
65
+ if (t <= time) {
66
+ const [pt, pv] = ks[i - 1];
67
+ const fn = ease[name];
68
+ if (!fn) throw new Error(`unknown ease: ${name}`);
69
+ return lerp(pv, value, fn((t - pt) / (time - pt)));
70
+ }
71
+ }
72
+ return ks[ks.length - 1][1];
73
+ }
74
+
75
+ /** Damped spring response to a step at time 0 (the rare deliberate overshoot, MO-A-08). */
76
+ export const springStep = (t, freq = 4, damping = 0.35) => {
77
+ if (t <= 0) return 0;
78
+ const w = TAU * freq;
79
+ return 1 - Math.exp(-damping * w * t) * Math.cos(w * Math.sqrt(1 - damping * damping) * t);
80
+ };
81
+
82
+ /** Exponential decay after an event at t0 (1 at t0, half-life hl). */
83
+ export const pulse = (t, t0, hl = 0.12) => (t < t0 ? 0 : 0.5 ** ((t - t0) / hl));
84
+
85
+ // ---- seeded randomness (MO-SH-01, MO-A-23) ----
86
+
87
+ /** FNV-1a 32-bit over the UTF-8 bytes of `text`; offset basis 0x811c9dc5, prime 0x01000193. */
88
+ export function fnv1a32(text) {
89
+ let hash = 0x811c9dc5;
90
+ for (const byte of new TextEncoder().encode(text)) {
91
+ hash ^= byte;
92
+ hash = Math.imul(hash, 0x01000193) >>> 0;
93
+ }
94
+ return hash >>> 0;
95
+ }
96
+
97
+ /** MO-SH-01: the one seed formula for every pass in every product. */
98
+ export const passSeed = (runSeed, sceneId, shotIndex, pass) => fnv1a32(`${runSeed}:${sceneId}:${shotIndex}:${pass}`);
99
+
100
+ /** mulberry32 PRNG in unsigned 32-bit arithmetic. Returns a function yielding [0, 1). */
101
+ export function mulberry32(seed) {
102
+ let a = seed >>> 0;
103
+ return () => {
104
+ a = (a + 0x6d2b79f5) >>> 0;
105
+ let t = a;
106
+ t = Math.imul(t ^ (t >>> 15), t | 1);
107
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
108
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
109
+ };
110
+ }
111
+
112
+ /** Stateless hash of numbers to [0, 1). */
113
+ export function hash(...xs) {
114
+ let h = 2166136261 >>> 0;
115
+ for (const x of xs) {
116
+ h ^= Math.floor(x * 1000003) | 0;
117
+ h = Math.imul(h, 16777619);
118
+ h ^= h >>> 13;
119
+ h = Math.imul(h, 0x5bd1e995);
120
+ h ^= h >>> 15;
121
+ }
122
+ return (h >>> 0) / 4294967296;
123
+ }
124
+
125
+ const quintic = (t) => t * t * t * (t * (t * 6 - 15) + 10);
126
+ export function noise1(x, seed = 0) {
127
+ const i = Math.floor(x);
128
+ return lerp(hash(i, seed) * 2 - 1, hash(i + 1, seed) * 2 - 1, quintic(x - i));
129
+ }
130
+
131
+ // ---- colour ----
132
+
133
+ export const srgbToLinear = (s) => (s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4);
134
+ export const linearToSrgb = (l) => (l <= 0.0031308 ? 12.92 * l : 1.055 * l ** (1 / 2.4) - 0.055);
135
+
136
+ export function hexToRgb(hex) {
137
+ const n = Number.parseInt(hex.replace("#", ""), 16);
138
+ return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
139
+ }
140
+ export const hexToLinear = (hex) => hexToRgb(hex).map((v) => srgbToLinear(v / 255));
141
+
142
+ /** WCAG relative luminance of an sRGB hex colour. */
143
+ export function relativeLuminance(hex) {
144
+ const [r, g, b] = hexToLinear(hex);
145
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
146
+ }
147
+ export const contrastRatio = (la, lb) => (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
148
+
149
+ /** HSL hue (degrees) and saturation (0..1) of 0..255 sRGB values. */
150
+ export function hsl(r, g, b) {
151
+ const [rn, gn, bn] = [r / 255, g / 255, b / 255];
152
+ const max = Math.max(rn, gn, bn);
153
+ const min = Math.min(rn, gn, bn);
154
+ const l = (max + min) / 2;
155
+ const d = max - min;
156
+ if (d === 0) return { h: 0, s: 0, l };
157
+ const s = d / (1 - Math.abs(2 * l - 1));
158
+ let h;
159
+ if (max === rn) h = ((gn - bn) / d) % 6;
160
+ else if (max === gn) h = (bn - rn) / d + 2;
161
+ else h = (rn - gn) / d + 4;
162
+ return { h: mod(h * 60, 360), s, l };
163
+ }
164
+ export const hueDistance = (a, b) => {
165
+ const d = Math.abs(mod(a, 360) - mod(b, 360));
166
+ return Math.min(d, 360 - d);
167
+ };