create-aura3d 1.1.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +5 -3
  4. package/dist/index.js.map +1 -1
  5. package/package.json +11 -9
  6. package/templates/{cartoon-channel → animation-channel}/README.md +11 -11
  7. package/templates/{cartoon-studio → animation-channel}/index.html +1 -1
  8. package/templates/{cartoon-channel → animation-channel}/package.json +2 -2
  9. package/templates/{cartoon-channel → animation-channel}/src/episode.ts +22 -22
  10. package/templates/{cartoon-channel → animation-channel}/src/experimental/README.md +5 -5
  11. package/templates/{cartoon-channel → animation-channel}/src/experimental/concept-episode-2-5d.css +3 -3
  12. package/templates/{cartoon-channel → animation-channel}/src/experimental/concept-episode-2-5d.ts +7 -7
  13. package/templates/{cartoon-channel → animation-channel}/src/experimental/image-puppet-episode.css +4 -4
  14. package/templates/{cartoon-channel → animation-channel}/src/experimental/image-puppet-episode.ts +6 -6
  15. package/templates/{cartoon-channel → animation-channel}/src/experimental/puppet-episode-2d.css +3 -3
  16. package/templates/{cartoon-channel → animation-channel}/src/experimental/puppet-episode-2d.ts +7 -7
  17. package/templates/{cartoon-channel → animation-channel}/src/main.ts +32 -32
  18. package/templates/{cartoon-channel → animation-channel}/src/render-plan.ts +13 -13
  19. package/templates/{cartoon-channel → animation-channel}/src/sample-episode-visual.css +34 -34
  20. package/templates/{cartoon-channel → animation-channel}/src/sample-episode-visual.ts +20 -20
  21. package/templates/{cartoon-channel → animation-channel}/tests/concept-2-5d-animation.spec.ts +3 -3
  22. package/templates/{cartoon-channel → animation-channel}/tests/concept-2-5d.spec.ts +6 -6
  23. package/templates/{cartoon-channel → animation-channel}/tests/image-puppet-animation.spec.ts +3 -3
  24. package/templates/{cartoon-channel → animation-channel}/tests/image-puppet.spec.ts +5 -5
  25. package/templates/{cartoon-channel → animation-channel}/tests/puppet-2d-animation.spec.ts +3 -3
  26. package/templates/{cartoon-channel → animation-channel}/tests/puppet-2d.spec.ts +4 -4
  27. package/templates/{prompt-cartoon-channel → animation-channel}/tests/route-health.spec.ts +1 -1
  28. package/templates/{cartoon-channel → animation-channel}/tests/sample-episode-visual.spec.ts +5 -5
  29. package/templates/{cartoon-channel → animation-channel}/tests/storyboard-playback.spec.ts +7 -7
  30. package/templates/animation-studio/AGENTS.md +71 -0
  31. package/templates/{cartoon-studio → animation-studio}/ASSET-LICENSES.md +7 -7
  32. package/templates/{cartoon-studio → animation-studio}/README.md +6 -6
  33. package/templates/animation-studio/aura.assets.json +669 -0
  34. package/templates/animation-studio/dist/episodes/scene/episode-3d.webm +0 -0
  35. package/templates/animation-studio/dist/episodes/scene/frames/action.png +0 -0
  36. package/templates/animation-studio/dist/episodes/scene/frames/dialogue.png +0 -0
  37. package/templates/animation-studio/dist/episodes/scene/frames/final.png +0 -0
  38. package/templates/animation-studio/dist/episodes/scene/frames/first.png +0 -0
  39. package/templates/animation-studio/dist/episodes/scene/frames/mouth-closed.png +0 -0
  40. package/templates/animation-studio/dist/episodes/scene/frames/mouth-open.png +0 -0
  41. package/templates/animation-studio/dist/episodes/scene/render-live-summary.json +10284 -0
  42. package/templates/animation-studio/dist/episodes/scene/skeleton-overlays/worker-1.png +0 -0
  43. package/templates/animation-studio/dist/episodes/scene/skeleton-overlays/worker-2.png +0 -0
  44. package/templates/animation-studio/dist/generated/second-scene.document.json +1210 -0
  45. package/templates/animation-studio/dist/generated/studio-edited.document.json +1196 -0
  46. package/templates/animation-studio/dist/scene/inshader-accept.document.json +1 -0
  47. package/templates/animation-studio/dist/scene/inshader-test.document.json +1 -0
  48. package/templates/animation-studio/dist/scene/integ.document.json +1 -0
  49. package/templates/animation-studio/dist/scene/working.document.json +723 -0
  50. package/templates/animation-studio/dist/scene/working.history.json +1 -0
  51. package/templates/{cartoon-studio → animation-studio}/live-route.html +1 -1
  52. package/templates/{cartoon-studio → animation-studio}/package-lock.json +2 -2
  53. package/templates/animation-studio/package.json +32 -0
  54. package/templates/animation-studio/public/aura-assets/cast-a.catalog.glb +0 -0
  55. package/templates/animation-studio/public/aura-assets/cast-b.catalog.glb +0 -0
  56. package/templates/animation-studio/public/aura-assets/luma.catalog.glb +0 -0
  57. package/templates/animation-studio/public/aura-assets/luma2.catalog.glb +0 -0
  58. package/templates/animation-studio/public/aura-assets/miko.catalog.glb +0 -0
  59. package/templates/{cartoon-studio → animation-studio}/public/aura-assets/moonGarden.gltf +1 -1
  60. package/templates/animation-studio/public/aura-assets/mushroom.catalog.glb +0 -0
  61. package/templates/animation-studio/public/aura-assets/rusty.catalog.glb +0 -0
  62. package/templates/animation-studio/public/cast-library/cast-library.json +71 -0
  63. package/templates/animation-studio/public/clip-library/gesture.json +173903 -0
  64. package/templates/animation-studio/public/clip-library/idle.json +23035 -0
  65. package/templates/animation-studio/public/clip-library/manifest.json +154 -0
  66. package/templates/animation-studio/public/clip-library/nod.json +173903 -0
  67. package/templates/animation-studio/public/clip-library/point.json +69879 -0
  68. package/templates/animation-studio/public/clip-library/react.json +66084 -0
  69. package/templates/animation-studio/public/clip-library/run.json +9648 -0
  70. package/templates/animation-studio/public/clip-library/talk.json +69879 -0
  71. package/templates/animation-studio/public/clip-library/walk.json +8283 -0
  72. package/templates/animation-studio/public/hifi-cast/BrainStem.glb +0 -0
  73. package/templates/animation-studio/public/hifi-cast/CesiumMan.glb +0 -0
  74. package/templates/animation-studio/public/hifi-cast/RiggedFigure.glb +0 -0
  75. package/templates/animation-studio/public/hifi-cast/kaykit/Barbarian.glb +0 -0
  76. package/templates/animation-studio/public/hifi-cast/kaykit/Knight.glb +0 -0
  77. package/templates/animation-studio/public/hifi-cast/kaykit/Mage.glb +0 -0
  78. package/templates/animation-studio/public/hifi-cast/kaykit/Rogue.glb +0 -0
  79. package/templates/animation-studio/public/hifi-cast/kaykit/Rogue_Hooded.glb +0 -0
  80. package/templates/animation-studio/public/hifi-cast/khronos-report.json +295 -0
  81. package/templates/animation-studio/public/hifi-cast/quaternius-report.json +449 -0
  82. package/templates/animation-studio/public/hifi-cast/rpm/cesiumman.glb +0 -0
  83. package/templates/animation-studio/public/hifi-cast/rpm/fox.glb +0 -0
  84. package/templates/animation-studio/public/hifi-cast/rpm/riggedfigure.glb +0 -0
  85. package/templates/animation-studio/public/hifi-cast/rpm-report.json +301 -0
  86. package/templates/animation-studio/scripts/anim.ts +103 -0
  87. package/templates/animation-studio/scripts/animation-scene.ts +457 -0
  88. package/templates/animation-studio/scripts/asset-motion-probe.ts +450 -0
  89. package/templates/animation-studio/scripts/asset-render-probe.ts +152 -0
  90. package/templates/animation-studio/scripts/author-office-scene.ts +65 -0
  91. package/templates/animation-studio/scripts/build-cast-library.ts +97 -0
  92. package/templates/animation-studio/scripts/build-characters.ts +1543 -0
  93. package/templates/animation-studio/scripts/build-clip-library.ts +972 -0
  94. package/templates/animation-studio/scripts/clip-decision-cli.ts +51 -0
  95. package/templates/animation-studio/scripts/determinism-check.ts +48 -0
  96. package/templates/animation-studio/scripts/generate-scene.ts +95 -0
  97. package/templates/animation-studio/scripts/hifi-cast-validate.ts +572 -0
  98. package/templates/animation-studio/scripts/motion-evidence-cli.ts +150 -0
  99. package/templates/animation-studio/scripts/motion-evidence.ts +362 -0
  100. package/templates/animation-studio/scripts/preview-server.ts +52 -0
  101. package/templates/animation-studio/scripts/regen-manifest.ts +156 -0
  102. package/templates/animation-studio/scripts/render-core.ts +360 -0
  103. package/templates/animation-studio/scripts/render-live.ts +813 -0
  104. package/templates/animation-studio/scripts/render-parallel.ts +70 -0
  105. package/templates/animation-studio/scripts/render-server.ts +119 -0
  106. package/templates/animation-studio/scripts/resolve-asset.ts +669 -0
  107. package/templates/animation-studio/scripts/skeleton-overlay-cli.ts +82 -0
  108. package/templates/animation-studio/scripts/skeleton-overlay.ts +293 -0
  109. package/templates/animation-studio/scripts/studio-tools-demo.ts +45 -0
  110. package/templates/animation-studio/scripts/texture-bake.ts +297 -0
  111. package/templates/{cartoon-studio → animation-studio}/scripts/validate-characters.ts +0 -0
  112. package/templates/animation-studio/scripts/verify-extracted-overlay-cli.ts +264 -0
  113. package/templates/animation-studio/src/animation-episode-validator.ts +97 -0
  114. package/templates/animation-studio/src/animation-performance.ts +556 -0
  115. package/templates/animation-studio/src/aura-assets.ts +71 -0
  116. package/templates/animation-studio/src/character.ts +40 -0
  117. package/templates/animation-studio/src/director/compile-episode-document.ts +45 -0
  118. package/templates/animation-studio/src/director/director-heuristics.ts +697 -0
  119. package/templates/animation-studio/src/director/prompt-to-scene.ts +369 -0
  120. package/templates/animation-studio/src/empty-document.ts +77 -0
  121. package/templates/animation-studio/src/episode-document.ts +442 -0
  122. package/templates/animation-studio/src/examples/moon-garden.example.ts +183 -0
  123. package/templates/animation-studio/src/fidelity.ts +129 -0
  124. package/templates/animation-studio/src/graph.ts +14 -0
  125. package/templates/animation-studio/src/procedural-hdri.ts +243 -0
  126. package/templates/animation-studio/src/profile.ts +97 -0
  127. package/templates/animation-studio/src/render-live-route.ts +42 -0
  128. package/templates/animation-studio/src/render-modes.ts +137 -0
  129. package/templates/animation-studio/src/scene-player.ts +867 -0
  130. package/templates/animation-studio/src/set-templates.ts +361 -0
  131. package/templates/animation-studio/src/studio/episode-document-store.ts +72 -0
  132. package/templates/animation-studio/src/studio/scene-tool-registry.ts +86 -0
  133. package/templates/animation-studio/src/studio/scene-tools.ts +169 -0
  134. package/templates/animation-studio/tests/reports/animation-studio/hifi-cast-validation.json +938 -0
  135. package/templates/animation-studio/tsconfig.json +26 -0
  136. package/templates/{cartoon-studio → animation-studio}/vite.config.ts +6 -1
  137. package/templates/character-controller/README.md +33 -0
  138. package/templates/character-controller/index.html +19 -0
  139. package/templates/character-controller/package.json +23 -0
  140. package/templates/character-controller/playwright.config.ts +14 -0
  141. package/templates/character-controller/src/controller.ts +44 -0
  142. package/templates/character-controller/src/main.ts +62 -0
  143. package/templates/character-controller/tests/route-health.spec.ts +26 -0
  144. package/templates/character-controller/tests/screenshot.spec.ts +9 -0
  145. package/templates/character-controller/tsconfig.json +15 -0
  146. package/templates/cinematic-scene/package.json +1 -1
  147. package/templates/episode-builder/README.md +4 -4
  148. package/templates/episode-builder/package.json +1 -1
  149. package/templates/episode-builder/src/aura-assets.ts +1 -1
  150. package/templates/episode-builder/src/builder.ts +4 -4
  151. package/templates/episode-builder/src/episode.ts +21 -21
  152. package/templates/episode-builder/src/main.ts +20 -20
  153. package/templates/episode-builder/src/render-plan.ts +13 -13
  154. package/templates/episode-builder/tests/storyboard-playback.spec.ts +7 -7
  155. package/templates/fighting-game/package.json +1 -1
  156. package/templates/mini-game/package.json +1 -1
  157. package/templates/product-viewer/package.json +1 -1
  158. package/templates/{prompt-cartoon-channel → prompt-animation-channel}/README.md +5 -5
  159. package/templates/{cartoon-channel → prompt-animation-channel}/index.html +1 -1
  160. package/templates/{prompt-cartoon-channel → prompt-animation-channel}/package.json +2 -2
  161. package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/aura-assets.ts +1 -1
  162. package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/episode.ts +22 -22
  163. package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/main.ts +28 -28
  164. package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/render-plan.ts +13 -13
  165. package/templates/{cartoon-channel → prompt-animation-channel}/tests/route-health.spec.ts +1 -1
  166. package/templates/{prompt-cartoon-channel → prompt-animation-channel}/tests/storyboard-playback.spec.ts +8 -8
  167. package/templates/cartoon-studio/aura.assets.json +0 -400
  168. package/templates/cartoon-studio/package.json +0 -33
  169. package/templates/cartoon-studio/public/aura-assets/luma.authored.glb +0 -0
  170. package/templates/cartoon-studio/public/aura-assets/miko.authored.glb +0 -0
  171. package/templates/cartoon-studio/scripts/build-characters.ts +0 -738
  172. package/templates/cartoon-studio/scripts/build-dialogue-audio.ts +0 -262
  173. package/templates/cartoon-studio/scripts/episode.ts +0 -323
  174. package/templates/cartoon-studio/scripts/render-live.ts +0 -873
  175. package/templates/cartoon-studio/src/aura-assets.ts +0 -64
  176. package/templates/cartoon-studio/src/characters.ts +0 -65
  177. package/templates/cartoon-studio/src/episode-renderer.ts +0 -605
  178. package/templates/cartoon-studio/src/episode.ts +0 -306
  179. package/templates/cartoon-studio/src/main.ts +0 -400
  180. package/templates/cartoon-studio/src/render-live-route.ts +0 -913
  181. package/templates/cartoon-studio/src/render-plan.ts +0 -567
  182. package/templates/cartoon-studio/src/review.ts +0 -99
  183. package/templates/cartoon-studio/src/studio.ts +0 -101
  184. package/templates/cartoon-studio/test-results/.last-run.json +0 -4
  185. package/templates/cartoon-studio/tests/episode-render.spec.ts +0 -44
  186. package/templates/cartoon-studio/tests/motion-quality.spec.ts +0 -45
  187. package/templates/cartoon-studio/tests/route-health.spec.ts +0 -7
  188. package/templates/cartoon-studio/tests/storyboard-playback.spec.ts +0 -99
  189. package/templates/cartoon-studio/tests/visual-review.spec.ts +0 -21
  190. package/templates/cartoon-studio/tsconfig.json +0 -14
  191. package/templates/prompt-cartoon-channel/index.html +0 -13
  192. package/templates/prompt-cartoon-channel/src/sets.ts +0 -14
  193. /package/templates/{cartoon-channel → animation-channel}/aura.assets.json +0 -0
  194. /package/templates/{cartoon-channel → animation-channel}/playwright.config.ts +0 -0
  195. /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/luma.047f5e5f.glb +0 -0
  196. /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/luma.thumb.svg +0 -0
  197. /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/miko.047f5e5f.glb +0 -0
  198. /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/miko.thumb.svg +0 -0
  199. /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/moon-garden-feature-frame.png +0 -0
  200. /package/templates/{cartoon-channel → animation-channel}/src/aura-assets.ts +0 -0
  201. /package/templates/{cartoon-channel → animation-channel}/src/characters.ts +0 -0
  202. /package/templates/{cartoon-channel → animation-channel}/src/contract.ts +0 -0
  203. /package/templates/{cartoon-channel → animation-channel}/src/sets.ts +0 -0
  204. /package/templates/{cartoon-channel → animation-channel}/test-results/.last-run.json +0 -0
  205. /package/templates/{cartoon-channel → animation-channel}/tests/reports/prompt-animation/cartoon-sample-episode.png +0 -0
  206. /package/templates/{cartoon-channel → animation-channel}/tsconfig.json +0 -0
  207. /package/templates/{cartoon-studio → animation-studio}/playwright.config.ts +0 -0
  208. /package/templates/{cartoon-studio → animation-studio}/public/aura-assets/luma.thumb.svg +0 -0
  209. /package/templates/{cartoon-studio → animation-studio}/public/aura-assets/miko.thumb.svg +0 -0
  210. /package/templates/{cartoon-studio → animation-studio}/src/contract.ts +0 -0
  211. /package/templates/{prompt-cartoon-channel → prompt-animation-channel}/playwright.config.ts +0 -0
  212. /package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/characters.ts +0 -0
  213. /package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/contract.ts +0 -0
  214. /package/templates/{cartoon-studio → prompt-animation-channel}/src/sets.ts +0 -0
  215. /package/templates/{prompt-cartoon-channel → prompt-animation-channel}/tsconfig.json +0 -0
