@biunow/agent-biuart 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/server.mjs +575 -0
- package/data/styles.json +533 -0
- package/engine/audit_clip.py +46 -0
- package/engine/clip.html +24 -0
- package/engine/clip.js +104 -0
- package/engine/clip_schema.json +19 -0
- package/engine/clips/t1_3b1b.js +203 -0
- package/engine/clips/t2_keynote_ui.js +347 -0
- package/engine/clips/t3_finance_chart.js +206 -0
- package/engine/clips/y1_kurzgesagt.js +183 -0
- package/engine/clips/y2_vox.js +150 -0
- package/engine/clips/y3_whiteboard.js +209 -0
- package/engine/clips/y4_storytime.js +194 -0
- package/engine/clips/y5_kinetic_type.js +134 -0
- package/engine/compare.py +19 -0
- package/engine/demos/_shared/hero/c1_0.png +0 -0
- package/engine/demos/_shared/hero/c1_1.png +0 -0
- package/engine/demos/_shared/hero/c1_2.png +0 -0
- package/engine/demos/_shared/hero/c3_line.png +0 -0
- package/engine/demos/_shared/hero.js +96 -0
- package/engine/demos/long_scroll/eras.js +23 -0
- package/engine/demos/long_scroll/frames/8bit_act/01.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/02.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/03.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/04.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/05.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/06.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/07.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/08.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/meta.json +69 -0
- package/engine/demos/long_scroll/frames/8bit_walk/01.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/02.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/03.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/04.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/05.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/06.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/07.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/08.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/meta.json +69 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/01.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/02.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/03.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/04.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/05.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/06.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/07.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/08.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/meta.json +69 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/01.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/02.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/03.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/04.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/05.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/06.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/07.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/08.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/meta.json +69 -0
- package/engine/demos/long_scroll/frames/monet_throw/01.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/02.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/03.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/04.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/05.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/06.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/07.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/08.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/meta.json +71 -0
- package/engine/demos/long_scroll/frames/monet_walk/01.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/02.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/03.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/04.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/05.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/06.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/07.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/08.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/meta.json +71 -0
- package/engine/demos/long_scroll/lib/acts.js +87 -0
- package/engine/demos/long_scroll/lib/crossing.js +463 -0
- package/engine/demos/long_scroll/lib/world.js +143 -0
- package/engine/demos/long_scroll/lib/xing2_ding.js +42 -0
- package/engine/demos/long_scroll/lib/xing2_jia.js +114 -0
- package/engine/demos/long_scroll/lib/xing2_yi.js +133 -0
- package/engine/demos/long_scroll/segments/02_egypt.js +234 -0
- package/engine/demos/long_scroll/segments/14_8bit.js +118 -0
- package/engine/demos/long_scroll/segments/28_monet.js +86 -0
- package/engine/demos/t1_3b1b/eras.js +11 -0
- package/engine/demos/t1_3b1b/t1_s1.js +101 -0
- package/engine/demos/t1_3b1b/t1_s2.js +74 -0
- package/engine/demos/t1_3b1b/t1_s3.js +65 -0
- package/engine/demos/t2_keynote_ui/eras.js +10 -0
- package/engine/demos/t2_keynote_ui/t2_s1.js +57 -0
- package/engine/demos/t2_keynote_ui/t2_s2.js +70 -0
- package/engine/demos/t2_keynote_ui/t2_s3.js +61 -0
- package/engine/demos/t3_finance_chart/eras.js +11 -0
- package/engine/demos/t3_finance_chart/t3_s1.js +48 -0
- package/engine/demos/t3_finance_chart/t3_s2.js +42 -0
- package/engine/demos/t3_finance_chart/t3_s3.js +51 -0
- package/engine/demos/y1_kurzgesagt/eras.js +10 -0
- package/engine/demos/y1_kurzgesagt/kurzgesagt.js +347 -0
- package/engine/demos/y2_vox/eras.js +10 -0
- package/engine/demos/y2_vox/vox.js +240 -0
- package/engine/demos/y3_whiteboard/eras.js +10 -0
- package/engine/demos/y3_whiteboard/whiteboard.js +162 -0
- package/engine/demos/y4_storytime/eras.js +14 -0
- package/engine/demos/y4_storytime/s1_desk.js +18 -0
- package/engine/demos/y4_storytime/s2_screen.js +82 -0
- package/engine/demos/y4_storytime/s3_react.js +39 -0
- package/engine/demos/y4_storytime/s4_wide.js +16 -0
- package/engine/demos/y4_storytime/s5_close.js +18 -0
- package/engine/demos/y4_storytime/story.js +25 -0
- package/engine/demos/y4_storytime/vo_env.js +2 -0
- package/engine/demos/y4_storytime/world.js +73 -0
- package/engine/demos/y5_kinetic_type/eras.js +16 -0
- package/engine/demos/y5_kinetic_type/k1_title.js +38 -0
- package/engine/demos/y5_kinetic_type/k2_complete.js +55 -0
- package/engine/demos/y5_kinetic_type/k3_chat.js +47 -0
- package/engine/demos/y5_kinetic_type/k4_agent.js +49 -0
- package/engine/demos/y5_kinetic_type/kinetic.js +52 -0
- package/engine/engine.js +277 -0
- package/engine/eras.js +60 -0
- package/engine/eras_gallery.js +115 -0
- package/engine/eras_style_studies.js +20 -0
- package/engine/examples/assets/K/347/272/277/345/233/276_/346/250/252/345/261/217.png +0 -0
- 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
- package/engine/examples/assets//347/273/210/347/253/257_sum/346/261/202/345/222/214.png +0 -0
- package/engine/examples/assets//350/220/245/346/224/266/345/233/276_/347/253/226/345/261/217.png +0 -0
- 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
- package/engine/examples/t1_3b1b.json +19 -0
- package/engine/examples/t2_fullbleed_pulse.json +15 -0
- package/engine/examples/t2_keynote_ui.json +15 -0
- package/engine/examples/t3_finance_chart.json +29 -0
- package/engine/examples/y1_kurzgesagt.json +16 -0
- package/engine/examples/y2_vox.json +14 -0
- package/engine/examples/y3_whiteboard.json +17 -0
- package/engine/examples/y4_storytime.json +52 -0
- package/engine/examples/y5_kinetic_type.json +14 -0
- package/engine/index.html +42 -0
- package/engine/lib/THREE_LICENSE.txt +21 -0
- package/engine/lib/brush.js +149 -0
- package/engine/lib/camera.js +99 -0
- package/engine/lib/chart.js +152 -0
- package/engine/lib/collage.js +97 -0
- package/engine/lib/diagram.js +264 -0
- package/engine/lib/finish.js +70 -0
- package/engine/lib/fonts/AlfaSlabOne-400.woff +0 -0
- package/engine/lib/fonts/Anton-400.woff +0 -0
- package/engine/lib/fonts/ArchivoBlack-400.woff +0 -0
- package/engine/lib/fonts/Bangers-400.woff +0 -0
- package/engine/lib/fonts/Caveat-600.woff +0 -0
- package/engine/lib/fonts/Cinzel-400.woff +0 -0
- package/engine/lib/fonts/Cinzel-700.woff +0 -0
- package/engine/lib/fonts/CormorantGaramond-500.woff +0 -0
- package/engine/lib/fonts/CormorantGaramond-500i.woff +0 -0
- package/engine/lib/fonts/CormorantGaramond-700.woff +0 -0
- package/engine/lib/fonts/EBGaramond-400.woff +0 -0
- package/engine/lib/fonts/EBGaramond-400i.woff +0 -0
- package/engine/lib/fonts/EBGaramond-600.woff +0 -0
- package/engine/lib/fonts/Exo2-800i.woff +0 -0
- package/engine/lib/fonts/GochiHand-400.woff +0 -0
- package/engine/lib/fonts/IMFellEnglish-400.woff +0 -0
- package/engine/lib/fonts/IMFellEnglish-400i.woff +0 -0
- package/engine/lib/fonts/Inter-var.woff +0 -0
- package/engine/lib/fonts/JosefinSans-700.woff +0 -0
- package/engine/lib/fonts/Kalam-700.woff +0 -0
- package/engine/lib/fonts/LICENSES.md +40 -0
- package/engine/lib/fonts/LXGWWenKai-500.woff +0 -0
- package/engine/lib/fonts/LibreBaskerville-400.woff +0 -0
- package/engine/lib/fonts/LibreBaskerville-700.woff +0 -0
- package/engine/lib/fonts/LilitaOne-400.woff +0 -0
- package/engine/lib/fonts/Marcellus-400.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-500.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-700.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-800.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-900.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-sub.woff +0 -0
- package/engine/lib/fonts/NotoSerifJP-600.woff +0 -0
- package/engine/lib/fonts/NotoSerifSC-sub.woff +0 -0
- package/engine/lib/fonts/OFL.txt +94 -0
- package/engine/lib/fonts/PlayfairDisplay-400i.woff +0 -0
- package/engine/lib/fonts/PlayfairDisplay-700.woff +0 -0
- package/engine/lib/fonts/PlayfairDisplay-700i.woff +0 -0
- package/engine/lib/fonts/Poppins-600.woff +0 -0
- package/engine/lib/fonts/Poppins-700.woff +0 -0
- package/engine/lib/fonts/Poppins-800.woff +0 -0
- package/engine/lib/fonts/PressStart2P-400.woff +0 -0
- package/engine/lib/fonts/Righteous-400.woff +0 -0
- package/engine/lib/fonts/RobotoCondensed-var.woff +0 -0
- package/engine/lib/fonts/Rye-400.woff +0 -0
- package/engine/lib/fonts/UnifrakturMaguntia-400.woff +0 -0
- package/engine/lib/fonts/cmunrm.woff +0 -0
- package/engine/lib/fonts/cmunti.woff +0 -0
- package/engine/lib/fonts/index.json +1 -0
- package/engine/lib/fonts.js +56 -0
- package/engine/lib/kit.js +91 -0
- package/engine/lib/media.js +118 -0
- package/engine/lib/medium.js +258 -0
- package/engine/lib/motion.js +111 -0
- package/engine/lib/paint.js +200 -0
- package/engine/lib/palettes.js +57 -0
- package/engine/lib/post.js +108 -0
- package/engine/lib/render.js +189 -0
- package/engine/lib/rig.js +390 -0
- package/engine/lib/rig_huashu.js +171 -0
- package/engine/lib/three.min.js +7 -0
- package/engine/lib/toon.js +186 -0
- package/engine/lib/typo.js +136 -0
- package/engine/lib/ui.js +141 -0
- package/engine/lib/util.js +92 -0
- package/engine/render.py +157 -0
- package/engine/scenes/01_cave.js +364 -0
- package/engine/scenes/02_egypt.js +524 -0
- package/engine/scenes/03_greek.js +448 -0
- package/engine/scenes/04_roman.js +555 -0
- package/engine/scenes/05_gothic.js +522 -0
- package/engine/scenes/06_renaissance.js +338 -0
- package/engine/scenes/08_impressionism.js +206 -0
- package/engine/scenes/09_postimp.js +183 -0
- package/engine/scenes/10_nouveau.js +334 -0
- package/engine/scenes/11_cubism.js +265 -0
- package/engine/scenes/12_bauhaus.js +214 -0
- package/engine/scenes/13_pop.js +269 -0
- package/engine/scenes/14_8bit.js +238 -0
- package/engine/scenes/15_raytrace.js +300 -0
- package/engine/scenes/16_2026.js +565 -0
- package/engine/scenes/17_ink.js +273 -0
- package/engine/scenes/18_klimt.js +227 -0
- package/engine/scenes/19_munch.js +153 -0
- package/engine/scenes/20_dunhuang.js +215 -0
- package/engine/scenes/21_kusama.js +124 -0
- package/engine/scenes/22_constructivism.js +205 -0
- package/engine/scenes/23_dali.js +221 -0
- package/engine/scenes/24_hopper.js +150 -0
- package/engine/scenes/25_ghibli.js +251 -0
- package/engine/scenes/26_vaporwave.js +191 -0
- package/engine/scenes/27_kirby.js +255 -0
- package/engine/scenes/28_monet.js +176 -0
- package/engine/scenes/29_seurat.js +104 -0
- package/engine/scenes/30_matisse.js +151 -0
- package/engine/scenes/31_haring.js +109 -0
- package/engine/scenes/32_rembrandt.js +217 -0
- package/engine/scenes/33_rubberhose.js +219 -0
- package/engine/scenes/34_shadowpuppet.js +195 -0
- package/engine/scenes/35_shinkai.js +197 -0
- package/engine/scenes/36_picasso_blue.js +123 -0
- package/engine/scenes/38_giotto.js +133 -0
- package/engine/scenes/39_piero.js +53 -0
- package/engine/scenes/40_raphael.js +96 -0
- package/engine/scenes/41_michelangelo.js +112 -0
- package/engine/scenes/42_guardi.js +70 -0
- package/engine/scenes/43_lorenzetti.js +145 -0
- package/engine/scenes/44_cortona.js +86 -0
- package/engine/scenes/45_renoir.js +86 -0
- package/engine/scenes/46_pissarro.js +82 -0
- package/engine/scenes/47_sisley.js +94 -0
- package/engine/scenes/48_gauguin.js +107 -0
- package/engine/scenes/49_chagall.js +60 -0
- package/engine/scenes/50_ma_yuan.js +131 -0
- package/engine/scenes/51_persian_miniature.js +149 -0
- package/engine/scenes/52_south_park.js +105 -0
- package/engine/scenes/53_pixar.js +60 -0
- package/engine/scenes/54_ghibli_lab.js +68 -0
- package/engine/scenes/55_dunhuang.js +161 -0
- package/engine/scenes/index.js +28 -0
- package/engine/spec_assets.py +76 -0
- package/engine/transitions.js +929 -0
- package/engine//346/227/266/344/273/243/344/275/234/350/200/205/350/247/204/350/214/203.md +49 -0
- package/lib/host.mjs +754 -0
- package/lib/render-bridge.mjs +543 -0
- package/lib/render-cli.mjs +98 -0
- package/lib/storyboard-lint.mjs +54 -0
- package/manifest.json +52 -0
- package/package.json +8 -4
- package/runtime/package.json +8 -0
- package/skills/biuart/SKILL.md +154 -0
- package/skills/biuart/references/01-/346/213/206/350/247/243.md +55 -0
- package/skills/biuart/references/02-/346/234/272/345/210/266.md +41 -0
- 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
- package/skills/biuart/references/04-/347/272/257/344/273/243/347/240/201/347/273/230/345/210/266.md +92 -0
- package/skills/biuart/references/05-/350/212/202/345/245/217/344/270/216/351/205/215/344/271/220.md +19 -0
- 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
- package/skills/biuart/references/07-/346/255/243/351/235/242/347/273/217/351/252/214.md +196 -0
- 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
- 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
- package/skills/biuart/references/10-/350/247/222/350/211/262.md +34 -0
- package/skills/biuart/references/11-/351/225/277/345/215/267/347/251/277/350/266/212/347/211/207.md +43 -0
- 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
- 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
- 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
- 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
- package/skills/biuart/references/about-author.md +99 -0
- package/skills/biuart/references/capabilities.md +91 -0
- package/skills/biuart/references/compatibility.md +34 -0
- package/skills/biuart/references/images.md +97 -0
- package/skills/biuart/references/voice-model-review.md +18 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t1_3b1b.md +122 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t2_keynote_ui.md +117 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t3_finance_chart.md +116 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y1_kurzgesagt.md +193 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y2_vox.md +195 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y3_whiteboard.md +190 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y4_storytime.md +166 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y5_kinetic_type.md +158 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y6_presenter_explainer.md +24 -0
- package/skills/biuart/references//345/217/243/346/222/255API.md +125 -0
- package/skills/biuart/references//350/211/262/346/235/277.md +38 -0
- package/skills/biuart/references//350/247/222/350/211/262/347/262/276/347/273/206/345/272/246.md +61 -0
- package/skills/biuart/references//351/225/234/345/244/264/350/241/250/346/250/241/346/235/277.md +80 -0
- package/skills/biuart/references//351/225/234/345/244/264/350/257/255/350/250/200.md +73 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/01_cave.md +46 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/02_egypt.md +64 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/03_greek.md +50 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/04_roman.md +99 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/05_gothic.md +32 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/06_renaissance.md +41 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/08_impressionism.md +34 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/09_postimp.md +17 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/10_nouveau.md +31 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/11_cubism.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/12_bauhaus.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/13_pop.md +29 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/14_8bit.md +27 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/15_raytrace.md +32 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/16_2026.md +55 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/17_ink.md +50 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/18_klimt.md +37 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/19_munch.md +42 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/20_dunhuang.md +49 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/21_kusama.md +32 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/22_constructivism.md +35 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/23_dali.md +29 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/24_hopper.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/25_ghibli.md +55 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/26_vaporwave.md +27 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/27_kirby.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/28_monet.md +39 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/29_seurat.md +31 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/30_matisse.md +26 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/31_haring.md +22 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/32_rembrandt.md +29 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/33_rubberhose.md +31 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/34_shadowpuppet.md +40 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/35_shinkai.md +34 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/36_picasso_blue.md +25 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/37_rick_morty.md +48 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/38_giotto.md +67 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/39_piero.md +59 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/40_raphael.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/41_michelangelo.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/42_guardi.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/43_lorenzetti.md +69 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/44_cortona.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/45_renoir.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/46_pissarro.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/47_sisley.md +67 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/48_gauguin.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/49_chagall.md +59 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/50_ma_yuan.md +68 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/51_persian_miniature.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/52_south_park.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/53_pixar.md +61 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/55_dunhuang.md +41 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/INDEX.md +89 -0
- 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
- 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
- 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
- package/studio/app.js +380 -0
- package/studio/assert-panel-permit.mjs +67 -0
- package/studio/composer.css +465 -0
- package/studio/composer.js +480 -0
- package/studio/index.html +97 -0
- package/studio/optimize-prompt.mjs +84 -0
- package/studio/optimize-prompt.test.mjs +47 -0
- package/studio/recipes.mjs +87 -0
- package/studio/select-menu.js +450 -0
- package/studio/styles.css +71 -0
- package/studio/to-english-prompt.mjs +149 -0
- package/studio/to-english-prompt.test.mjs +72 -0
- package/README.md +0 -3
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// 敦煌壁画(北朝:257 窟鹿王本生 · 285 窟西魏飞天):土红地上的白色走兽和锯齿山,奶白地上的青绿风叶和长飘带飞天;
|
|
2
|
+
// 不是「中国风插画」——它是干燥的泥壁画:矿物色粉上墙、铅白氧化发暗、墙皮龟裂起甲、盐碱泛白,线是红褐的铁线/兰叶描。
|
|
3
|
+
// 题材(新构图):上栏一位飞天托莲横空而过,风叶和散花从身边向后翻;下栏一只白鹿领着一只小鹿穿过三角形的山奔跑。
|
|
4
|
+
// 原作锚定(fetch_reference.py:257 窟鹿王本生、285 窟西魏飞天、428 窟北周飞天、盛唐 112 窟):
|
|
5
|
+
// 土红地 #92342d/#9b4745;白鹿 #efe6d2;青绿 #3e919c/#577f7a;奶白地 #e8dcc5;赭 #b89d7d;深褐线 #3a1812;
|
|
6
|
+
// 山=一排排锯齿三角、各自涂青/白/黑/绿;动物=平涂白身+极少内部线;飞天=水平横飞、下身化成一条飘到身后的长裙;
|
|
7
|
+
// 上下两栏之间有一道多色横带;窟顶下沿垂幔三角纹;整面墙龟裂、起甲、泛盐。
|
|
8
|
+
// 管线:墙底(泥+色差,缓存)→ 上栏奶白地+下栏土红地+多色分隔带+顶部菱格带+底部垂幔 → 锯齿山(缓存)
|
|
9
|
+
// → 动态:鹿群奔跑、风叶后掠、飞天、散花、尘埃 → 龟裂/起甲/盐碱覆盖层(盖在画上面,裂缝穿过人和鹿)→ 泥壁颗粒相乘。
|
|
10
|
+
SCENES['55_dunhuang'] = (() => {
|
|
11
|
+
const W = 1920, H = 1080, { clamp, lerp, rng, ss } = U, P = PAINT, TAU = Math.PI * 2;
|
|
12
|
+
const C = { sky: '#e6d9bf', red: '#92342d', red2: '#7c2a24', white: '#efe6d2', teal: '#3e919c', teal2: '#1f5f6a', green: '#577f7a', ochre: '#c58a3e', ink: '#3a1812', line: '#6b2a1c', skin: '#e6cfae', flush: '#df8d74', dark: '#241512', lapis: '#35597c' };
|
|
13
|
+
const TOP = 64, SPLIT = 478, GROUND = 930, BOT = 986;
|
|
14
|
+
let base, over;
|
|
15
|
+
const sh = (h, k) => { const q = P.hex(h); return `rgb(${Math.round(q[0] * k)},${Math.round(q[1] * k)},${Math.round(q[2] * k)})`; };
|
|
16
|
+
const poly = (g, pts) => { g.beginPath(); pts.forEach((p, i) => i ? g.lineTo(p[0], p[1]) : g.moveTo(p[0], p[1])); g.closePath(); };
|
|
17
|
+
|
|
18
|
+
// ---- 静态:墙与两栏 ----
|
|
19
|
+
function band(g) { // 顶部:菱格带(青/白/红/黑)
|
|
20
|
+
g.fillStyle = C.dark; g.fillRect(0, 0, W, TOP);
|
|
21
|
+
const cols = [C.teal, C.white, C.red, C.ochre];
|
|
22
|
+
for (let i = 0, x = 0; x < W + 60; i++, x += 56) { g.fillStyle = cols[i % 4]; poly(g, [[x, TOP / 2], [x + 28, 8], [x + 56, TOP / 2], [x + 28, TOP - 8]]); g.fill(); g.strokeStyle = C.dark; g.lineWidth = 2; g.stroke(); g.fillStyle = cols[(i + 2) % 4]; g.beginPath(); g.arc(x + 28, TOP / 2, 5, 0, TAU); g.fill(); }
|
|
23
|
+
}
|
|
24
|
+
function divider(g) { // 上下栏之间的多色横带+联珠
|
|
25
|
+
const rows = [[C.dark, 8], [C.white, 14], [C.teal, 20], [C.ochre, 14], [C.white, 12], [C.dark, 8]]; let y = SPLIT;
|
|
26
|
+
rows.forEach(([col, h]) => { g.fillStyle = col; g.fillRect(0, y, W, h); y += h; });
|
|
27
|
+
g.fillStyle = C.white; g.strokeStyle = C.dark; g.lineWidth = 1.6; for (let x = 14; x < W; x += 28) { g.beginPath(); g.arc(x, SPLIT + 8 + 14 + 10, 5, 0, TAU); g.fill(); g.stroke(); }
|
|
28
|
+
}
|
|
29
|
+
function drapery(g) { // 底部:垂幔三角纹,每片垂一粒珠
|
|
30
|
+
g.fillStyle = C.dark; g.fillRect(0, BOT, W, H - BOT);
|
|
31
|
+
const cols = [C.teal, C.ochre, C.white, C.red2, C.green];
|
|
32
|
+
for (let i = 0, x = -10; x < W + 80; i++, x += 84) { g.fillStyle = cols[i % 5]; poly(g, [[x, BOT], [x + 84, BOT], [x + 42, BOT + 70]]); g.fill(); g.strokeStyle = C.dark; g.lineWidth = 2.4; g.stroke();
|
|
33
|
+
g.fillStyle = cols[(i + 2) % 5]; poly(g, [[x + 20, BOT], [x + 64, BOT], [x + 42, BOT + 38]]); g.fill(); g.fillStyle = C.white; g.beginPath(); g.arc(x + 42, BOT + 82, 6, 0, TAU); g.fill(); g.stroke(); }
|
|
34
|
+
}
|
|
35
|
+
function mountains(g) { // 257 窟式的山:窄高、倾斜、参差的三角碎片,一排排叠在红地上,红地大面积露出来;每片一色,一侧压暗,内部几道斜向地层线
|
|
36
|
+
const r = rng(257), rows = [[790, 150, 250, [C.teal2, C.dark, C.green, C.lapis], 1.18], [905, 90, 160, [C.white, C.teal, C.ochre, C.white], 1.0]];
|
|
37
|
+
rows.forEach(([bs, h0, h1, pal, step], ri) => { let x = -60 + ri * 90; while (x < W + 100) { const w = 130 + r() * 150, hh = h0 + r() * (h1 - h0), c0 = pal[Math.floor(r() * pal.length)], ap = x + w * (0.5 + (r() - .5) * 1.5);
|
|
38
|
+
g.fillStyle = c0; poly(g, [[x, bs], [ap, bs - hh], [x + w, bs]]); g.fill();
|
|
39
|
+
g.fillStyle = sh(c0, 0.6); poly(g, [[ap, bs - hh], [x + w, bs], [ap - (ap - x) * 0.05, bs - hh * 0.0]]); g.fill();
|
|
40
|
+
g.save(); poly(g, [[x, bs], [ap, bs - hh], [x + w, bs]]); g.clip(); g.strokeStyle = 'rgba(58,24,18,.5)'; g.lineWidth = 2; for (let k = 1; k < 6; k++) { const yy = bs - hh * k / 6.4; g.beginPath(); g.moveTo(x - 10, yy + 26); g.lineTo(x + w + 10, yy - 14); g.stroke(); } g.restore();
|
|
41
|
+
g.strokeStyle = C.ink; g.lineWidth = 3; g.lineJoin = 'round'; poly(g, [[x, bs], [ap, bs - hh], [x + w, bs]]); g.stroke();
|
|
42
|
+
x += w * (step + r() * 0.25); } });
|
|
43
|
+
}
|
|
44
|
+
function ground(g) { // 山脚地面:赭土+青绿三叶草+碎石点
|
|
45
|
+
g.fillStyle = C.ochre; g.fillRect(0, GROUND, W, BOT - GROUND); g.fillStyle = C.ink; g.fillRect(0, GROUND - 3, W, 5);
|
|
46
|
+
const r = rng(11); for (let i = 0; i < 70; i++) { const x = r() * W, y = GROUND + 10 + r() * (BOT - GROUND - 20); g.strokeStyle = r() < 0.6 ? C.teal2 : C.ink; g.lineWidth = 2.2; g.beginPath(); g.moveTo(x, y); g.lineTo(x - 7, y - 12); g.moveTo(x, y); g.lineTo(x + 1, y - 15); g.moveTo(x, y); g.lineTo(x + 8, y - 11); g.stroke(); }
|
|
47
|
+
}
|
|
48
|
+
function build() {
|
|
49
|
+
base = P.canvas(); const g = base.getContext('2d');
|
|
50
|
+
g.drawImage(P.texture('dh_sky', C.sky, { scale: 0.003, amt: 22, grain: 8, seed: 4 }), 0, TOP, W, SPLIT - TOP, 0, TOP, W, SPLIT - TOP);
|
|
51
|
+
g.drawImage(P.texture('dh_red', C.red, { scale: 0.0034, amt: 26, grain: 9, dark: '#5a1d1a', seed: 9 }), 0, SPLIT, W, BOT - SPLIT, 0, SPLIT, W, BOT - SPLIT);
|
|
52
|
+
g.save(); g.beginPath(); g.rect(0, SPLIT + 76, W, GROUND - SPLIT - 76); g.clip(); mountains(g); g.restore();
|
|
53
|
+
// 红地上撒几只远处的小白兽剪影(257 窟满地走兽的感觉)
|
|
54
|
+
const rs = rng(77); for (let i = 0; i < 7; i++) { const x = 120 + i * 270 + rs() * 80, y = SPLIT + 120 + rs() * 90; g.fillStyle = 'rgba(239,230,210,.92)'; g.strokeStyle = C.ink; g.lineWidth = 2; g.beginPath(); g.ellipse(x, y, 26, 11, 0, 0, TAU); g.fill(); g.stroke(); g.beginPath(); g.ellipse(x + 26, y - 14, 8, 6, 0.3, 0, TAU); g.fill(); g.stroke(); [-14, 14].forEach(dx => { g.beginPath(); g.moveTo(x + dx, y + 8); g.lineTo(x + dx - 3, y + 26); g.stroke(); }); }
|
|
55
|
+
ground(g); band(g); divider(g); drapery(g);
|
|
56
|
+
// 上栏底部一圈淡淡的熏黑(油灯与岁月)
|
|
57
|
+
const gr = g.createLinearGradient(0, TOP, 0, SPLIT); gr.addColorStop(0, 'rgba(60,34,20,.26)'); gr.addColorStop(0.22, 'rgba(60,34,20,0)'); gr.addColorStop(1, 'rgba(60,34,20,.12)'); g.fillStyle = gr; g.fillRect(0, TOP, W, SPLIT - TOP);
|
|
58
|
+
// 覆盖层:龟裂、起甲露底、盐碱
|
|
59
|
+
over = P.canvas(); const o = over.getContext('2d'), r = rng(1999);
|
|
60
|
+
for (let k = 0; k < 18; k++) { let x = r() * W, y = TOP + r() * (BOT - TOP), a = r() * TAU; o.strokeStyle = 'rgba(30,14,10,.5)'; o.lineWidth = 1.2 + r() * 1.2; o.lineJoin = 'round'; o.beginPath(); o.moveTo(x, y);
|
|
61
|
+
const n = 10 + Math.floor(r() * 22); for (let i = 0; i < n; i++) { a += (r() - .5) * 0.9; x += Math.cos(a) * (12 + r() * 20); y += Math.sin(a) * (12 + r() * 20); o.lineTo(x, y); if (r() < 0.12) { o.stroke(); o.beginPath(); o.moveTo(x, y); a += (r() < 0.5 ? 1 : -1) * 0.9; } } o.stroke(); }
|
|
62
|
+
for (let k = 0; k < 22; k++) { const cx = r() * W, cy = TOP + r() * (BOT - TOP), n = 9 + Math.floor(r() * 6), R = 6 + r() * 22; o.fillStyle = r() < 0.6 ? 'rgba(206,176,136,.34)' : 'rgba(96,60,40,.26)'; o.beginPath();
|
|
63
|
+
for (let i = 0; i < n; i++) { const aa = i / n * TAU, rr = R * (0.45 + r() * 0.75); o.lineTo(cx + Math.cos(aa) * rr, cy + Math.sin(aa) * rr * 0.7); } o.closePath(); o.fill(); o.strokeStyle = 'rgba(40,20,12,.3)'; o.lineWidth = 1.4; o.stroke(); }
|
|
64
|
+
for (let k = 0; k < 260; k++) { o.fillStyle = `rgba(245,238,225,${0.1 + r() * 0.3})`; o.beginPath(); o.ellipse(r() * W, TOP + r() * (BOT - TOP), 1.5 + r() * 4.5, 1 + r() * 2.5, r() * 3, 0, TAU); o.fill(); }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ---- 动态件 ----
|
|
68
|
+
const lineStroke = (c, w = 2.6) => { c.strokeStyle = C.line; c.lineWidth = w; c.lineJoin = 'round'; c.lineCap = 'round'; };
|
|
69
|
+
function ribbon(c, pts, w0, w1, fill, edge = C.line, hi = null) { // 变宽飘带:两侧沿法线展开,铁线描边
|
|
70
|
+
const L = [], R = [];
|
|
71
|
+
pts.forEach((p, i) => { const a = pts[Math.max(0, i - 1)], b = pts[Math.min(pts.length - 1, i + 1)], dx = b[0] - a[0], dy = b[1] - a[1], d = Math.hypot(dx, dy) || 1, nx = -dy / d, ny = dx / d, w = lerp(w0, w1, i / (pts.length - 1)) / 2; L.push([p[0] + nx * w, p[1] + ny * w]); R.push([p[0] - nx * w, p[1] - ny * w]); });
|
|
72
|
+
c.beginPath(); L.forEach((p, i) => i ? c.lineTo(p[0], p[1]) : c.moveTo(p[0], p[1])); R.reverse().forEach(p => c.lineTo(p[0], p[1])); c.closePath(); c.fillStyle = fill; c.fill(); lineStroke(c, 2.2); c.strokeStyle = edge; c.stroke();
|
|
73
|
+
if (hi) { c.strokeStyle = hi; c.lineWidth = 2; c.beginPath(); pts.forEach((p, i) => i ? c.lineTo(p[0], p[1]) : c.moveTo(p[0], p[1])); c.stroke(); }
|
|
74
|
+
}
|
|
75
|
+
function leaf(c, x, y, ang, len, col, col2, k) { // 西魏「风叶」:一撮向后翻卷的逗号形青绿叶,三尖
|
|
76
|
+
c.save(); c.translate(x, y); c.rotate(ang); c.scale(1, k);
|
|
77
|
+
c.beginPath(); c.moveTo(0, 0); c.bezierCurveTo(len * 0.25, -len * 0.5, len * 0.8, -len * 0.45, len, -len * 0.12); c.bezierCurveTo(len * 0.7, -len * 0.18, len * 0.5, -len * 0.1, len * 0.42, len * 0.06); c.bezierCurveTo(len * 0.3, len * 0.18, len * 0.1, len * 0.14, 0, 0); c.closePath();
|
|
78
|
+
c.fillStyle = col; c.fill(); lineStroke(c, 2); c.strokeStyle = col2; c.stroke();
|
|
79
|
+
c.strokeStyle = 'rgba(255,250,235,.8)'; c.lineWidth = 2.2; c.beginPath(); c.moveTo(len * 0.1, -len * 0.06); c.bezierCurveTo(len * 0.3, -len * 0.3, len * 0.6, -len * 0.3, len * 0.84, -len * 0.14); c.stroke();
|
|
80
|
+
c.restore();
|
|
81
|
+
}
|
|
82
|
+
function bloom(c, x, y, s, rot, col) { // 散花:四瓣白花,红心
|
|
83
|
+
c.save(); c.translate(x, y); c.rotate(rot); c.scale(s, s); c.fillStyle = col; lineStroke(c, 1.8 / s);
|
|
84
|
+
for (let i = 0; i < 4; i++) { c.save(); c.rotate(i * TAU / 4); c.beginPath(); c.ellipse(0, -9, 5.5, 9, 0, 0, TAU); c.fill(); c.stroke(); c.restore(); }
|
|
85
|
+
c.fillStyle = C.red; c.beginPath(); c.arc(0, 0, 3.2, 0, TAU); c.fill(); c.restore();
|
|
86
|
+
}
|
|
87
|
+
function lotus(c, x, y, s) {
|
|
88
|
+
c.save(); c.translate(x, y); c.scale(s, s); lineStroke(c, 2.2 / s);
|
|
89
|
+
[[-1.0, '#f1d9d0'], [1.0, '#f1d9d0'], [-0.5, '#f6e4dc'], [0.5, '#f6e4dc'], [0, '#fbeee8']].forEach(([a, col]) => { c.save(); c.rotate(a * 0.9 - 0.2); c.beginPath(); c.moveTo(0, 0); c.bezierCurveTo(-11, -14, -9, -32, 0, -40); c.bezierCurveTo(9, -32, 11, -14, 0, 0); c.fillStyle = col; c.fill(); c.stroke(); c.restore(); });
|
|
90
|
+
c.fillStyle = C.ochre; c.beginPath(); c.arc(0, -4, 5, 0, TAU); c.fill(); c.restore();
|
|
91
|
+
}
|
|
92
|
+
// 飞天(西魏式):水平横飞,头在前,披帛后扬,躯干与长裙是一条连贯的 S 形;脸小、眉眼细长、颊上一点红晕;红褐铁线勾边,肤色铅丹淡赭
|
|
93
|
+
function apsara(c, x, y, s, flip, t, ph = 0) {
|
|
94
|
+
c.save(); c.translate(x, y + Math.sin(t * 1.15 + ph) * 12); c.rotate(-0.07 + Math.sin(t * 0.9 + ph) * 0.03); c.scale(s * flip, s);
|
|
95
|
+
const w = (i, k) => Math.sin(t * 2.6 - i * 0.55 + ph + k), SK = '#eab894';
|
|
96
|
+
const sa = []; for (let i = 0; i <= 18; i++) sa.push([30 - i * 22, -30 - Math.sin(i * 0.22) * 34 + w(i, 0) * (3 + i * 1.5)]); ribbon(c, sa, 17, 3, C.teal, C.teal2, 'rgba(255,255,240,.75)');
|
|
97
|
+
const sb = []; for (let i = 0; i <= 12; i++) sb.push([24 - i * 20, 12 + w(i, 2) * (3 + i * 1.2) + i * 5]); ribbon(c, sb, 14, 3, C.ochre, C.line);
|
|
98
|
+
const sk = [[-16, 2]]; for (let i = 1; i <= 15; i++) sk.push([-16 - i * 23, 4 + Math.sin(i * 0.42 + t * 2.2 + ph) * (4 + i * 1.8) - i * 2.4]); // 长裙:从腰接出,越飘越尖
|
|
99
|
+
ribbon(c, sk, 52, 4, '#79b2a6', C.line, 'rgba(255,255,240,.5)'); c.strokeStyle = 'rgba(31,95,106,.7)'; c.lineWidth = 2; for (let k = -1; k <= 1; k += 2) { c.beginPath(); sk.slice(1, 13).forEach((p, i) => { const yy = p[1] + k * (12 - i * 0.8); i ? c.lineTo(p[0], yy) : c.moveTo(p[0], yy); }); c.stroke(); }
|
|
100
|
+
c.fillStyle = 'rgba(240,226,190,.8)'; for (let i = 2; i < 12; i += 2) { c.beginPath(); c.arc(sk[i][0], sk[i][1] - 2, 3.2, 0, TAU); c.fill(); }
|
|
101
|
+
ribbon(c, [[52, -28], [26, -18], [2, -6], [-22, 2]], 36, 30, SK, C.line); // 躯干:由肩向腰收
|
|
102
|
+
c.fillStyle = C.red; ribbon(c, [[-6, -14], [-8, -2], [-12, 10]], 10, 10, C.red, C.line); // 腰带
|
|
103
|
+
c.strokeStyle = C.teal; c.lineWidth = 4; c.beginPath(); c.arc(56, -34, 16, 0.4, 2.2); c.stroke(); c.fillStyle = C.ochre; c.beginPath(); c.arc(56, -17, 4, 0, TAU); c.fill(); lineStroke(c, 1.6); c.stroke(); // 璎珞
|
|
104
|
+
ribbon(c, [[40, -34], [24, -58], [0, -72]], 14, 10, SK, C.line); c.fillStyle = SK; c.beginPath(); c.arc(-6, -74, 7.5, 0, TAU); c.fill(); lineStroke(c, 2.2); c.stroke();
|
|
105
|
+
ribbon(c, [[52, -28], [84, -2 + w(0, 1) * 3], [112, -20]], 15, 11, SK, C.line); c.fillStyle = SK; c.beginPath(); c.arc(116, -22, 8, 0, TAU); c.fill(); lineStroke(c, 2.2); c.stroke(); lotus(c, 120, -26, 0.95);
|
|
106
|
+
const hr = []; for (let i = 0; i <= 8; i++) hr.push([62 - i * 12, -78 + i * 2.5 + w(i, 4) * (2 + i)]); ribbon(c, hr, 18, 3, C.dark, C.line); // 发尾后扬
|
|
107
|
+
c.fillStyle = SK; c.beginPath(); c.ellipse(80, -54, 20, 23, 0.12, 0, TAU); c.fill(); lineStroke(c, 2.6); c.stroke();
|
|
108
|
+
c.fillStyle = C.dark; c.beginPath(); c.moveTo(60, -58); c.bezierCurveTo(60, -86, 100, -88, 100, -60); c.bezierCurveTo(92, -72, 72, -72, 60, -58); c.fill(); c.beginPath(); c.arc(70, -86, 11, 0, TAU); c.fill(); c.strokeStyle = C.line; c.stroke();
|
|
109
|
+
c.fillStyle = C.ochre; [[78, -82], [86, -78], [92, -72]].forEach(([px, py]) => { c.beginPath(); c.arc(px, py, 2.8, 0, TAU); c.fill(); }); c.fillStyle = C.teal; c.beginPath(); c.arc(70, -97, 3.6, 0, TAU); c.fill();
|
|
110
|
+
c.fillStyle = 'rgba(223,120,96,.8)'; c.beginPath(); c.ellipse(92, -45, 7, 5.5, 0, 0, TAU); c.fill(); c.beginPath(); c.ellipse(68, -45, 6, 5, 0, 0, TAU); c.fill();
|
|
111
|
+
c.strokeStyle = C.line; c.lineWidth = 2.2; c.beginPath(); c.moveTo(80, -64); c.quadraticCurveTo(90, -69, 99, -62); c.moveTo(62, -63); c.quadraticCurveTo(68, -68, 77, -64); c.stroke();
|
|
112
|
+
c.lineWidth = 2.6; c.beginPath(); c.moveTo(83, -57); c.quadraticCurveTo(91, -60, 98, -56); c.moveTo(62, -57); c.quadraticCurveTo(69, -60, 76, -57); c.stroke(); c.fillStyle = C.dark; c.beginPath(); c.arc(91, -57, 2, 0, TAU); c.arc(69, -57, 1.8, 0, TAU); c.fill();
|
|
113
|
+
c.strokeStyle = C.line; c.lineWidth = 1.8; c.beginPath(); c.moveTo(82, -54); c.quadraticCurveTo(86, -46, 82, -43); c.stroke(); c.fillStyle = C.red; c.beginPath(); c.ellipse(80, -36, 4.6, 2.3, 0, 0, TAU); c.fill();
|
|
114
|
+
c.restore();
|
|
115
|
+
}
|
|
116
|
+
// 白鹿(鹿王本生式):侧身,身子是一整块白,只有轮廓与脊背一线赭点;奔跑用「腾空伸展—收拢」的两拍,前后腿成对错开
|
|
117
|
+
function deer(c, x, y, s, t, ph, col = C.white) {
|
|
118
|
+
const f = t * 5.2 + ph, g = Math.sin(f), jump = Math.max(0, Math.sin(f + 1.1)) * 20;
|
|
119
|
+
c.save(); c.translate(x, y - jump * s); c.rotate(-g * 0.03); c.scale(s, s); c.lineJoin = 'round'; c.lineCap = 'round';
|
|
120
|
+
const leg = (hx, hy, a, front) => { // a∈[-1,1]:前摆为正;前腿膝向前弯、后腿膝向后弯
|
|
121
|
+
const th = a * 0.95, kn = [hx + Math.sin(th) * 52, hy + Math.cos(th) * 52], th2 = th + (front ? -1 : 1) * (0.55 + 0.45 * (1 - a * (front ? 1 : -1)) * 0.5), fo = [kn[0] + Math.sin(th2 + (front ? 0.25 : -0.1)) * 56, kn[1] + Math.cos(th2) * 56];
|
|
122
|
+
ribbon(c, [[hx, hy], [kn[0], kn[1]], [fo[0], fo[1]]], 22, 8, col, C.line); c.fillStyle = C.ochre; c.beginPath(); c.ellipse(fo[0] + 3, fo[1] - 2, 8, 4.5, 0.2, 0, TAU); c.fill(); c.strokeStyle = C.line; c.lineWidth = 2; c.stroke(); };
|
|
123
|
+
leg(-56, -78, -g * 0.9, false); leg(-40, -76, g * 0.9 + 0.2, false); leg(50, -80, g * 0.9, true); leg(64, -78, -g * 0.9 + 0.2, true);
|
|
124
|
+
c.beginPath(); c.moveTo(-90, -92); c.bezierCurveTo(-70, -132, 30, -138, 68, -114); c.bezierCurveTo(90, -126, 100, -150, 112, -172); c.bezierCurveTo(124, -190, 150, -190, 160, -174); c.bezierCurveTo(150, -158, 130, -156, 120, -146); c.bezierCurveTo(116, -118, 100, -90, 70, -76); c.bezierCurveTo(28, -56, -30, -56, -64, -66); c.bezierCurveTo(-84, -70, -98, -82, -90, -92); c.closePath();
|
|
125
|
+
c.fillStyle = col; c.fill(); lineStroke(c, 3.4); c.stroke();
|
|
126
|
+
c.fillStyle = C.ochre; for (let i = 0; i < 12; i++) { const q = i / 11, px = lerp(-70, 66, q), py = lerp(-100, -114, Math.sin(q * 2.2)) - 4; c.beginPath(); c.arc(px, py + (q > 0.8 ? (q - 0.8) * 40 : 0), 3.6, 0, TAU); c.fill(); }
|
|
127
|
+
c.strokeStyle = 'rgba(58,24,18,.55)'; c.lineWidth = 1.8; [[-22, -96, -8, -78], [10, -98, 22, -80], [-52, -90, -42, -74]].forEach(([a1, b1, a2, b2]) => { c.beginPath(); c.moveTo(a1, b1); c.quadraticCurveTo((a1 + a2) / 2 + 6, (b1 + b2) / 2, a2, b2); c.stroke(); });
|
|
128
|
+
c.fillStyle = col; lineStroke(c, 3); c.beginPath(); c.moveTo(110, -172); c.quadraticCurveTo(100, -204, 124, -214); c.quadraticCurveTo(124, -192, 124, -172); c.closePath(); c.fill(); c.stroke(); c.fillStyle = C.teal; c.beginPath(); c.moveTo(114, -184); c.quadraticCurveTo(112, -200, 121, -206); c.quadraticCurveTo(120, -194, 120, -184); c.fill();
|
|
129
|
+
c.strokeStyle = C.ochre; c.lineWidth = 5; c.beginPath(); c.moveTo(136, -186); c.quadraticCurveTo(148, -222, 176, -230); c.moveTo(152, -212); c.lineTo(150, -240); c.moveTo(160, -222); c.lineTo(184, -220); c.stroke();
|
|
130
|
+
c.fillStyle = C.ink; c.beginPath(); c.arc(138, -172, 3.4, 0, TAU); c.fill(); c.strokeStyle = C.red; c.lineWidth = 1.8; c.beginPath(); c.arc(138, -172, 6, 0, TAU); c.stroke(); c.fillStyle = C.ink; c.beginPath(); c.ellipse(158, -173, 3, 2.2, 0, 0, TAU); c.fill();
|
|
131
|
+
c.fillStyle = col; c.beginPath(); c.moveTo(-88, -94); c.quadraticCurveTo(-116, -108, -112, -80); c.quadraticCurveTo(-100, -86, -88, -84); c.fill(); lineStroke(c, 2.6); c.stroke();
|
|
132
|
+
c.restore();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function draw(c, lt) {
|
|
136
|
+
if (!base) build();
|
|
137
|
+
const t = clamp(lt, 0, 6);
|
|
138
|
+
c.drawImage(base, 0, 0);
|
|
139
|
+
// 上栏:风叶(远处小的在前面,带浅色;大的青绿深色)整体向后(左)翻,速度分层
|
|
140
|
+
const rl = rng(285);
|
|
141
|
+
for (let i = 0; i < 26; i++) {
|
|
142
|
+
const sp = 70 + rl() * 120, y0 = TOP + 40 + rl() * (SPLIT - TOP - 100), ln = 60 + rl() * 80, x0 = rl() * (W + 300), k = 0.8 + rl() * 0.4, rot = (rl() - .5) * 0.7, col = rl() < 0.62 ? C.teal : rl() < 0.8 ? C.green : '#c9a23a';
|
|
143
|
+
const x = ((x0 - t * sp) % (W + 300) + (W + 300)) % (W + 300) - 150, y = y0 + Math.sin(t * 1.3 + i) * 10;
|
|
144
|
+
leaf(c, x, y, Math.PI + rot + Math.sin(t * 1.1 + i) * 0.1, ln, col, i % 5 === 0 ? C.line : C.teal2, k);
|
|
145
|
+
}
|
|
146
|
+
apsara(c, 1060, 262, 1.72, 1, t, 0); // 主飞天
|
|
147
|
+
apsara(c, 560, 150, 0.82, -1, t, 2.2); // 远处的小飞天,反向飞
|
|
148
|
+
const rb = rng(31); for (let i = 0; i < 16; i++) { const sp = 60 + rb() * 90, x = (((rb() * (W + 200)) - t * sp * 0.9) % (W + 200) + W + 200) % (W + 200) - 100, y = TOP + 30 + ((rb() * (SPLIT - TOP - 80)) + t * 28 * (0.5 + rb())) % (SPLIT - TOP - 60); bloom(c, x, y, 0.8 + rb() * 0.7, t * (0.6 + rb()) + i, C.white); }
|
|
149
|
+
// 下栏:白鹿领队,小鹿稍后;前后各一个相位
|
|
150
|
+
const run = (t / 6), x1 = 360 + run * 1000, x2 = 160 + run * 940;
|
|
151
|
+
deer(c, x2, GROUND + 22, 0.95, t, 1.6, '#e8dcc2'); deer(c, x1, GROUND + 32, 1.5, t, 0);
|
|
152
|
+
// 奔跑扬起的尘(鹿蹄后面)
|
|
153
|
+
for (let i = 0; i < 12; i++) { const q = ((t * 1.6 + i / 12) % 1), px = x1 - 60 - q * 150 - i * 4, py = GROUND + 30 - q * 40 - (i % 3) * 6; c.fillStyle = `rgba(214,190,150,${(1 - q) * 0.55})`; c.beginPath(); c.arc(px, py, 6 + q * 18, 0, TAU); c.fill(); }
|
|
154
|
+
// 覆盖层+泥壁相乘
|
|
155
|
+
c.drawImage(over, 0, 0);
|
|
156
|
+
c.save(); c.globalCompositeOperation = 'multiply'; c.globalAlpha = 0.42; c.drawImage(P.texture('dh_mud', '#d9c6a6', { scale: 0.006, amt: 30, grain: 14, dark: '#9a7a54', seed: 21 }), 0, 0); c.restore();
|
|
157
|
+
// 漂在光里的尘
|
|
158
|
+
const rd = rng(5); for (let i = 0; i < 40; i++) { const x = (rd() * W + t * (6 + rd() * 10)) % W, y = TOP + rd() * (BOT - TOP) + Math.sin(t * 0.6 + i) * 6; c.fillStyle = `rgba(255,244,214,${0.1 + rd() * 0.14})`; c.beginPath(); c.arc(x, y, 1 + rd() * 1.8, 0, TAU); c.fill(); }
|
|
159
|
+
}
|
|
160
|
+
return { draw };
|
|
161
|
+
})();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// 按 id 加载 scenes/<id>.js;按 transition.type 自动加载 transitions/<type>.js(同步 XHR,保证 engine 启动前全部注册)。
|
|
2
|
+
// 任何一个场景缺文件、语法错、没注册,或转场名在 TRANSITIONS 和 transitions/ 里都找不到 → 记进 window.__bootErrors,
|
|
3
|
+
// 引擎拒绝启动,render.py/qa.py 直接报错退出。
|
|
4
|
+
// (迁移测试 B 踩过:以前缺场景会画「待实现」占位照常渲,整段 1.2 秒灰底,靠帧差 0.0% 才发现;转场名写错会静默退成交叉淡化。)
|
|
5
|
+
(() => {
|
|
6
|
+
window.SCENES = window.SCENES || {}; window.__bootErrors = [];
|
|
7
|
+
const load = (url) => { const x = new XMLHttpRequest(); x.open('GET', url, false); try { x.send(); } catch (err) { return { err: `请求失败 ${err}` }; }
|
|
8
|
+
if (x.status !== 200) return { err: `${url} 不存在 (HTTP ${x.status})` };
|
|
9
|
+
try { (0, eval)(x.responseText + `\n//# sourceURL=${url}`); } catch (err) { return { err: `${url} 执行出错 ${err && err.stack || err}` }; } return {}; };
|
|
10
|
+
// 片子可以先加载自己的共用脚本(window.SCENE_LIBS,按顺序),场景文件目录 window.SCENE_DIR(默认 scenes)。
|
|
11
|
+
// 共用脚本里已经注册了 SCENES[id] 的段落,不再找单独的场景文件(demos/ 的示范片就是这么组织的)。
|
|
12
|
+
for (const f of window.SCENE_LIBS || []) { const r = load(f); if (r.err) __bootErrors.push(`共用脚本 ${r.err}`); }
|
|
13
|
+
const dir = window.SCENE_DIR || 'scenes';
|
|
14
|
+
for (const e of ERAS) {
|
|
15
|
+
if (!e.draw) { // eras 里内联了 draw 的段落不需要文件
|
|
16
|
+
const r = SCENES[e.id] ? {} : load(`${dir}/${e.id}.js`);
|
|
17
|
+
if (r.err) { __bootErrors.push(`${e.id}: ${r.err}`); continue; }
|
|
18
|
+
const sc = SCENES[e.id];
|
|
19
|
+
if (!sc || typeof sc.draw !== 'function') { __bootErrors.push(`${e.id}: 文件里没有 SCENES['${e.id}'] = { draw(c, lt, t) }`); continue; }
|
|
20
|
+
e.draw = sc.draw; if (sc.init) e.init = sc.init;
|
|
21
|
+
}
|
|
22
|
+
const ty = e.transition && e.transition.type;
|
|
23
|
+
if (ty && !TRANSITIONS[ty]) { // 项目自己的转场:放 transitions/<type>.js,往 TRANSITIONS 上挂同名函数
|
|
24
|
+
const r = load(`transitions/${ty}.js`);
|
|
25
|
+
if (r.err || !TRANSITIONS[ty]) __bootErrors.push(`${e.id}: 转场「${ty}」不在 transitions.js 里,也没有 transitions/${ty}.js(${r.err || '文件里没注册 TRANSITIONS.' + ty})`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
})();
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""片段 spec 里的本地素材路径:找出来、核存在、改写成本地服务能取的 URL。render.py 用它(qa.py 可以照搬)。
|
|
2
|
+
|
|
3
|
+
认这些字段(路径相对 spec 文件,也可写绝对路径;data: / http(s): 原样放行):
|
|
4
|
+
cues[].image 一张图(截图、照片、录像的一帧)
|
|
5
|
+
cues[].frames 帧序列:目录(按文件名排序取 .png/.jpg/.jpeg/.webp)或路径数组;配 cues[].fps(默认 30)
|
|
6
|
+
data.image 语法级的一张图(y1 用作中心物的图)
|
|
7
|
+
data.character y4 角色:预设名(neutral / bun / author)原样放行(y4 已停用代码画的角色,启动时会报错要帧库);目录 → 帧库(文件名去扩展名 = 姿势名);
|
|
8
|
+
对象 {frames: {姿势: 路径} | 目录} 同理
|
|
9
|
+
文件不存在 → FileNotFoundError(调用方拒绝渲染,不出空白帧)。
|
|
10
|
+
"""
|
|
11
|
+
import urllib.parse
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
FRAME_EXT = ('.png', '.jpg', '.jpeg', '.webp')
|
|
15
|
+
PRESETS = ('neutral', 'bun', 'author')
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _url(f, allowed):
|
|
19
|
+
allowed.add(str(f))
|
|
20
|
+
return '/__file__/' + urllib.parse.quote(str(f))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _file(v, base, allowed, what):
|
|
24
|
+
if not v or str(v).startswith(('data:', 'http:', 'https:')):
|
|
25
|
+
return v
|
|
26
|
+
f = (base / v).resolve()
|
|
27
|
+
if not f.is_file():
|
|
28
|
+
raise FileNotFoundError(f'spec 里的{what}不存在:{v}(相对 {base})')
|
|
29
|
+
return _url(f, allowed)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _dir_frames(v, base, what):
|
|
33
|
+
d = (base / v).resolve()
|
|
34
|
+
if not d.is_dir():
|
|
35
|
+
return None
|
|
36
|
+
files = sorted(p for p in d.iterdir() if p.suffix.lower() in FRAME_EXT)
|
|
37
|
+
if not files:
|
|
38
|
+
raise FileNotFoundError(f'spec 里的{what}目录是空的(没有 {"/".join(FRAME_EXT)}):{v}')
|
|
39
|
+
return files
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def localize(spec, base, allowed):
|
|
43
|
+
"""原地改写 spec。base = spec 所在目录;allowed 收集允许服务的绝对路径。"""
|
|
44
|
+
base = Path(base)
|
|
45
|
+
for q in spec.get('cues', []):
|
|
46
|
+
if q.get('image'):
|
|
47
|
+
q['image'] = _file(q['image'], base, allowed, '图片')
|
|
48
|
+
fr = q.get('frames')
|
|
49
|
+
if isinstance(fr, str):
|
|
50
|
+
files = _dir_frames(fr, base, '帧序列')
|
|
51
|
+
if files is None:
|
|
52
|
+
raise FileNotFoundError(f'spec 里的帧序列目录不存在:{fr}(相对 {base})')
|
|
53
|
+
q['frames'] = [_url(f, allowed) for f in files]
|
|
54
|
+
elif isinstance(fr, list):
|
|
55
|
+
if not fr:
|
|
56
|
+
raise FileNotFoundError('spec 里的 frames 是空数组')
|
|
57
|
+
q['frames'] = [_file(v, base, allowed, '视频帧') for v in fr]
|
|
58
|
+
data = spec.get('data') or {}
|
|
59
|
+
if data.get('image'):
|
|
60
|
+
data['image'] = _file(data['image'], base, allowed, '图片')
|
|
61
|
+
ch = data.get('character')
|
|
62
|
+
if isinstance(ch, str) and ch not in PRESETS:
|
|
63
|
+
files = _dir_frames(ch, base, '角色帧库')
|
|
64
|
+
if files is None:
|
|
65
|
+
raise FileNotFoundError(f'data.character 既不是预设({" / ".join(PRESETS)})也不是帧库目录:{ch}(相对 {base})')
|
|
66
|
+
data['character'] = {'frames': {f.stem: _url(f, allowed) for f in files}}
|
|
67
|
+
elif isinstance(ch, dict):
|
|
68
|
+
fr = ch.get('frames')
|
|
69
|
+
if isinstance(fr, str):
|
|
70
|
+
files = _dir_frames(fr, base, '角色帧库')
|
|
71
|
+
if files is None:
|
|
72
|
+
raise FileNotFoundError(f'data.character.frames 目录不存在:{fr}(相对 {base})')
|
|
73
|
+
ch['frames'] = {f.stem: _url(f, allowed) for f in files}
|
|
74
|
+
elif isinstance(fr, dict):
|
|
75
|
+
ch['frames'] = {k: _file(v, base, allowed, f'角色帧「{k}」') for k, v in fr.items()}
|
|
76
|
+
return spec
|