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
@@ -0,0 +1,51 @@
1
+ /**
2
+ * clip-decision-cli.ts — B1 standalone proof of the per-beat clip-decision record.
3
+ *
4
+ * Builds a real {@link PerformanceRig} for a synthetic full-humanoid skeleton from the shared
5
+ * standard library and samples a beat, emitting the {@link ClipDecision} so a unit test can assert
6
+ * the B1 contract fields are present and populated:
7
+ * { intent, clipId, source, bonesTouched, maxRotAmplitudeRad, maxTransAmplitude, reachedGLBRuntime }
8
+ * plus bodyBoneRotationRad + rootTranslation.
9
+ *
10
+ * Browser/GPU/Playwright-free: it drives `animation-performance.ts` directly (the same module
11
+ * scene-player.ts uses), so the proof is of the REAL decision producer, not a re-implementation.
12
+ *
13
+ * Usage: tsx scripts/clip-decision-cli.ts --intent talk --t 0.6
14
+ */
15
+ import { createSharedClipRegistry, createPerformanceRig, resolveIntent } from "../src/animation-performance.js";
16
+
17
+ function arg(name: string, fallback: string): string {
18
+ const i = process.argv.indexOf(`--${name}`);
19
+ return i >= 0 && process.argv[i + 1] ? process.argv[i + 1]! : fallback;
20
+ }
21
+
22
+ // A full-humanoid skeleton (so retargeting maps the body bones and the decision carries real motion).
23
+ const HUMANOID_NODES = [
24
+ "Hips", "Spine", "Chest", "UpperChest", "Neck", "Head",
25
+ "LeftShoulder", "LeftUpperArm", "LeftLowerArm", "LeftHand",
26
+ "RightShoulder", "RightUpperArm", "RightLowerArm", "RightHand",
27
+ "LeftUpperLeg", "LeftLowerLeg", "LeftFoot",
28
+ "RightUpperLeg", "RightLowerLeg", "RightFoot"
29
+ ];
30
+
31
+ function main(): void {
32
+ const requestedIntent = arg("intent", "talk");
33
+ const t = Number(arg("t", "0.6"));
34
+ const registry = createSharedClipRegistry();
35
+ const rig = createPerformanceRig(registry, { nodeNames: HUMANOID_NODES, embeddedClips: ["Idle"] });
36
+ // resolveIntent normally maps a beat → standard intent; here we honor the requested intent directly
37
+ // unless it is non-standard, in which case resolveIntent derives one.
38
+ const intent = resolveIntent({
39
+ clip: requestedIntent,
40
+ moving: requestedIntent === "walk" || requestedIntent === "run",
41
+ running: requestedIntent === "run",
42
+ speaking: requestedIntent === "talk",
43
+ anyDialogue: true
44
+ });
45
+ const { decision } = rig.poseFor(intent, t);
46
+ // poseFor emits reachedGLBRuntime:false (the player flips it true after applyRetargetedPose). We
47
+ // assert the FIELD EXISTS here; the gate test below covers the true case from the render summary.
48
+ console.log(JSON.stringify(decision));
49
+ }
50
+
51
+ main();
@@ -0,0 +1,48 @@
1
+ /**
2
+ * determinism-check.ts — renders the same document + range TWICE and verifies the
3
+ * frames are byte-identical, proving the render is deterministic given a document.
4
+ *
5
+ * Run: pnpm exec tsx --tsconfig tsconfig.base.json packages/create-aura3d/templates/animation-studio/scripts/determinism-check.ts
6
+ */
7
+
8
+ import { spawnSync } from "node:child_process";
9
+ import { createHash } from "node:crypto";
10
+ import { existsSync, readFileSync } from "node:fs";
11
+ import { dirname, resolve } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const REPO = resolve(__dirname, "..", "..", "..", "..", "..");
16
+ const TEMPLATE_ROOT = resolve(__dirname, "..");
17
+
18
+ function render(outDir: string): void {
19
+ const r = spawnSync(
20
+ "pnpm",
21
+ ["exec", "tsx", "--tsconfig", "tsconfig.base.json", "packages/create-aura3d/templates/animation-studio/scripts/render-live.ts"],
22
+ { cwd: REPO, stdio: "ignore", env: { ...process.env, AURA_OUTPUT_DIR: outDir, AURA_PREVIEW_RANGE: "4-6" } }
23
+ );
24
+ if (r.status !== 0) throw new Error(`render to ${outDir} failed (status ${r.status})`);
25
+ }
26
+
27
+ function hashFrame(outDir: string): string | null {
28
+ const p = resolve(TEMPLATE_ROOT, outDir, "frames", "first.png");
29
+ if (!existsSync(p)) return null;
30
+ return createHash("sha256").update(readFileSync(p)).digest("hex");
31
+ }
32
+
33
+ function main(): void {
34
+ console.log("rendering pass A (range 4-6) ...");
35
+ render("dist/episodes/determinism-a");
36
+ console.log("rendering pass B (range 4-6) ...");
37
+ render("dist/episodes/determinism-b");
38
+
39
+ const a = hashFrame("dist/episodes/determinism-a");
40
+ const b = hashFrame("dist/episodes/determinism-b");
41
+ console.log(`A first.png sha256 = ${a?.slice(0, 16)}…`);
42
+ console.log(`B first.png sha256 = ${b?.slice(0, 16)}…`);
43
+ const ok = a !== null && a === b;
44
+ console.log(`\nDETERMINISM ${ok ? "PASS" : "FAIL"} — same document ${ok ? "→ byte-identical frame." : "produced different frames."}`);
45
+ if (!ok) process.exitCode = 1;
46
+ }
47
+
48
+ main();
@@ -0,0 +1,95 @@
1
+ /**
2
+ * generate-scene.ts — the SECOND-SCENE test (heuristic Director).
3
+ *
4
+ * Builds a DIFFERENT scene input (different shots/dialogue/blocking intent), runs it
5
+ * through the deterministic Director → EpisodeDocument → validates it → writes the
6
+ * document JSON. Then `AURA_DOCUMENT=<that json> ... render-live.ts` renders it through
7
+ * the SAME generic player — proving the renderer + Director generalize beyond Moon Garden.
8
+ *
9
+ * HONEST SCOPE: it reuses the Moon Garden cast + set assets (so no catalog resolution is
10
+ * needed here) but generates entirely NEW direction (blocking, camera, shots, prop
11
+ * scatter, world-state). The captions still come from the Moon Garden dialogue track
12
+ * (dialogue-in-document is a follow-up). This proves the Director produces a *valid,
13
+ * renderable, distinct* scene — NOT that arbitrary prompts are "watchable" (the human
14
+ * rubric / watchability gate covers that, and remains the open risk).
15
+ *
16
+ * Run: pnpm exec tsx --tsconfig tsconfig.base.json packages/create-aura3d/templates/animation-studio/scripts/generate-scene.ts
17
+ */
18
+
19
+ import { mkdirSync, writeFileSync } from "node:fs";
20
+ import { dirname, resolve } from "node:path";
21
+ import { fileURLToPath } from "node:url";
22
+ import { compileEpisodeDocument } from "../src/director/compile-episode-document.js";
23
+ import type { DirectorSceneInput } from "../src/director/director-heuristics.js";
24
+ import { validateEpisodeDocument } from "../src/animation-episode-validator.js";
25
+ import { moonGardenDocument } from "../src/examples/moon-garden.example.js";
26
+
27
+ const __dirname = dirname(fileURLToPath(import.meta.url));
28
+ const OUT_DIR = resolve(__dirname, "..", "dist", "generated");
29
+ const OUT_PATH = resolve(OUT_DIR, "second-scene.document.json");
30
+
31
+ // A different scene: both characters ENTER from the sides, CONVERGE through the middle
32
+ // beats, and the speaker alternates — completely different staging from Moon Garden.
33
+ const secondScene: DirectorSceneInput = {
34
+ duration: 60,
35
+ characters: [
36
+ { id: "miko", entersFrom: "left" },
37
+ { id: "luma", entersFrom: "right" }
38
+ ],
39
+ shots: [
40
+ { shotId: "open", startTime: 0, endTime: 15 },
41
+ { shotId: "approach", startTime: 15, endTime: 32 },
42
+ { shotId: "together", startTime: 32, endTime: 48 },
43
+ { shotId: "close", startTime: 48, endTime: 60 }
44
+ ],
45
+ dialogue: [
46
+ { lineId: "l1", speakerId: "miko", startTime: 1, endTime: 14 },
47
+ { lineId: "l2", speakerId: "luma", startTime: 16, endTime: 31 },
48
+ { lineId: "l3", speakerId: "miko", startTime: 33, endTime: 47 },
49
+ { lineId: "l4", speakerId: "luma", startTime: 49, endTime: 59 }
50
+ ],
51
+ walkableBounds: { min: [-3.6, 0, -2], max: [3.6, 0, 2] },
52
+ props: [{ propId: "mushroom", count: 7, scaleRange: [0.06, 0.16], feetOffset: 2.8 }],
53
+ clips: { idle: "idle", walk: "walk", gesture: "wave" }
54
+ };
55
+
56
+ async function main(): Promise<void> {
57
+ const result = await compileEpisodeDocument({
58
+ id: "second-scene-001",
59
+ duration: 60,
60
+ assets: moonGardenDocument.assets,
61
+ set: moonGardenDocument.set,
62
+ scene: secondScene
63
+ });
64
+
65
+ const validation = validateEpisodeDocument(result.document, {
66
+ availableClipsByCharacter: {
67
+ miko: ["Loops"],
68
+ luma: ["Armature|ArmatureAction", "Armature|Armature.001Action", "Armature|PoseLib"]
69
+ }
70
+ });
71
+
72
+ mkdirSync(OUT_DIR, { recursive: true });
73
+ writeFileSync(OUT_PATH, `${JSON.stringify(result.document, null, 2)}\n`);
74
+
75
+ console.log("=== Director second-scene test (heuristics-only) ===");
76
+ console.log(`document: ${OUT_PATH}`);
77
+ console.log(`shots: ${result.document.shots.map((s) => `${s.shotId}[${s.startTime}-${s.endTime}] ${s.presetId}`).join(", ")}`);
78
+ console.log(
79
+ `blocking: ${result.document.blocking
80
+ .map((b) => `${b.characterId} (${b.shots.map((s) => `${s.shotId}:${s.waypoints.length}wp/${s.clip}`).join(", ")})`)
81
+ .join(" | ")}`
82
+ );
83
+ console.log(`setDressing: ${result.document.setDressing.length} props`);
84
+ console.log(`shape-valid: ${result.validation.ok} coherence-valid: ${validation.ok}`);
85
+ if (validation.errors.length) console.log("ERRORS:\n - " + validation.errors.join("\n - "));
86
+ if (validation.warnings.length) console.log("warnings:\n - " + validation.warnings.join("\n - "));
87
+ console.log(
88
+ `\nrender it:\n AURA_DOCUMENT=${OUT_PATH} AURA_OUTPUT_DIR=dist/episodes/second-scene \\\n` +
89
+ ` pnpm exec tsx --tsconfig tsconfig.base.json packages/create-aura3d/templates/animation-studio/scripts/render-live.ts`
90
+ );
91
+
92
+ if (!result.validation.ok || !validation.ok) process.exitCode = 1;
93
+ }
94
+
95
+ void main();