@biunow/agent-biuart 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/bin/server.mjs +575 -0
  2. package/data/styles.json +533 -0
  3. package/engine/audit_clip.py +46 -0
  4. package/engine/clip.html +24 -0
  5. package/engine/clip.js +104 -0
  6. package/engine/clip_schema.json +19 -0
  7. package/engine/clips/t1_3b1b.js +203 -0
  8. package/engine/clips/t2_keynote_ui.js +347 -0
  9. package/engine/clips/t3_finance_chart.js +206 -0
  10. package/engine/clips/y1_kurzgesagt.js +183 -0
  11. package/engine/clips/y2_vox.js +150 -0
  12. package/engine/clips/y3_whiteboard.js +209 -0
  13. package/engine/clips/y4_storytime.js +194 -0
  14. package/engine/clips/y5_kinetic_type.js +134 -0
  15. package/engine/compare.py +19 -0
  16. package/engine/demos/_shared/hero/c1_0.png +0 -0
  17. package/engine/demos/_shared/hero/c1_1.png +0 -0
  18. package/engine/demos/_shared/hero/c1_2.png +0 -0
  19. package/engine/demos/_shared/hero/c3_line.png +0 -0
  20. package/engine/demos/_shared/hero.js +96 -0
  21. package/engine/demos/long_scroll/eras.js +23 -0
  22. package/engine/demos/long_scroll/frames/8bit_act/01.png +0 -0
  23. package/engine/demos/long_scroll/frames/8bit_act/02.png +0 -0
  24. package/engine/demos/long_scroll/frames/8bit_act/03.png +0 -0
  25. package/engine/demos/long_scroll/frames/8bit_act/04.png +0 -0
  26. package/engine/demos/long_scroll/frames/8bit_act/05.png +0 -0
  27. package/engine/demos/long_scroll/frames/8bit_act/06.png +0 -0
  28. package/engine/demos/long_scroll/frames/8bit_act/07.png +0 -0
  29. package/engine/demos/long_scroll/frames/8bit_act/08.png +0 -0
  30. package/engine/demos/long_scroll/frames/8bit_act/meta.json +69 -0
  31. package/engine/demos/long_scroll/frames/8bit_walk/01.png +0 -0
  32. package/engine/demos/long_scroll/frames/8bit_walk/02.png +0 -0
  33. package/engine/demos/long_scroll/frames/8bit_walk/03.png +0 -0
  34. package/engine/demos/long_scroll/frames/8bit_walk/04.png +0 -0
  35. package/engine/demos/long_scroll/frames/8bit_walk/05.png +0 -0
  36. package/engine/demos/long_scroll/frames/8bit_walk/06.png +0 -0
  37. package/engine/demos/long_scroll/frames/8bit_walk/07.png +0 -0
  38. package/engine/demos/long_scroll/frames/8bit_walk/08.png +0 -0
  39. package/engine/demos/long_scroll/frames/8bit_walk/meta.json +69 -0
  40. package/engine/demos/long_scroll/frames/egypt_dodge/01.png +0 -0
  41. package/engine/demos/long_scroll/frames/egypt_dodge/02.png +0 -0
  42. package/engine/demos/long_scroll/frames/egypt_dodge/03.png +0 -0
  43. package/engine/demos/long_scroll/frames/egypt_dodge/04.png +0 -0
  44. package/engine/demos/long_scroll/frames/egypt_dodge/05.png +0 -0
  45. package/engine/demos/long_scroll/frames/egypt_dodge/06.png +0 -0
  46. package/engine/demos/long_scroll/frames/egypt_dodge/07.png +0 -0
  47. package/engine/demos/long_scroll/frames/egypt_dodge/08.png +0 -0
  48. package/engine/demos/long_scroll/frames/egypt_dodge/meta.json +69 -0
  49. package/engine/demos/long_scroll/frames/egypt_walk8/01.png +0 -0
  50. package/engine/demos/long_scroll/frames/egypt_walk8/02.png +0 -0
  51. package/engine/demos/long_scroll/frames/egypt_walk8/03.png +0 -0
  52. package/engine/demos/long_scroll/frames/egypt_walk8/04.png +0 -0
  53. package/engine/demos/long_scroll/frames/egypt_walk8/05.png +0 -0
  54. package/engine/demos/long_scroll/frames/egypt_walk8/06.png +0 -0
  55. package/engine/demos/long_scroll/frames/egypt_walk8/07.png +0 -0
  56. package/engine/demos/long_scroll/frames/egypt_walk8/08.png +0 -0
  57. package/engine/demos/long_scroll/frames/egypt_walk8/meta.json +69 -0
  58. package/engine/demos/long_scroll/frames/monet_throw/01.png +0 -0
  59. package/engine/demos/long_scroll/frames/monet_throw/02.png +0 -0
  60. package/engine/demos/long_scroll/frames/monet_throw/03.png +0 -0
  61. package/engine/demos/long_scroll/frames/monet_throw/04.png +0 -0
  62. package/engine/demos/long_scroll/frames/monet_throw/05.png +0 -0
  63. package/engine/demos/long_scroll/frames/monet_throw/06.png +0 -0
  64. package/engine/demos/long_scroll/frames/monet_throw/07.png +0 -0
  65. package/engine/demos/long_scroll/frames/monet_throw/08.png +0 -0
  66. package/engine/demos/long_scroll/frames/monet_throw/meta.json +71 -0
  67. package/engine/demos/long_scroll/frames/monet_walk/01.png +0 -0
  68. package/engine/demos/long_scroll/frames/monet_walk/02.png +0 -0
  69. package/engine/demos/long_scroll/frames/monet_walk/03.png +0 -0
  70. package/engine/demos/long_scroll/frames/monet_walk/04.png +0 -0
  71. package/engine/demos/long_scroll/frames/monet_walk/05.png +0 -0
  72. package/engine/demos/long_scroll/frames/monet_walk/06.png +0 -0
  73. package/engine/demos/long_scroll/frames/monet_walk/07.png +0 -0
  74. package/engine/demos/long_scroll/frames/monet_walk/08.png +0 -0
  75. package/engine/demos/long_scroll/frames/monet_walk/meta.json +71 -0
  76. package/engine/demos/long_scroll/lib/acts.js +87 -0
  77. package/engine/demos/long_scroll/lib/crossing.js +463 -0
  78. package/engine/demos/long_scroll/lib/world.js +143 -0
  79. package/engine/demos/long_scroll/lib/xing2_ding.js +42 -0
  80. package/engine/demos/long_scroll/lib/xing2_jia.js +114 -0
  81. package/engine/demos/long_scroll/lib/xing2_yi.js +133 -0
  82. package/engine/demos/long_scroll/segments/02_egypt.js +234 -0
  83. package/engine/demos/long_scroll/segments/14_8bit.js +118 -0
  84. package/engine/demos/long_scroll/segments/28_monet.js +86 -0
  85. package/engine/demos/t1_3b1b/eras.js +11 -0
  86. package/engine/demos/t1_3b1b/t1_s1.js +101 -0
  87. package/engine/demos/t1_3b1b/t1_s2.js +74 -0
  88. package/engine/demos/t1_3b1b/t1_s3.js +65 -0
  89. package/engine/demos/t2_keynote_ui/eras.js +10 -0
  90. package/engine/demos/t2_keynote_ui/t2_s1.js +57 -0
  91. package/engine/demos/t2_keynote_ui/t2_s2.js +70 -0
  92. package/engine/demos/t2_keynote_ui/t2_s3.js +61 -0
  93. package/engine/demos/t3_finance_chart/eras.js +11 -0
  94. package/engine/demos/t3_finance_chart/t3_s1.js +48 -0
  95. package/engine/demos/t3_finance_chart/t3_s2.js +42 -0
  96. package/engine/demos/t3_finance_chart/t3_s3.js +51 -0
  97. package/engine/demos/y1_kurzgesagt/eras.js +10 -0
  98. package/engine/demos/y1_kurzgesagt/kurzgesagt.js +347 -0
  99. package/engine/demos/y2_vox/eras.js +10 -0
  100. package/engine/demos/y2_vox/vox.js +240 -0
  101. package/engine/demos/y3_whiteboard/eras.js +10 -0
  102. package/engine/demos/y3_whiteboard/whiteboard.js +162 -0
  103. package/engine/demos/y4_storytime/eras.js +14 -0
  104. package/engine/demos/y4_storytime/s1_desk.js +18 -0
  105. package/engine/demos/y4_storytime/s2_screen.js +82 -0
  106. package/engine/demos/y4_storytime/s3_react.js +39 -0
  107. package/engine/demos/y4_storytime/s4_wide.js +16 -0
  108. package/engine/demos/y4_storytime/s5_close.js +18 -0
  109. package/engine/demos/y4_storytime/story.js +25 -0
  110. package/engine/demos/y4_storytime/vo_env.js +2 -0
  111. package/engine/demos/y4_storytime/world.js +73 -0
  112. package/engine/demos/y5_kinetic_type/eras.js +16 -0
  113. package/engine/demos/y5_kinetic_type/k1_title.js +38 -0
  114. package/engine/demos/y5_kinetic_type/k2_complete.js +55 -0
  115. package/engine/demos/y5_kinetic_type/k3_chat.js +47 -0
  116. package/engine/demos/y5_kinetic_type/k4_agent.js +49 -0
  117. package/engine/demos/y5_kinetic_type/kinetic.js +52 -0
  118. package/engine/engine.js +277 -0
  119. package/engine/eras.js +60 -0
  120. package/engine/eras_gallery.js +115 -0
  121. package/engine/eras_style_studies.js +20 -0
  122. package/engine/examples/assets/K/347/272/277/345/233/276_/346/250/252/345/261/217.png +0 -0
  123. package/engine/examples/assets//347/273/210/347/253/257_for/345/276/252/347/216/257/346/261/202/345/222/214.png +0 -0
  124. package/engine/examples/assets//347/273/210/347/253/257_sum/346/261/202/345/222/214.png +0 -0
  125. package/engine/examples/assets//350/220/245/346/224/266/345/233/276_/347/253/226/345/261/217.png +0 -0
  126. package/engine/examples/assets//350/264/242/347/273/217/345/233/276/350/241/250_/346/250/252/345/261/217.png +0 -0
  127. package/engine/examples/t1_3b1b.json +19 -0
  128. package/engine/examples/t2_fullbleed_pulse.json +15 -0
  129. package/engine/examples/t2_keynote_ui.json +15 -0
  130. package/engine/examples/t3_finance_chart.json +29 -0
  131. package/engine/examples/y1_kurzgesagt.json +16 -0
  132. package/engine/examples/y2_vox.json +14 -0
  133. package/engine/examples/y3_whiteboard.json +17 -0
  134. package/engine/examples/y4_storytime.json +52 -0
  135. package/engine/examples/y5_kinetic_type.json +14 -0
  136. package/engine/index.html +42 -0
  137. package/engine/lib/THREE_LICENSE.txt +21 -0
  138. package/engine/lib/brush.js +149 -0
  139. package/engine/lib/camera.js +99 -0
  140. package/engine/lib/chart.js +152 -0
  141. package/engine/lib/collage.js +97 -0
  142. package/engine/lib/diagram.js +264 -0
  143. package/engine/lib/finish.js +70 -0
  144. package/engine/lib/fonts/AlfaSlabOne-400.woff +0 -0
  145. package/engine/lib/fonts/Anton-400.woff +0 -0
  146. package/engine/lib/fonts/ArchivoBlack-400.woff +0 -0
  147. package/engine/lib/fonts/Bangers-400.woff +0 -0
  148. package/engine/lib/fonts/Caveat-600.woff +0 -0
  149. package/engine/lib/fonts/Cinzel-400.woff +0 -0
  150. package/engine/lib/fonts/Cinzel-700.woff +0 -0
  151. package/engine/lib/fonts/CormorantGaramond-500.woff +0 -0
  152. package/engine/lib/fonts/CormorantGaramond-500i.woff +0 -0
  153. package/engine/lib/fonts/CormorantGaramond-700.woff +0 -0
  154. package/engine/lib/fonts/EBGaramond-400.woff +0 -0
  155. package/engine/lib/fonts/EBGaramond-400i.woff +0 -0
  156. package/engine/lib/fonts/EBGaramond-600.woff +0 -0
  157. package/engine/lib/fonts/Exo2-800i.woff +0 -0
  158. package/engine/lib/fonts/GochiHand-400.woff +0 -0
  159. package/engine/lib/fonts/IMFellEnglish-400.woff +0 -0
  160. package/engine/lib/fonts/IMFellEnglish-400i.woff +0 -0
  161. package/engine/lib/fonts/Inter-var.woff +0 -0
  162. package/engine/lib/fonts/JosefinSans-700.woff +0 -0
  163. package/engine/lib/fonts/Kalam-700.woff +0 -0
  164. package/engine/lib/fonts/LICENSES.md +40 -0
  165. package/engine/lib/fonts/LXGWWenKai-500.woff +0 -0
  166. package/engine/lib/fonts/LibreBaskerville-400.woff +0 -0
  167. package/engine/lib/fonts/LibreBaskerville-700.woff +0 -0
  168. package/engine/lib/fonts/LilitaOne-400.woff +0 -0
  169. package/engine/lib/fonts/Marcellus-400.woff +0 -0
  170. package/engine/lib/fonts/NotoSansSC-500.woff +0 -0
  171. package/engine/lib/fonts/NotoSansSC-700.woff +0 -0
  172. package/engine/lib/fonts/NotoSansSC-800.woff +0 -0
  173. package/engine/lib/fonts/NotoSansSC-900.woff +0 -0
  174. package/engine/lib/fonts/NotoSansSC-sub.woff +0 -0
  175. package/engine/lib/fonts/NotoSerifJP-600.woff +0 -0
  176. package/engine/lib/fonts/NotoSerifSC-sub.woff +0 -0
  177. package/engine/lib/fonts/OFL.txt +94 -0
  178. package/engine/lib/fonts/PlayfairDisplay-400i.woff +0 -0
  179. package/engine/lib/fonts/PlayfairDisplay-700.woff +0 -0
  180. package/engine/lib/fonts/PlayfairDisplay-700i.woff +0 -0
  181. package/engine/lib/fonts/Poppins-600.woff +0 -0
  182. package/engine/lib/fonts/Poppins-700.woff +0 -0
  183. package/engine/lib/fonts/Poppins-800.woff +0 -0
  184. package/engine/lib/fonts/PressStart2P-400.woff +0 -0
  185. package/engine/lib/fonts/Righteous-400.woff +0 -0
  186. package/engine/lib/fonts/RobotoCondensed-var.woff +0 -0
  187. package/engine/lib/fonts/Rye-400.woff +0 -0
  188. package/engine/lib/fonts/UnifrakturMaguntia-400.woff +0 -0
  189. package/engine/lib/fonts/cmunrm.woff +0 -0
  190. package/engine/lib/fonts/cmunti.woff +0 -0
  191. package/engine/lib/fonts/index.json +1 -0
  192. package/engine/lib/fonts.js +56 -0
  193. package/engine/lib/kit.js +91 -0
  194. package/engine/lib/media.js +118 -0
  195. package/engine/lib/medium.js +258 -0
  196. package/engine/lib/motion.js +111 -0
  197. package/engine/lib/paint.js +200 -0
  198. package/engine/lib/palettes.js +57 -0
  199. package/engine/lib/post.js +108 -0
  200. package/engine/lib/render.js +189 -0
  201. package/engine/lib/rig.js +390 -0
  202. package/engine/lib/rig_huashu.js +171 -0
  203. package/engine/lib/three.min.js +7 -0
  204. package/engine/lib/toon.js +186 -0
  205. package/engine/lib/typo.js +136 -0
  206. package/engine/lib/ui.js +141 -0
  207. package/engine/lib/util.js +92 -0
  208. package/engine/render.py +157 -0
  209. package/engine/scenes/01_cave.js +364 -0
  210. package/engine/scenes/02_egypt.js +524 -0
  211. package/engine/scenes/03_greek.js +448 -0
  212. package/engine/scenes/04_roman.js +555 -0
  213. package/engine/scenes/05_gothic.js +522 -0
  214. package/engine/scenes/06_renaissance.js +338 -0
  215. package/engine/scenes/08_impressionism.js +206 -0
  216. package/engine/scenes/09_postimp.js +183 -0
  217. package/engine/scenes/10_nouveau.js +334 -0
  218. package/engine/scenes/11_cubism.js +265 -0
  219. package/engine/scenes/12_bauhaus.js +214 -0
  220. package/engine/scenes/13_pop.js +269 -0
  221. package/engine/scenes/14_8bit.js +238 -0
  222. package/engine/scenes/15_raytrace.js +300 -0
  223. package/engine/scenes/16_2026.js +565 -0
  224. package/engine/scenes/17_ink.js +273 -0
  225. package/engine/scenes/18_klimt.js +227 -0
  226. package/engine/scenes/19_munch.js +153 -0
  227. package/engine/scenes/20_dunhuang.js +215 -0
  228. package/engine/scenes/21_kusama.js +124 -0
  229. package/engine/scenes/22_constructivism.js +205 -0
  230. package/engine/scenes/23_dali.js +221 -0
  231. package/engine/scenes/24_hopper.js +150 -0
  232. package/engine/scenes/25_ghibli.js +251 -0
  233. package/engine/scenes/26_vaporwave.js +191 -0
  234. package/engine/scenes/27_kirby.js +255 -0
  235. package/engine/scenes/28_monet.js +176 -0
  236. package/engine/scenes/29_seurat.js +104 -0
  237. package/engine/scenes/30_matisse.js +151 -0
  238. package/engine/scenes/31_haring.js +109 -0
  239. package/engine/scenes/32_rembrandt.js +217 -0
  240. package/engine/scenes/33_rubberhose.js +219 -0
  241. package/engine/scenes/34_shadowpuppet.js +195 -0
  242. package/engine/scenes/35_shinkai.js +197 -0
  243. package/engine/scenes/36_picasso_blue.js +123 -0
  244. package/engine/scenes/38_giotto.js +133 -0
  245. package/engine/scenes/39_piero.js +53 -0
  246. package/engine/scenes/40_raphael.js +96 -0
  247. package/engine/scenes/41_michelangelo.js +112 -0
  248. package/engine/scenes/42_guardi.js +70 -0
  249. package/engine/scenes/43_lorenzetti.js +145 -0
  250. package/engine/scenes/44_cortona.js +86 -0
  251. package/engine/scenes/45_renoir.js +86 -0
  252. package/engine/scenes/46_pissarro.js +82 -0
  253. package/engine/scenes/47_sisley.js +94 -0
  254. package/engine/scenes/48_gauguin.js +107 -0
  255. package/engine/scenes/49_chagall.js +60 -0
  256. package/engine/scenes/50_ma_yuan.js +131 -0
  257. package/engine/scenes/51_persian_miniature.js +149 -0
  258. package/engine/scenes/52_south_park.js +105 -0
  259. package/engine/scenes/53_pixar.js +60 -0
  260. package/engine/scenes/54_ghibli_lab.js +68 -0
  261. package/engine/scenes/55_dunhuang.js +161 -0
  262. package/engine/scenes/index.js +28 -0
  263. package/engine/spec_assets.py +76 -0
  264. package/engine/transitions.js +929 -0
  265. package/engine//346/227/266/344/273/243/344/275/234/350/200/205/350/247/204/350/214/203.md +49 -0
  266. package/lib/host.mjs +754 -0
  267. package/lib/render-bridge.mjs +543 -0
  268. package/lib/render-cli.mjs +98 -0
  269. package/lib/storyboard-lint.mjs +54 -0
  270. package/manifest.json +52 -0
  271. package/package.json +8 -4
  272. package/runtime/package.json +8 -0
  273. package/skills/biuart/SKILL.md +154 -0
  274. package/skills/biuart/references/01-/346/213/206/350/247/243.md +55 -0
  275. package/skills/biuart/references/02-/346/234/272/345/210/266.md +41 -0
  276. package/skills/biuart/references/03-/344/270/200/345/270/247/345/205/210/350/241/214/345/233/233/346/235/241/350/267/257/347/272/277.md +39 -0
  277. package/skills/biuart/references/04-/347/272/257/344/273/243/347/240/201/347/273/230/345/210/266.md +92 -0
  278. package/skills/biuart/references/05-/350/212/202/345/245/217/344/270/216/351/205/215/344/271/220.md +19 -0
  279. package/skills/biuart/references/06-/345/217/243/346/222/255/351/251/261/345/212/250/347/232/204/350/211/272/346/234/257/347/237/255/347/211/207.md +31 -0
  280. package/skills/biuart/references/07-/346/255/243/351/235/242/347/273/217/351/252/214.md +196 -0
  281. package/skills/biuart/references/08-/351/243/216/346/240/274/344/275/234/350/200/205/350/247/204/350/214/203.md +61 -0
  282. package/skills/biuart/references/09-/350/247/206/351/242/221/345/212/250/347/224/273/350/257/255/346/263/225.md +382 -0
  283. package/skills/biuart/references/10-/350/247/222/350/211/262.md +34 -0
  284. package/skills/biuart/references/11-/351/225/277/345/215/267/347/251/277/350/266/212/347/211/207.md +43 -0
  285. package/skills/biuart/references/12-/345/217/243/346/222/255/346/225/264/347/211/207/344/270/216/347/273/217/351/252/214/345/233/236/346/265/201.md +25 -0
  286. package/skills/biuart/references/13-/345/217/243/346/222/255/344/270/216/350/257/255/351/237/263/345/244/215/345/210/273.md +7 -0
  287. package/skills/biuart/references/15-/350/267/250/345/234/272/346/231/257/351/243/216/346/240/274/346/217/220/347/202/274.md +48 -0
  288. package/skills/biuart/references/16-/351/243/216/346/240/274/346/274/224/347/244/27295/345/210/206/345/215/217/350/256/256.md +103 -0
  289. package/skills/biuart/references/about-author.md +99 -0
  290. package/skills/biuart/references/capabilities.md +91 -0
  291. package/skills/biuart/references/compatibility.md +34 -0
  292. package/skills/biuart/references/images.md +97 -0
  293. package/skills/biuart/references/voice-model-review.md +18 -0
  294. package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t1_3b1b.md +122 -0
  295. package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t2_keynote_ui.md +117 -0
  296. package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t3_finance_chart.md +116 -0
  297. package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y1_kurzgesagt.md +193 -0
  298. package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y2_vox.md +195 -0
  299. package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y3_whiteboard.md +190 -0
  300. package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y4_storytime.md +166 -0
  301. package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y5_kinetic_type.md +158 -0
  302. package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y6_presenter_explainer.md +24 -0
  303. package/skills/biuart/references//345/217/243/346/222/255API.md +125 -0
  304. package/skills/biuart/references//350/211/262/346/235/277.md +38 -0
  305. package/skills/biuart/references//350/247/222/350/211/262/347/262/276/347/273/206/345/272/246.md +61 -0
  306. package/skills/biuart/references//351/225/234/345/244/264/350/241/250/346/250/241/346/235/277.md +80 -0
  307. package/skills/biuart/references//351/225/234/345/244/264/350/257/255/350/250/200.md +73 -0
  308. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/01_cave.md +46 -0
  309. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/02_egypt.md +64 -0
  310. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/03_greek.md +50 -0
  311. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/04_roman.md +99 -0
  312. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/05_gothic.md +32 -0
  313. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/06_renaissance.md +41 -0
  314. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/08_impressionism.md +34 -0
  315. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/09_postimp.md +17 -0
  316. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/10_nouveau.md +31 -0
  317. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/11_cubism.md +30 -0
  318. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/12_bauhaus.md +30 -0
  319. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/13_pop.md +29 -0
  320. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/14_8bit.md +27 -0
  321. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/15_raytrace.md +32 -0
  322. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/16_2026.md +55 -0
  323. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/17_ink.md +50 -0
  324. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/18_klimt.md +37 -0
  325. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/19_munch.md +42 -0
  326. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/20_dunhuang.md +49 -0
  327. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/21_kusama.md +32 -0
  328. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/22_constructivism.md +35 -0
  329. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/23_dali.md +29 -0
  330. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/24_hopper.md +30 -0
  331. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/25_ghibli.md +55 -0
  332. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/26_vaporwave.md +27 -0
  333. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/27_kirby.md +30 -0
  334. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/28_monet.md +39 -0
  335. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/29_seurat.md +31 -0
  336. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/30_matisse.md +26 -0
  337. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/31_haring.md +22 -0
  338. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/32_rembrandt.md +29 -0
  339. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/33_rubberhose.md +31 -0
  340. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/34_shadowpuppet.md +40 -0
  341. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/35_shinkai.md +34 -0
  342. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/36_picasso_blue.md +25 -0
  343. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/37_rick_morty.md +48 -0
  344. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/38_giotto.md +67 -0
  345. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/39_piero.md +59 -0
  346. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/40_raphael.md +65 -0
  347. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/41_michelangelo.md +65 -0
  348. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/42_guardi.md +65 -0
  349. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/43_lorenzetti.md +69 -0
  350. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/44_cortona.md +66 -0
  351. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/45_renoir.md +66 -0
  352. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/46_pissarro.md +66 -0
  353. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/47_sisley.md +67 -0
  354. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/48_gauguin.md +66 -0
  355. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/49_chagall.md +59 -0
  356. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/50_ma_yuan.md +68 -0
  357. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/51_persian_miniature.md +66 -0
  358. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/52_south_park.md +65 -0
  359. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/53_pixar.md +61 -0
  360. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/55_dunhuang.md +41 -0
  361. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/INDEX.md +89 -0
  362. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/_/350/275/254/345/234/272_/350/277/201/347/247/273/346/265/213/350/257/225.md +53 -0
  363. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/_/351/207/215/345/201/232/350/277/233/345/272/246.md +37 -0
  364. package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/_/351/237/263/350/275/250_/350/211/272/346/234/257/345/217/262/351/200/237/351/200/232.md +135 -0
  365. package/studio/app.js +380 -0
  366. package/studio/assert-panel-permit.mjs +67 -0
  367. package/studio/composer.css +465 -0
  368. package/studio/composer.js +480 -0
  369. package/studio/index.html +97 -0
  370. package/studio/optimize-prompt.mjs +84 -0
  371. package/studio/optimize-prompt.test.mjs +47 -0
  372. package/studio/recipes.mjs +87 -0
  373. package/studio/select-menu.js +450 -0
  374. package/studio/styles.css +71 -0
  375. package/studio/to-english-prompt.mjs +149 -0
  376. package/studio/to-english-prompt.test.mjs +72 -0
  377. package/README.md +0 -3