@@ -1,400 +0,0 @@
1
- import {
2
- applyShotPlaybackFrame,
3
- camera,
4
- captionCueAtTime,
5
- createAuraApp,
6
- createShotPlaybackPlan,
7
- effects,
8
- game,
9
- group,
10
- labels,
11
- lights,
12
- material,
13
- model,
14
- primitives,
15
- sampleAuraVoiceBridgeAtTime,
16
- sampleShotPlaybackPlan,
17
- scene
18
- } from "@aura3d/engine";
19
- import { assets } from "./aura-assets";
20
- import {
21
- episode,
22
- episodeContractId,
23
- missingCartoonCharacterAssets,
24
- publicCartoonAssetInstructions,
25
- requiredCartoonCharacterAssets,
26
- typedCartoonAssetSummary
27
- } from "./episode";
28
- import {
29
- accessibilityProofMetadata,
30
- auraVoicePackage,
31
- bridgeIssues,
32
- bridgeSampleAtThumbnail,
33
- captionFrameSyncSourceProof,
34
- captionTimingProof,
35
- deterministicScreenshotFixtures,
36
- glbVisemeRuntimeExample,
37
- promptAnimationEvidence,
38
- primitiveMouthRuntimeExample,
39
- phonemeVisemeDubSyncSourceProof,
40
- publishReadiness,
41
- renderOutputPackage,
42
- renderPlan,
43
- sampleRenderSourceWorkflow,
44
- visemeFrameSyncSourceProof,
45
- visemeTrack
46
- } from "./render-plan";
47
- import { cartoonStudioSupport, installCartoonStudioPanel } from "./studio";
48
-
49
- declare global {
50
- interface Window {
51
- __AURA3D_CARTOON_EPISODE_SEEK__?: (time: number) => void;
52
- __AURA3D_CARTOON_EPISODE_PROOF__?: CartoonEpisodeRouteProof;
53
- __AURA3D_CARTOON_TEMPLATE__?: CartoonEpisodeRouteProof;
54
- }
55
- }
56
-
57
- interface CartoonEpisodeRouteProof {
58
- readonly proofKind: "aura3d-cartoon-episode-proof";
59
- readonly contractId: string;
60
- readonly template: string;
61
- readonly storyBible: unknown;
62
- readonly shots: readonly unknown[];
63
- readonly captions: readonly unknown[];
64
- readonly visemes: readonly unknown[];
65
- readonly gestures: readonly unknown[];
66
- readonly assets: unknown;
67
- readonly renderStatus: unknown;
68
- readonly errors: readonly string[];
69
- readonly sourceOnlyAcceptedAsPublishProof: false;
70
- readonly shotIds: readonly string[];
71
- readonly captionIds: readonly string[];
72
- readonly playbackProbeTimes: readonly number[];
73
- readonly playbackProbeSamples: readonly unknown[];
74
- readonly renderQueueItems: number;
75
- readonly renderPreset: unknown;
76
- readonly typedAssets: unknown;
77
- readonly requiredTypedAssets: readonly string[];
78
- readonly missingTypedAssets: readonly string[];
79
- readonly assetCommands: readonly string[];
80
- readonly bridgeIssues: readonly unknown[];
81
- readonly promptAnimationEvidence: unknown;
82
- readonly publishReadiness: unknown;
83
- readonly studio: unknown;
84
- readonly sourceProofs: unknown;
85
- readonly sampleRenderSourceWorkflow: unknown;
86
- sampleAt(time: number): unknown;
87
- }
88
-
89
- const firstStoryboardShot = episode.storyboard.scenes[0]?.shots[0];
90
- const firstCaption = episode.captionTrack.cues[0];
91
- const thumbnailCapture = renderOutputPackage.thumbnailCapture;
92
- const thumbnailCaption = captionCueAtTime(episode.captionTrack, thumbnailCapture.time);
93
- const storyBible = episode.storyBible;
94
- const captureMode = new URLSearchParams(window.location.search).get("capture") === "thumbnail";
95
- const cartoonRenderPreset = createCartoonStudioRouteRenderPreset({
96
- name: "moon-garden-cartoon-studio",
97
- resolution: episode.episodePlan.runtime.resolution,
98
- materialStyle: { treatment: "cel" },
99
- reducedMotion: episode.episodePlan.runtime.reducedMotion,
100
- reducedFlash: true
101
- });
102
-
103
- const captionOverlay = document.createElement("div");
104
- captionOverlay.id = "caption-overlay";
105
- captionOverlay.textContent = firstCaption?.text ?? firstStoryboardShot?.storyBeat ?? "Aura3D cartoon studio";
106
- captionOverlay.style.cssText = [
107
- "position:fixed",
108
- captureMode ? "display:none" : "",
109
- "left:50%",
110
- "bottom:28px",
111
- "transform:translateX(-50%)",
112
- "max-width:min(840px,calc(100vw - 32px))",
113
- "padding:12px 18px",
114
- "border-radius:14px",
115
- "background:rgba(3,12,20,0.88)",
116
- "color:#f8fff2",
117
- "font:700 18px/1.35 ui-rounded, Trebuchet MS, sans-serif",
118
- "letter-spacing:0.01em",
119
- "text-align:center",
120
- "box-shadow:0 10px 30px rgba(0,0,0,0.28)",
121
- "z-index:10"
122
- ].join(";");
123
- document.body.appendChild(captionOverlay);
124
-
125
- const shotPlaybackPlan = createShotPlaybackPlan({
126
- timeline: episode.shotTimeline,
127
- performance: episode.performance,
128
- captions: episode.captionTrack,
129
- visemes: visemeTrack,
130
- runtimeNodeByCharacterId: {
131
- miko: "miko",
132
- luma: "luma"
133
- },
134
- loop: true
135
- });
136
-
137
- const playbackProbeTimes = [1, 21, 43] as const;
138
- const playbackProbeSamples = playbackProbeTimes.map((time) => sampleCartoonRouteAt(time));
139
- captionOverlay.dataset.shotId = playbackProbeSamples[0]?.shotId ?? "";
140
- captionOverlay.dataset.captionId = playbackProbeSamples[0]?.captionId ?? firstCaption?.captionId ?? "";
141
- document.body.dataset.cartoonShotCount = String(episode.shotTimeline.shots.length);
142
- document.body.dataset.cartoonCaptionCount = String(episode.captionTrack.cues.length);
143
- document.body.dataset.cartoonStoryBibleProps = String(storyBible.props.length);
144
- document.body.dataset.cartoonStudioPanels = cartoonStudioSupport.panels.join(",");
145
- if (!captureMode) installCartoonStudioPanel(document.body);
146
-
147
- // Ground the cartoon characters on the moon-garden path and normalize their
148
- // wildly different native scales (miko bounds ~0.066m tall, luma ~1.8m) to a
149
- // single on-screen height so neither floats nor dwarfs the other. Bounds come
150
- // from the generated typed assets (`boundsMetadata` in aura.assets.json):
151
- // miko -> min/max y [-0.013, 0.013], center origin
152
- // luma -> min/max y [0, 1.8], foot origin
153
- // The path box sits at y=0.05 with a 0.04-thick top, so its walkable surface is
154
- // at y = 0.05 + 0.02 = 0.07; both characters rest their lowest point there.
155
- // Local grounding helper (kept in-template so the scaffold builds against the
156
- // published @aura3d/engine). Grounds a scaled asset's lowest point on `floorY`
157
- // and normalizes its height to `targetHeight`.
158
- function groundedPlacement(
159
- bounds: { readonly min: readonly [number, number, number]; readonly max: readonly [number, number, number] },
160
- opts: { readonly targetHeight: number; readonly x: number; readonly z: number; readonly floorY: number }
161
- ): { position: [number, number, number]; scale: number } {
162
- const height = bounds.max[1] - bounds.min[1];
163
- const scale = height > 0 && opts.targetHeight > 0 ? opts.targetHeight / height : 1;
164
- const y = opts.floorY + -bounds.min[1] * scale;
165
- return { position: [opts.x, y, opts.z], scale };
166
- }
167
-
168
- const PATH_FLOOR_Y = 0.07;
169
- const CHARACTER_TARGET_HEIGHT = 1.5;
170
- const mikoBounds = { min: [-0.033, -0.013, -0.009], max: [0.033, 0.013, 0.008] } as const;
171
- const lumaBounds = { min: [-0.55, 0, -0.4], max: [0.55, 1.8, 0.4] } as const;
172
- const mikoPlacement = groundedPlacement(mikoBounds, { targetHeight: CHARACTER_TARGET_HEIGHT, x: -0.8, z: 0, floorY: PATH_FLOOR_Y });
173
- const lumaPlacement = groundedPlacement(lumaBounds, { targetHeight: CHARACTER_TARGET_HEIGHT, x: 0.8, z: 0, floorY: PATH_FLOOR_Y });
174
-
175
- const app = createAuraApp("#app", {
176
- scene: scene()
177
- .background("#081b2a")
178
- .add(
179
- model(assets.moonGarden, { name: "Moon Garden typed set asset" })
180
- .position(0, 0, -0.02)
181
- .scale(1)
182
- .runtime(game.runtimeNode("moonGarden", { tags: ["set", "typed-asset", "moon-garden"] }))
183
- )
184
- .add(
185
- model(assets.miko, { name: "Miko typed cartoon character" })
186
- .position(mikoPlacement.position[0], mikoPlacement.position[1], mikoPlacement.position[2])
187
- .scale(mikoPlacement.scale)
188
- .runtime(game.runtimeNode("miko", { tags: ["character", "miko", "typed-asset"] }))
189
- )
190
- .add(createMouthCard("miko:mouth", "Miko", [mikoPlacement.position[0], mikoPlacement.position[1] + CHARACTER_TARGET_HEIGHT * 0.92, 0.32], "#f8fff2"))
191
- .add(
192
- model(assets.luma, { name: "Luma typed cartoon character" })
193
- .position(lumaPlacement.position[0], lumaPlacement.position[1], lumaPlacement.position[2])
194
- .scale(lumaPlacement.scale)
195
- .runtime(game.runtimeNode("luma", { tags: ["character", "luma", "typed-asset"] }))
196
- )
197
- .add(createMouthCard("luma:mouth", "Luma", [lumaPlacement.position[0], lumaPlacement.position[1] + CHARACTER_TARGET_HEIGHT * 0.92, 0.32], "#40ffbf"))
198
- .add(
199
- primitives
200
- .box({ name: "moon garden path", material: material.pbr({ color: "#182d3f", roughness: 0.78 }) })
201
- .position(0, 0.05, 0)
202
- .scale([2.8, 0.04, 0.8])
203
- )
204
- .add(
205
- primitives
206
- .sphere({ name: "glow stones primitive fallback", material: material.emissive({ color: "#ffe18e", emissive: "#ffe18e", emissiveIntensity: 0.42 }) })
207
- .position(0.18, 0.16, 0.28)
208
- .scale([0.16, 0.08, 0.16])
209
- )
210
- .add(
211
- primitives
212
- .box({ name: "moon lilies primitive fallback", material: material.pbr({ color: "#f8fff2", roughness: 0.5 }) })
213
- .position(-0.38, 0.2, 0.18)
214
- .scale([0.12, 0.24, 0.04])
215
- )
216
- .add(captureMode ? group("thumbnail capture label placeholder") : labels.hud(firstCaption?.text ?? firstStoryboardShot?.storyBeat ?? "Aura3D cartoon studio"))
217
- .add(lights.studio({ intensity: 1.2 }))
218
- .add(effects.bloom({ intensity: 0.18, color: "#7de2ff" }))
219
- .camera(camera.perspective({ position: [0, 1.4, 4.2], target: [0, 0.7, 0], fov: 42 })),
220
- diagnostics: !captureMode
221
- });
222
-
223
- const cartoonEpisodeProof: CartoonEpisodeRouteProof = {
224
- proofKind: "aura3d-cartoon-episode-proof",
225
- contractId: episodeContractId,
226
- template: "cartoon-studio",
227
- storyBible,
228
- shots: episode.shotTimeline.shots,
229
- captions: episode.captionTrack.cues,
230
- visemes: visemeTrack.cues,
231
- gestures: episode.performance.cues,
232
- assets: typedCartoonAssetSummary,
233
- renderStatus: {
234
- route: renderPlan.route,
235
- renderQueueItems: renderPlan.items.length,
236
- outputs: renderPlan.outputs.map((output) => output.kind),
237
- preset: cartoonRenderPreset,
238
- sourceOnlyAcceptedAsPublishProof: false,
239
- publishReadyFromCurrentEvidence: publishReadiness.ready,
240
- issueCount: publishReadiness.issues.length
241
- },
242
- errors: bridgeIssues.map((issue) => String((issue as { message?: unknown }).message ?? issue)),
243
- sourceOnlyAcceptedAsPublishProof: false,
244
- shotIds: episode.shotTimeline.shots.map((shot) => shot.shotId),
245
- captionIds: episode.captionTrack.cues.map((caption) => caption.captionId),
246
- playbackProbeTimes,
247
- playbackProbeSamples,
248
- renderQueueItems: renderPlan.items.length,
249
- renderPreset: cartoonRenderPreset,
250
- typedAssets: typedCartoonAssetSummary,
251
- requiredTypedAssets: requiredCartoonCharacterAssets,
252
- missingTypedAssets: missingCartoonCharacterAssets,
253
- assetCommands: publicCartoonAssetInstructions,
254
- bridgeIssues,
255
- promptAnimationEvidence,
256
- publishReadiness,
257
- studio: cartoonStudioSupport,
258
- sourceProofs: {
259
- captionFrameSyncSourceProof,
260
- visemeFrameSyncSourceProof,
261
- phonemeVisemeDubSyncSourceProof
262
- },
263
- sampleRenderSourceWorkflow,
264
- sampleAt(time: number) {
265
- return sampleCartoonRouteAt(time);
266
- }
267
- };
268
- window.__AURA3D_CARTOON_EPISODE_PROOF__ = cartoonEpisodeProof;
269
- window.__AURA3D_CARTOON_TEMPLATE__ = cartoonEpisodeProof;
270
- const shotPlaybackApplyOptions = {
271
- primitiveMouthNodeByCharacterId: {
272
- miko: "miko:mouth",
273
- luma: "luma:mouth"
274
- },
275
- playAnimationClips: true,
276
- onCaption(caption: { readonly text?: string; readonly captionId?: string } | undefined, framePlan: { readonly shotId?: string }) {
277
- captionOverlay.textContent = caption?.text ?? firstCaption?.text ?? "";
278
- captionOverlay.dataset.shotId = framePlan.shotId ?? "";
279
- captionOverlay.dataset.captionId = caption?.captionId ?? "";
280
- }
281
- } as const;
282
-
283
- // Map a director action to an actual GLB clip so the characters play real skeletal
284
- // animation instead of standing in their imported bind (T) pose.
285
- function clipForAction(action: string | undefined): string {
286
- switch (action) {
287
- case "walk":
288
- case "move":
289
- return "Walking";
290
- case "wave":
291
- case "greet":
292
- case "point":
293
- case "react":
294
- case "celebrate":
295
- case "happy":
296
- return "Wave";
297
- case "jump":
298
- return "Jump";
299
- case "punch":
300
- case "action":
301
- case "clean":
302
- return "Punch";
303
- default:
304
- return "Idle"; // idle / speak / listen
305
- }
306
- }
307
-
308
- // Deterministically pose every character (position, rotation, animation clip, mouth)
309
- // at the requested time, injecting a real GLB clip per action so nobody is T-posed.
310
- function applyCartoonFrameAt(time: number) {
311
- const frame = sampleShotPlaybackPlan(shotPlaybackPlan, time);
312
- const nodeUpdates = frame.nodeUpdates.map((update) => ({
313
- ...update,
314
- animationClip: update.animationClip ?? clipForAction(update.action)
315
- }));
316
- applyShotPlaybackFrame(app, { ...frame, nodeUpdates }, shotPlaybackApplyOptions);
317
- }
318
- window.__AURA3D_CARTOON_EPISODE_SEEK__ = applyCartoonFrameAt;
319
-
320
- if (captureMode) {
321
- // Deterministic capture: the seek hook drives the rendered frame.
322
- applyCartoonFrameAt(1);
323
- } else {
324
- // Live preview: play the episode timeline on the runtime clock with real clips.
325
- app.onFrame((frame) => applyCartoonFrameAt(frame.time));
326
- }
327
-
328
- function createMouthCard(id: "miko:mouth" | "luma:mouth", name: string, position: readonly [number, number, number], color: string) {
329
- return primitives
330
- .box({
331
- name: `${name} primitive mouth card`,
332
- material: material.emissive({ color, emissive: color, emissiveIntensity: 0.32 })
333
- })
334
- .position(position[0], position[1], position[2])
335
- .scale([0.22, 0.035, 0.025])
336
- .runtime(game.runtimeNode(id, { tags: ["mouth", "primitive", name.toLowerCase()] }));
337
- }
338
-
339
- function createCartoonStudioRouteRenderPreset(input: {
340
- readonly name: string;
341
- readonly resolution: { readonly width: number; readonly height: number };
342
- readonly materialStyle: { readonly treatment: "cel" | "preserve-pbr" };
343
- readonly reducedMotion?: boolean | undefined;
344
- readonly reducedFlash?: boolean | undefined;
345
- }) {
346
- return {
347
- kind: "cartoon-render-preset-evidence",
348
- name: input.name,
349
- resolution: input.resolution,
350
- lights: ["soft-key", "cool-rim", "set-fill", "emissive-practicals"],
351
- shadows: { soft: true, contact: true },
352
- postprocess: {
353
- bloom: input.reducedFlash ? 0.08 : 0.18,
354
- colorGrade: "storybook-night",
355
- fogDepthCue: true
356
- },
357
- materialStyle: {
358
- treatment: input.materialStyle.treatment,
359
- outline: input.materialStyle.treatment === "cel",
360
- rampSteps: input.materialStyle.treatment === "cel" ? 4 : 7,
361
- saturation: 1.08,
362
- blackLineWeight: input.materialStyle.treatment === "cel" ? 0.9 : 0
363
- },
364
- frameBudgetMs: 16.7,
365
- debugOverlaysAllowedInExport: false,
366
- reducedMotion: input.reducedMotion ?? false,
367
- reducedFlash: input.reducedFlash ?? false
368
- } as const;
369
- }
370
-
371
- function sampleCartoonRouteAt(time: number) {
372
- const bridgeSample = sampleAuraVoiceBridgeAtTime(auraVoicePackage, time);
373
- const playbackSample = sampleShotPlaybackPlan(shotPlaybackPlan, time);
374
- const caption = captionCueAtTime(episode.captionTrack, time);
375
- const speakingCharacterId = bridgeSample.dialogue?.speakerId;
376
- return {
377
- time,
378
- frame: bridgeSample.frame,
379
- shotId: bridgeSample.shot?.shotId,
380
- sceneId: bridgeSample.shot?.sceneId,
381
- captionId: caption?.captionId,
382
- captionText: caption?.text,
383
- cameraMove: bridgeSample.shot?.camera.move,
384
- transitionOut: bridgeSample.shot?.transitionOut,
385
- dialogueLineId: bridgeSample.dialogue?.lineId,
386
- visemeId: bridgeSample.viseme?.primaryVisemeId,
387
- nodeUpdates: playbackSample.nodeUpdates.map((update) => ({
388
- characterId: update.characterId,
389
- action: speakingCharacterId === update.characterId ? "speak" : update.action,
390
- emotion: update.emotion,
391
- position: update.position
392
- })),
393
- sourceShotCharacters: (bridgeSample.shot?.characters ?? []).map((character) => ({
394
- characterId: character.characterId,
395
- action: speakingCharacterId === character.characterId ? "speak" : character.action,
396
- emotion: character.emotion,
397
- position: character.position
398
- }))
399
- };
400
- }