@@ -0,0 +1,300 @@
1
+ // 1993 早期光线追踪 CGI——纯代码(不用 3D 引擎)。
2
+ // 管线:①静态底(青绿墙+窗外粉紫夕阳远山,缓存)→ ②逐像素透视棋盘地面(2×2 超采样,缓存)
3
+ // → ③物体层(椅/玻璃桌/少女/猫)先「倒着」画一遍当地面反射(按各自接地线镜像、半透明、往下渐隐)→ ④正着画物体
4
+ // → ⑤道具(绿锥、铬球逐像素环境映射、紫环 48 颗球按深度排序拼成圆环并自转)→ ⑥镜头光晕(lighter 叠加)。
5
+ // 「90 年代塑料感」= 每个部件:底色 → 径向渐变(高光点亮、边缘压暗)→ 左侧青色环境反光 → 一颗硬边白色镜面高光。
6
+ SCENES['15_raytrace'] = (() => {
7
+ const W = 1920, H = 1080, P = PAINT, { clamp, lerp } = U;
8
+ const FLOOR_Y = 790, VP = [960, 480];
9
+ const SUN = [695, 225];
10
+ const rgba = (h, a) => P.rgb(P.hex(h), a);
11
+
12
+ // ---------- 塑料着色 ----------
13
+ // 球面感:(hx,hy) 高光中心,R 影响半径;dark 边缘压暗量
14
+ function plastic(c, path, base, hx, hy, R, { dark = 0.42, spec = 0.85, specR = 0.16, rim = true, specAng = -0.5 } = {}) {
15
+ c.fillStyle = base; c.fill(path);
16
+ c.save(); c.clip(path);
17
+ const g = c.createRadialGradient(hx, hy, 0, hx + R * 0.25, hy + R * 0.3, R);
18
+ g.addColorStop(0, 'rgba(255,255,255,.55)'); g.addColorStop(0.28, 'rgba(255,255,255,.06)'); g.addColorStop(0.62, 'rgba(0,0,0,0)'); g.addColorStop(1, `rgba(10,0,30,${dark})`);
19
+ c.fillStyle = g; c.fillRect(hx - R * 3, hy - R * 3, R * 6, R * 6);
20
+ if (rim) { c.globalCompositeOperation = 'lighter'; c.lineWidth = R * 0.18; c.strokeStyle = 'rgba(70,150,150,.28)'; c.translate(-R * 0.04, 0); c.stroke(path); c.globalCompositeOperation = 'source-over'; }
21
+ c.restore();
22
+ if (spec) { c.save(); c.clip(path); c.fillStyle = `rgba(255,255,255,${spec})`; c.beginPath(); c.ellipse(hx, hy, R * specR, R * specR * 0.55, specAng, 0, 7); c.fill(); c.restore(); }
23
+ }
24
+ // 圆柱感:沿 A→B 的肢体,渐变横跨宽度方向
25
+ function cyl(c, path, base, A, B, w, { spec = 0.7 } = {}) {
26
+ c.fillStyle = base; c.fill(path);
27
+ const a = Math.atan2(B[1] - A[1], B[0] - A[0]), nx = Math.cos(a + Math.PI / 2), ny = Math.sin(a + Math.PI / 2);
28
+ const M = [(A[0] + B[0]) / 2, (A[1] + B[1]) / 2];
29
+ const s = ny < 0 ? -1 : 1; // 让渐变从「上方」到「下方」
30
+ const g = c.createLinearGradient(M[0] - nx * s * w / 2, M[1] - ny * s * w / 2, M[0] + nx * s * w / 2, M[1] + ny * s * w / 2);
31
+ g.addColorStop(0, 'rgba(10,0,30,.25)'); g.addColorStop(0.22, 'rgba(255,255,255,.5)'); g.addColorStop(0.34, 'rgba(255,255,255,.08)'); g.addColorStop(0.7, 'rgba(0,0,0,.05)'); g.addColorStop(1, 'rgba(10,0,30,.45)');
32
+ c.save(); c.clip(path); c.fillStyle = g; c.fillRect(Math.min(A[0], B[0]) - w * 2, Math.min(A[1], B[1]) - w * 2, Math.abs(B[0] - A[0]) + w * 4, Math.abs(B[1] - A[1]) + w * 4);
33
+ if (spec) { c.strokeStyle = `rgba(255,255,255,${spec})`; c.lineWidth = w * 0.09; c.lineCap = 'round'; const o = w * 0.22 * s; c.beginPath(); c.moveTo(lerp(A[0], B[0], .2) - nx * o, lerp(A[1], B[1], .2) - ny * o); c.lineTo(lerp(A[0], B[0], .75) - nx * o, lerp(A[1], B[1], .75) - ny * o); c.stroke(); }
34
+ c.restore();
35
+ }
36
+
37
+ // ---------- 静态底:墙、踢脚线、窗 ----------
38
+ function background(g) {
39
+ const wg = g.createRadialGradient(560, 260, 50, 700, 400, 1500); wg.addColorStop(0, '#7dbcb9'); wg.addColorStop(0.45, '#64a6a6'); wg.addColorStop(1, '#3f8285');
40
+ g.fillStyle = wg; g.fillRect(0, 0, W, FLOOR_Y);
41
+ // 窗的投影(右下偏移、软边)
42
+ g.save(); g.filter = 'blur(10px)'; g.fillStyle = 'rgba(20,60,70,.45)'; g.fillRect(372, 140, 450, 452); g.restore();
43
+ // 窗外:粉紫夕阳
44
+ g.save(); g.beginPath(); g.rect(375, 135, 410, 410); g.clip();
45
+ const sg = g.createLinearGradient(0, 135, 0, 480); sg.addColorStop(0, '#a24cc4'); sg.addColorStop(0.45, '#df62ae'); sg.addColorStop(0.8, '#f5a08a'); sg.addColorStop(1, '#f8c070');
46
+ g.fillStyle = sg; g.fillRect(375, 135, 410, 410);
47
+ // 远山(两层)+雪顶+线框网格
48
+ const mtn = (pts, col, snow) => {
49
+ g.beginPath(); g.moveTo(375, 545); pts.forEach(p => g.lineTo(...p)); g.lineTo(785, 545); g.closePath();
50
+ const mg = g.createLinearGradient(0, 340, 0, 545); mg.addColorStop(0, col[0]); mg.addColorStop(1, col[1]); g.fillStyle = mg; g.fill();
51
+ g.save(); g.clip(); g.strokeStyle = 'rgba(255,170,230,.45)'; g.lineWidth = 1.5;
52
+ for (let x = 375; x < 785; x += 28) { g.beginPath(); g.moveTo(x, 330); g.lineTo(x, 545); g.stroke(); }
53
+ for (let y = 360; y < 545; y += 26) { g.beginPath(); g.moveTo(375, y); g.lineTo(785, y); g.stroke(); }
54
+ g.fillStyle = '#fbeef6'; snow.forEach(([x, y, w]) => { g.beginPath(); g.moveTo(x - w, y + w * 0.9); g.lineTo(x, y); g.lineTo(x + w, y + w * 0.9); g.lineTo(x + w * 0.4, y + w * 0.6); g.lineTo(x, y + w * 0.95); g.lineTo(x - w * 0.5, y + w * 0.6); g.closePath(); g.fill(); });
55
+ g.restore();
56
+ };
57
+ mtn([[375, 380], [430, 352], [462, 345], [520, 400], [585, 440], [640, 420], [700, 390], [760, 395], [785, 400]], ['#b06ab8', '#8a50a8'], [[462, 345, 30], [700, 390, 22], [430, 352, 18]]);
58
+ mtn([[375, 470], [470, 430], [560, 470], [610, 440], [690, 480], [785, 440]], ['#8f5aa8', '#6c3f94'], [[610, 440, 18], [470, 430, 16]]);
59
+ g.restore();
60
+ // 白窗框(立体:亮边+暗边)
61
+ const frame = (x, y, w, h) => { const fg = g.createLinearGradient(x, y, x + w, y + h); fg.addColorStop(0, '#ffffff'); fg.addColorStop(1, '#d6dde0'); g.fillStyle = fg; g.fillRect(x, y, w, h); };
62
+ frame(355, 118, 445, 18); frame(355, 118, 20, 437); frame(783, 118, 17, 437); frame(355, 538, 445, 17); frame(571, 135, 14, 405); frame(375, 330, 410, 14);
63
+ g.fillStyle = 'rgba(0,40,60,.25)'; g.fillRect(375, 136, 410, 4); g.fillRect(375, 136, 4, 402);
64
+ // 窗台
65
+ const sl = g.createLinearGradient(0, 555, 0, 572); sl.addColorStop(0, '#ffffff'); sl.addColorStop(1, '#c9d2d6'); g.fillStyle = sl; g.fillRect(330, 555, 490, 16);
66
+ g.fillStyle = 'rgba(20,60,70,.35)'; g.fillRect(340, 571, 490, 12);
67
+ // 踢脚线
68
+ const bb = g.createLinearGradient(0, 760, 0, FLOOR_Y); bb.addColorStop(0, '#ffffff'); bb.addColorStop(1, '#d9dde0'); g.fillStyle = bb; g.fillRect(0, 760, W, FLOOR_Y - 760);
69
+ g.fillStyle = 'rgba(0,40,50,.25)'; g.fillRect(0, 756, W, 4);
70
+ }
71
+ // ---------- 透视棋盘地面(逐像素、2×2 超采样) ----------
72
+ function floor(g) {
73
+ const im = g.createImageData(W, H), d = im.data, TX = 0.27, TZ = 0.00029;
74
+ const A = P.hex('#d9dadf'), B = P.hex('#3e5d62');
75
+ for (let y = FLOOR_Y; y < H; y++) for (let x = 0; x < W; x++) {
76
+ let s = 0;
77
+ for (let k = 0; k < 4; k++) {
78
+ const yy = y + (k >> 1) * 0.5 + 0.25, xx = x + (k & 1) * 0.5 + 0.25, dy = yy - VP[1];
79
+ const X = (xx - VP[0]) / dy, Z = 1 / dy;
80
+ s += ((Math.floor(X / TX + 0.5) + Math.floor(Z / TZ)) & 1);
81
+ }
82
+ const q = s / 4, i = (y * W + x) * 4, fog = clamp(1 - (y - FLOOR_Y) / 140) * 0.35;
83
+ for (let ch = 0; ch < 3; ch++) d[i + ch] = lerp(lerp(A[ch], B[ch], q), [150, 190, 192][ch], fog);
84
+ d[i + 3] = 255;
85
+ }
86
+ g.putImageData(im, 0, 0);
87
+ // 地面上的环境光:窗光在地上的亮斑
88
+ const lg = g.createRadialGradient(560, 900, 20, 560, 900, 520); lg.addColorStop(0, 'rgba(255,200,230,.22)'); lg.addColorStop(1, 'rgba(255,200,230,0)');
89
+ g.fillStyle = lg; g.fillRect(0, FLOOR_Y, W, H - FLOOR_Y);
90
+ }
91
+
92
+ // ---------- 家具 ----------
93
+ function chair(c) {
94
+ const wood = '#b77a40', post = (x, y0, y1, w) => { const p = new Path2D(); p.rect(x, y0, w, y1 - y0); cyl(c, p, wood, [x + w / 2, y0], [x + w / 2, y1], w, { spec: 0.5 }); grain(c, x, y0, w, y1 - y0); };
95
+ post(1478, 455, 912, 22); post(1442, 470, 760, 18);
96
+ for (let k = 0; k < 4; k++) { const p = new Path2D(); p.rect(1444, 500 + k * 52, 52, 12); cyl(c, p, '#a86a34', [1444, 506 + k * 52], [1496, 506 + k * 52], 12, { spec: 0.4 }); }
97
+ const seat = new Path2D(); seat.rect(1290, 738, 214, 22); cyl(c, seat, wood, [1290, 749], [1504, 749], 22); grain(c, 1290, 738, 214, 22);
98
+ post(1312, 760, 900, 18);
99
+ }
100
+ function grain(c, x, y, w, h) { // 木纹:细噪声线
101
+ c.save(); c.beginPath(); c.rect(x, y, w, h); c.clip(); c.strokeStyle = 'rgba(90,45,15,.35)'; c.lineWidth = 1.2;
102
+ const r = U.rng((x * 7 + y) | 0), vert = h > w;
103
+ for (let k = 0; k < (vert ? w : h) / 3; k++) { const o = r() * (vert ? w : h); c.beginPath(); for (let s = 0; s <= 20; s++) { const q = s / 20, n = P.noise(o * 0.3 + k, q * 4) * 3; vert ? (s ? c.lineTo(x + o + n, y + q * h) : c.moveTo(x + o + n, y + q * h)) : (s ? c.lineTo(x + q * w, y + o + n) : c.moveTo(x + q * w, y + o + n)); } c.stroke(); }
104
+ c.restore();
105
+ }
106
+ function table(c) {
107
+ // 大理石柱:竖向凹槽 + 圆柱明暗
108
+ const col = new Path2D(); col.rect(984, 664, 52, 212); cyl(c, col, '#efe6ea', [984, 770], [1036, 770], 52, { spec: 0 });
109
+ c.save(); c.clip(col); c.strokeStyle = 'rgba(120,100,140,.35)'; c.lineWidth = 2; for (let x = 990; x < 1036; x += 9) { c.beginPath(); c.moveTo(x, 664); c.lineTo(x, 876); c.stroke(); }
110
+ c.strokeStyle = 'rgba(150,130,170,.25)'; c.lineWidth = 1.5; c.beginPath(); for (let s = 0; s < 30; s++) c.lineTo(990 + P.noise(s * 0.3, 2) * 30 + 20, 664 + s * 7.3); c.stroke(); c.restore();
111
+ const lg = c.createLinearGradient(984, 0, 1036, 0); lg.addColorStop(0, 'rgba(255,255,255,0)'); lg.addColorStop(0.3, 'rgba(255,255,255,.6)'); lg.addColorStop(0.45, 'rgba(255,255,255,0)'); c.fillStyle = lg; c.fillRect(984, 664, 52, 212);
112
+ // 底座
113
+ const base = new Path2D(); base.ellipse(1010, 884, 56, 14, 0, 0, 7); base.rect(954, 872, 112, 12); plastic(c, base, '#e9e1e6', 985, 876, 80, { spec: 0.6, rim: false });
114
+ const cap = new Path2D(); cap.ellipse(1010, 668, 40, 9, 0, 0, 7); plastic(c, cap, '#efe6ea', 995, 664, 50, { spec: 0, rim: false });
115
+ }
116
+ function glassTop(c, t) {
117
+ // 玻璃桌面:半透明绿 + 厚边 + 高光条 + 一道会滑动的反光
118
+ c.save();
119
+ const top = new Path2D(); top.ellipse(1010, 650, 192, 20, 0, 0, 7);
120
+ const edge = new Path2D(); edge.ellipse(1010, 660, 192, 20, 0, 0, Math.PI); edge.lineTo(818, 650); edge.ellipse(1010, 650, 192, 20, 0, Math.PI, 0, true); edge.closePath();
121
+ c.fillStyle = 'rgba(40,140,90,.75)'; c.fill(edge);
122
+ const tg = c.createLinearGradient(818, 630, 1202, 670); tg.addColorStop(0, 'rgba(140,230,190,.55)'); tg.addColorStop(0.5, 'rgba(70,170,120,.45)'); tg.addColorStop(1, 'rgba(30,110,80,.6)');
123
+ c.fillStyle = tg; c.fill(top);
124
+ c.strokeStyle = 'rgba(220,255,240,.8)'; c.lineWidth = 2; c.stroke(top);
125
+ c.clip(top); const sx = 860 + ((t * 260) % 420);
126
+ c.fillStyle = 'rgba(255,255,255,.35)'; c.beginPath(); c.moveTo(sx, 630); c.lineTo(sx + 40, 630); c.lineTo(sx + 10, 672); c.lineTo(sx - 30, 672); c.fill();
127
+ c.restore();
128
+ }
129
+ // ---------- 角色(塑料人偶) ----------
130
+ const SK = '#f2c39c', HAIR = '#f6c624', RED = '#e3283c', BLUE = '#2c55d8';
131
+ function girl(c, G) {
132
+ const A = G.A;
133
+ plastic(c, G.farSleeve, '#b81f30', 1300, 560, 140, { spec: 0.4 });
134
+ plastic(c, G.farHand, SK, 1170, 608, 50, { spec: 0.7 });
135
+ // 腿:牛仔蓝塑料圆柱
136
+ const hip = G.hipSeat, knee = [1222, 722], ank = [1212, 870];
137
+ const th2 = RIG.taper([hip[0] + 14, hip[1] - 4], [knee[0] + 30, knee[1] - 8], 84, 70); cyl(c, th2, '#1e3c9c', hip, knee, 84, { spec: 0.3 });
138
+ const sh2 = RIG.taper([knee[0] + 30, knee[1] - 8], [ank[0] + 30, ank[1]], 62, 52); cyl(c, sh2, '#1e3c9c', knee, ank, 62, { spec: 0.3 });
139
+ const th = RIG.taper(hip, knee, 92, 78), sh = RIG.taper(knee, ank, 72, 58);
140
+ cyl(c, sh, BLUE, knee, ank, 72); cyl(c, th, BLUE, hip, knee, 92);
141
+ const kneeBall = new Path2D(); kneeBall.arc(knee[0], knee[1], 40, 0, 7); plastic(c, kneeBall, BLUE, knee[0] - 14, knee[1] - 16, 60, { spec: 0.6 });
142
+ const shoe = RIG.smooth([[1150, 868], [1238, 860], [1252, 902], [1124, 906], [1116, 890]]); plastic(c, shoe, '#5a2c1c', 1160, 872, 80, { spec: 0.8 });
143
+ // 身体
144
+ plastic(c, G.torso, RED, 1318, 478, 200, { spec: 0.75, specR: 0.1 });
145
+ plastic(c, G.neck, SK, 1296, 420, 40, { spec: 0 });
146
+ // 头发(后)、脸、刘海——塑料头发要有几条亮带
147
+ if (G.hairDown) plastic(c, G.hairDown, HAIR, 1380, 470, 140, { spec: 0.5 });
148
+ plastic(c, G.hairBack, HAIR, 1330, 320, 130, { spec: 0.8 });
149
+ plastic(c, G.face, SK, 1268, 340, 95, { spec: 0.55, specR: 0.12 });
150
+ c.fillStyle = 'rgba(240,120,120,.22)'; c.beginPath(); c.arc(G.cheek[0], G.cheek[1], 10, 0, 7); c.fill();
151
+ const ear = new Path2D(); ear.ellipse(G.ear[0], G.ear[1], 9, 13, 0.2, 0, 7); plastic(c, ear, SK, G.ear[0] - 3, G.ear[1] - 4, 18, { spec: 0 });
152
+ plastic(c, G.bangs, HAIR, 1282, 306, 80, { spec: 0.9, specR: 0.2 });
153
+ c.save(); c.lineCap = 'round'; G.hairLines.forEach((h, k) => { c.strokeStyle = 'rgba(255,255,230,.55)'; c.lineWidth = 5 - k; c.stroke(h); c.strokeStyle = 'rgba(180,120,0,.35)'; c.lineWidth = 2; c.translate(0, 8); c.stroke(h); c.translate(0, -8); }); c.restore();
154
+ // 眼(蓝色玻璃珠)、眉、唇
155
+ const ey = G.eye; c.fillStyle = '#fff'; c.beginPath(); c.ellipse(ey.x, ey.y, 6.5, 7, 0, 0, 7); c.fill();
156
+ if (G.blink) { c.strokeStyle = '#4a2a1a'; c.lineWidth = 2.5; c.stroke(G.lid); }
157
+ else { const ig = c.createRadialGradient(ey.x - 2, ey.y - 1, 1, ey.x - 1, ey.y + 1, 6); ig.addColorStop(0, '#6fa0ff'); ig.addColorStop(1, '#1a2c8a'); c.fillStyle = ig; c.beginPath(); c.arc(ey.x - 1.5, ey.y + 1, 5, 0, 7); c.fill(); c.fillStyle = '#fff'; c.beginPath(); c.arc(ey.x - 3, ey.y - 1.5, 1.6, 0, 7); c.fill(); c.strokeStyle = '#4a2a1a'; c.lineWidth = 2.2; c.stroke(G.lid); }
158
+ c.strokeStyle = '#b8862a'; c.lineWidth = 2.6; c.stroke(G.brow);
159
+ c.fillStyle = '#d0505a'; c.beginPath(); c.moveTo(...G.lips[0]); c.lineTo(...G.lips[1]); c.lineTo(...G.lips[2]); c.closePath(); c.fill();
160
+ // 近侧手臂(圆柱+球关节)、杯子、手
161
+ const S = A.shoulder, E = A.elbow, Hd = A.hand;
162
+ cyl(c, G.upperArm, RED, S, E, 54); cyl(c, G.foreArm, RED, E, Hd, 40);
163
+ const sb = new Path2D(); sb.arc(S[0], S[1], 30, 0, 7); plastic(c, sb, RED, S[0] - 10, S[1] - 12, 44, { spec: 0.8 });
164
+ // 杯子:白瓷,椭圆口+高光
165
+ const u = G.cup; c.save(); c.translate(u.x, u.y); c.rotate(u.tilt);
166
+ const body = new Path2D(); body.moveTo(-u.w / 2, 0); body.lineTo(-u.w * 0.42, u.h); body.quadraticCurveTo(0, u.h * 1.12, u.w * 0.42, u.h); body.lineTo(u.w / 2, 0); body.closePath();
167
+ c.strokeStyle = '#e8e8f0'; c.lineWidth = 7; c.beginPath(); c.arc(u.w * 0.55, u.h * 0.4, u.h * 0.26, -1.2, 1.4); c.stroke();
168
+ plastic(c, body, '#f4f2f8', -u.w * 0.2, u.h * 0.3, 40, { spec: 0.9, rim: false });
169
+ c.fillStyle = '#6a3a1a'; c.beginPath(); c.ellipse(0, 0, u.w / 2, u.h * 0.14, 0, 0, 7); c.fill(); c.strokeStyle = '#fff'; c.lineWidth = 2; c.stroke();
170
+ c.restore();
171
+ plastic(c, G.hand, SK, Hd[0] - 5, Hd[1] - 6, 26, { spec: 0.8 });
172
+ }
173
+ function cat(c, K, t) {
174
+ const O = '#ee8f2e', Wt = '#f6f2ee';
175
+ // 尾巴:粗管+高光线
176
+ c.save(); c.lineCap = 'round'; c.strokeStyle = '#b35f14'; c.lineWidth = K.tailW + 4; c.stroke(K.tail); c.strokeStyle = O; c.lineWidth = K.tailW; c.stroke(K.tail);
177
+ c.strokeStyle = 'rgba(255,240,200,.75)'; c.lineWidth = 4; c.translate(-2, -7); c.stroke(K.tail); c.restore();
178
+ const tip = K.tailPts[K.tailPts.length - 1]; const tp = new Path2D(); tp.arc(tip[0], tip[1], K.tailW / 2 + 1, 0, 7); plastic(c, tp, Wt, tip[0] - 4, tip[1] - 5, 20);
179
+ const body = RIG.smooth(K.bodyPts); // RIG 的猫身是折线,塑料质感要先 Catmull-Rom 平滑
180
+ plastic(c, body, O, 500, 735, 230, { spec: 0.8, specR: 0.09 });
181
+ c.save(); c.clip(body); plastic(c, K.white, Wt, 585, 720, 120, { spec: 0.5, rim: false }); c.restore();
182
+ c.save(); c.clip(body); const wg = c.createLinearGradient(560, 700, 650, 860); wg.addColorStop(0, 'rgba(0,0,0,0)'); wg.addColorStop(1, 'rgba(40,0,60,.3)'); c.fillStyle = wg; c.fillRect(540, 680, 140, 220); c.restore();
183
+ c.save(); c.clip(body); c.filter = 'blur(2px)'; c.strokeStyle = 'rgba(170,70,10,.5)'; c.lineWidth = 12; c.lineCap = 'round'; K.stripes.slice(3).forEach(s => { c.beginPath(); c.moveTo(...s[0]); c.lineTo(...s[1]); c.stroke(); }); c.restore();
184
+ K.legs.forEach((l, k) => { plastic(c, l, Wt, 578 + k * 44, 770, 110, { spec: 0.7, specR: 0.08, dark: 0.5 }); const pw = new Path2D(); pw.ellipse(585 + k * 50, 892, 25, 14, 0, 0, 7); plastic(c, pw, Wt, 578 + k * 50, 884, 34, { spec: 0.8, dark: 0.5 }); c.strokeStyle = 'rgba(120,90,110,.5)'; c.lineWidth = 2; [-8, 8].forEach(o => { c.beginPath(); c.moveTo(585 + k * 50 + o, 888); c.lineTo(585 + k * 50 + o, 903); c.stroke(); }); });
185
+ plastic(c, K.head, O, 580, 598, 100, { spec: 0.9, specR: 0.13 });
186
+ c.save(); c.clip(K.head); const mz = new Path2D(); mz.ellipse(K.nose[0] - 14, K.nose[1] + 16, 27, 19, 0, 0, 7); plastic(c, mz, Wt, K.nose[0] - 20, K.nose[1] + 8, 34, { spec: 0.4, rim: false, dark: 0.3 });
187
+ c.filter = 'blur(1.5px)'; c.strokeStyle = 'rgba(170,70,10,.5)'; c.lineWidth = 8; c.lineCap = 'round'; K.stripes.slice(0, 3).forEach(s => { c.beginPath(); c.moveTo(...s[0]); c.lineTo(...s[1]); c.stroke(); }); c.restore();
188
+ c.fillStyle = '#f2a0a8'; K.earInner.forEach(e => { c.beginPath(); e.forEach((p, i) => i ? c.lineTo(...p) : c.moveTo(...p)); c.fill(); });
189
+ c.fillStyle = '#e66a7a'; c.beginPath(); c.arc(K.nose[0], K.nose[1], 6, 0, 7); c.fill();
190
+ c.strokeStyle = 'rgba(255,255,255,.85)'; c.lineWidth = 1.6; K.whiskers.forEach(w => { c.beginPath(); c.moveTo(...w[0]); c.lineTo(...w[1]); c.stroke(); });
191
+ // 猫眼:发绿光(lighter 叠加、随时间脉动)
192
+ const pulse = 0.75 + 0.25 * Math.sin(t * 18);
193
+ K.eyes.forEach(e => {
194
+ c.fillStyle = '#0a3a10'; c.beginPath(); c.arc(e.x, e.y, 10, 0, 7); c.fill();
195
+ c.save(); c.globalCompositeOperation = 'lighter';
196
+ const gg = c.createRadialGradient(e.x, e.y, 0, e.x, e.y, 46 * pulse); gg.addColorStop(0, 'rgba(200,255,200,1)'); gg.addColorStop(0.25, 'rgba(80,255,120,.8)'); gg.addColorStop(1, 'rgba(40,255,90,0)');
197
+ c.fillStyle = gg; c.beginPath(); c.arc(e.x, e.y, 46 * pulse, 0, 7); c.fill(); c.restore();
198
+ });
199
+ }
200
+
201
+ // ---------- 道具:绿锥、铬球(逐像素环境映射)、紫环(自转) ----------
202
+ function cone(c) {
203
+ const p = new Path2D(); p.moveTo(1592, 612); p.lineTo(1660, 780); p.ellipse(1592, 780, 68, 14, 0, 0, Math.PI); p.closePath();
204
+ c.fillStyle = '#25835a'; c.fill(p);
205
+ c.save(); c.clip(p); const g = c.createLinearGradient(1524, 0, 1660, 0); g.addColorStop(0, 'rgba(0,30,20,.35)'); g.addColorStop(0.3, 'rgba(160,255,200,.55)'); g.addColorStop(0.4, 'rgba(255,255,255,.15)'); g.addColorStop(1, 'rgba(0,20,10,.55)');
206
+ c.fillStyle = g; c.fillRect(1520, 600, 150, 200); c.restore();
207
+ }
208
+ function chromeSphere(c, t, cx, cy, r) {
209
+ const sc = P.scratch('rt_sph'), g = sc.getContext('2d'), D = r * 2 + 2;
210
+ const im = g.createImageData(D, D), d = im.data, rot = t * 4.5;
211
+ for (let y = 0; y < D; y++) for (let x = 0; x < D; x++) {
212
+ const nx = (x - r) / r, ny = (y - r) / r, q = nx * nx + ny * ny; if (q > 1) continue;
213
+ const nz = Math.sqrt(1 - q), i = (y * D + x) * 4;
214
+ // 反射方向 R = 2(N·V)N - V, V=(0,0,1)
215
+ const rx = 2 * nz * nx, ry = 2 * nz * ny, rz = 2 * nz * nz - 1;
216
+ let col;
217
+ if (ry > 0.05) { // 往下看到棋盘
218
+ const u = rx / ry * 1.6 + rot, v = rz / ry * 1.6; const ck = (Math.floor(u * 2) + Math.floor(v * 2)) & 1; col = ck ? [40, 60, 70] : [225, 225, 235];
219
+ } else { const k = clamp(-ry * 1.4); col = [lerp(245, 160, k), lerp(160, 80, k), lerp(170, 200, k)]; if (Math.abs(rx - 0.4) < 0.08 && ry < -0.2 && ry > -0.7) col = [255, 255, 255]; }
220
+ const f = 0.35 + 0.65 * Math.pow(1 - nz, 0.3) * 0.5 + 0.3; // 边缘更亮(菲涅尔)
221
+ d[i] = col[0] * f + 20; d[i + 1] = col[1] * f + 20; d[i + 2] = col[2] * f + 25; d[i + 3] = 255;
222
+ }
223
+ g.clearRect(0, 0, D + 4, D + 4); g.putImageData(im, 0, 0);
224
+ c.drawImage(sc, 0, 0, D, D, cx - r - 1, cy - r - 1, D, D);
225
+ c.save(); c.globalCompositeOperation = 'lighter'; const hg = c.createRadialGradient(cx - r * 0.38, cy - r * 0.45, 0, cx - r * 0.38, cy - r * 0.45, r * 0.3); hg.addColorStop(0, 'rgba(255,255,255,1)'); hg.addColorStop(1, 'rgba(255,255,255,0)'); c.fillStyle = hg; c.beginPath(); c.arc(cx - r * 0.38, cy - r * 0.45, r * 0.3, 0, 7); c.fill(); c.restore();
226
+ }
227
+ function torus(c, t, cx, cy, R, rr) {
228
+ const th = t * 7, tilt = 0.35, out = [], N = 140;
229
+ for (let k = 0; k < N; k++) {
230
+ const ph = k / N * Math.PI * 2, x0 = R * Math.cos(ph), y0 = R * Math.sin(ph);
231
+ const X = x0 * Math.cos(th), Z = x0 * Math.sin(th);
232
+ const Y = y0 * Math.cos(tilt) - Z * Math.sin(tilt), Z2 = y0 * Math.sin(tilt) + Z * Math.cos(tilt);
233
+ out.push([cx + X, cy + Y, Z2]);
234
+ }
235
+ out.sort((a, b) => a[2] - b[2]);
236
+ // 先画一层暗色底让球之间连成管,再逐颗加高光
237
+ out.forEach(([x, y]) => { c.fillStyle = '#7a1aa0'; c.beginPath(); c.arc(x, y, rr, 0, 7); c.fill(); });
238
+ out.forEach(([x, y, z]) => {
239
+ const g = c.createRadialGradient(x - rr * 0.35, y - rr * 0.4, 1, x, y, rr); const l = 0.5 + 0.5 * z / R;
240
+ g.addColorStop(0, `rgba(255,${190 + l * 50},255,1)`); g.addColorStop(0.3, '#d850f6'); g.addColorStop(0.75, '#9a28c4'); g.addColorStop(1, 'rgba(110,20,150,0)');
241
+ c.fillStyle = g; c.beginPath(); c.arc(x, y, rr * 0.92, 0, 7); c.fill();
242
+ });
243
+ }
244
+ function props(c, t, mirror) {
245
+ // mirror: 画反射时各自按接地线镜像
246
+ const M = (yC, fn) => { c.save(); if (mirror) { c.translate(0, 2 * yC); c.scale(1, -1); } fn(); c.restore(); };
247
+ M(780, () => cone(c));
248
+ M(846, () => torus(c, t, 1818, 772, 52, 22));
249
+ M(800, () => chromeSphere(c, t, 1712, 748, 52));
250
+ }
251
+
252
+ // ---------- 镜头光晕 ----------
253
+ function flare(c, t) {
254
+ c.save(); c.globalCompositeOperation = 'lighter';
255
+ const pul = 1 + 0.08 * Math.sin(t * 23);
256
+ const glow = c.createRadialGradient(...SUN, 0, ...SUN, 170 * pul); glow.addColorStop(0, 'rgba(255,255,255,1)'); glow.addColorStop(0.15, 'rgba(255,240,250,.9)'); glow.addColorStop(0.4, 'rgba(255,170,220,.25)'); glow.addColorStop(1, 'rgba(255,150,220,0)');
257
+ c.fillStyle = glow; c.beginPath(); c.arc(...SUN, 170 * pul, 0, 7); c.fill();
258
+ // 星芒(缓慢旋转)
259
+ const rot = t * 1.6;
260
+ for (let k = 0; k < 12; k++) { const a = rot + k / 12 * Math.PI * 2, L = (k % 2 ? 70 : 120) * pul; const g = c.createLinearGradient(SUN[0], SUN[1], SUN[0] + Math.cos(a) * L, SUN[1] + Math.sin(a) * L); g.addColorStop(0, 'rgba(255,255,255,.8)'); g.addColorStop(1, 'rgba(255,255,255,0)'); c.strokeStyle = g; c.lineWidth = 2.5; c.beginPath(); c.moveTo(...SUN); c.lineTo(SUN[0] + Math.cos(a) * L, SUN[1] + Math.sin(a) * L); c.stroke(); }
261
+ // 水平长条光
262
+ const hs = c.createLinearGradient(220, 0, 1180, 0); hs.addColorStop(0, 'rgba(255,255,255,0)'); hs.addColorStop(0.5, `rgba(255,255,255,${0.75 * pul})`); hs.addColorStop(1, 'rgba(255,255,255,0)');
263
+ c.fillStyle = hs; c.fillRect(220, SUN[1] - 2, 960, 4);
264
+ c.strokeStyle = 'rgba(255,255,255,.18)'; c.lineWidth = 3; c.beginPath(); c.arc(...SUN, 150, 0, 7); c.stroke();
265
+ // 鬼影:沿 太阳→画面中心 的直线排布,随时间轻微滑动
266
+ const C0 = [960, 540], dx = C0[0] - SUN[0], dy = C0[1] - SUN[1], sl = Math.sin(t * 5) * 0.03;
267
+ [[0.62, 58, 'rgba(180,255,240,.16)', 0], [0.95, 17, 'rgba(160,255,255,.4)', 6], [1.25, 40, 'rgba(255,200,255,.12)', 6], [1.55, 34, 'rgba(200,255,230,.18)', 0], [0.8, 12, 'rgba(255,255,200,.3)', 6]].forEach(([k, r, col, sides]) => {
268
+ const x = SUN[0] + dx * (k + sl), y = SUN[1] + dy * (k + sl); c.fillStyle = col; c.beginPath();
269
+ if (sides) for (let i = 0; i < sides; i++) { const a = i / sides * Math.PI * 2 + 0.3; c.lineTo(x + Math.cos(a) * r, y + Math.sin(a) * r); } else c.arc(x, y, r, 0, 7);
270
+ c.closePath(); c.fill();
271
+ });
272
+ c.restore();
273
+ }
274
+
275
+ return {
276
+ draw(c, lt, t) {
277
+ const ch = P.choreo(lt, t);
278
+ c.drawImage(P.cached('rt_bg', W, H, background), 0, 0);
279
+ c.drawImage(P.cached('rt_floor', W, H, floor), 0, FLOOR_Y, W, H - FLOOR_Y, 0, FLOOR_Y, W, H - FLOOR_Y);
280
+ const K = RIG.cat({ tail: ch.tail, blink: 0, breathe: ch.breathe });
281
+ const G = RIG.girl({ cup: ch.cup, sip: ch.sip, hair: 'long', breathe: ch.breathe }); G.blink = ch.blink;
282
+ // 物体层
283
+ const L = P.scratch('rt_obj'), lg = L.getContext('2d'); lg.clearRect(0, 0, W, H);
284
+ chair(lg); table(lg); glassTop(lg, t); girl(lg, G); cat(lg, K, t);
285
+ // 反射:物体层按接地线 y=905 镜像,往下渐隐
286
+ c.save(); c.beginPath(); c.rect(0, FLOOR_Y, W, H - FLOOR_Y); c.clip();
287
+ c.globalAlpha = 0.34; c.translate(0, 2 * 906); c.scale(1, -1); c.drawImage(L, 0, 0); c.restore();
288
+ const R2 = P.scratch('rt_ref2'), rg = R2.getContext('2d'); rg.clearRect(0, 0, W, H); props(rg, t, true); // 道具反射先画到独立层再整体半透明,避免小球叠加变实
289
+ c.save(); c.beginPath(); c.rect(0, FLOOR_Y, W, H - FLOOR_Y); c.clip(); c.globalAlpha = 0.34; c.drawImage(R2, 0, 0); c.restore();
290
+ const fg = c.createLinearGradient(0, 905, 0, H); fg.addColorStop(0, 'rgba(160,190,195,0)'); fg.addColorStop(1, 'rgba(160,190,195,.25)'); c.fillStyle = fg; c.fillRect(0, 905, W, H - 905);
291
+ // 接触阴影
292
+ c.fillStyle = 'rgba(10,30,35,.35)'; [[540, 906, 130, 10], [1010, 900, 70, 8], [1190, 905, 80, 8], [1400, 912, 110, 8], [1592, 782, 70, 8]].forEach(([x, y, rx, ry]) => { c.beginPath(); c.ellipse(x, y, rx, ry, 0, 0, 7); c.fill(); });
293
+ c.drawImage(L, 0, 0);
294
+ props(c, t, false);
295
+ // 热气:半透明白色管状
296
+ P.steam(c, t, G.cup.x, G.cup.y - 6, { h: 60, n: 2, color: 'rgba(255,255,255,.7)', width: 5, spread: 14, wobble: 8 });
297
+ flare(c, t);
298
+ },
299
+ };
300
+ })();