create-aura3d 1.3.2 → 1.4.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 (226) hide show
  1. package/dist/cli.js +10 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +11 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/showcase-spec-artifacts.d.ts +104 -0
  8. package/dist/showcase-spec-artifacts.d.ts.map +1 -0
  9. package/dist/showcase-spec-artifacts.js +142 -0
  10. package/dist/showcase-spec-artifacts.js.map +1 -0
  11. package/dist/showcase-spec-category-plan.d.ts +15 -0
  12. package/dist/showcase-spec-category-plan.d.ts.map +1 -0
  13. package/dist/showcase-spec-category-plan.js +45 -0
  14. package/dist/showcase-spec-category-plan.js.map +1 -0
  15. package/dist/showcase-spec-compiler.d.ts +5 -0
  16. package/dist/showcase-spec-compiler.d.ts.map +1 -0
  17. package/dist/showcase-spec-compiler.js +240 -0
  18. package/dist/showcase-spec-compiler.js.map +1 -0
  19. package/dist/showcase-spec-evidence.d.ts +7 -0
  20. package/dist/showcase-spec-evidence.d.ts.map +1 -0
  21. package/dist/showcase-spec-evidence.js +815 -0
  22. package/dist/showcase-spec-evidence.js.map +1 -0
  23. package/dist/showcase-spec-game-geometry-extractor.d.ts +21 -0
  24. package/dist/showcase-spec-game-geometry-extractor.d.ts.map +1 -0
  25. package/dist/showcase-spec-game-geometry-extractor.js +725 -0
  26. package/dist/showcase-spec-game-geometry-extractor.js.map +1 -0
  27. package/dist/showcase-spec-game-replacement-evidence.d.ts +14 -0
  28. package/dist/showcase-spec-game-replacement-evidence.d.ts.map +1 -0
  29. package/dist/showcase-spec-game-replacement-evidence.js +219 -0
  30. package/dist/showcase-spec-game-replacement-evidence.js.map +1 -0
  31. package/dist/showcase-spec-game-template-evidence.d.ts +72 -0
  32. package/dist/showcase-spec-game-template-evidence.d.ts.map +1 -0
  33. package/dist/showcase-spec-game-template-evidence.js +435 -0
  34. package/dist/showcase-spec-game-template-evidence.js.map +1 -0
  35. package/dist/showcase-spec-gameplay-evidence.d.ts +3 -0
  36. package/dist/showcase-spec-gameplay-evidence.d.ts.map +1 -0
  37. package/dist/showcase-spec-gameplay-evidence.js +108 -0
  38. package/dist/showcase-spec-gameplay-evidence.js.map +1 -0
  39. package/dist/showcase-spec-parser.d.ts +3 -0
  40. package/dist/showcase-spec-parser.d.ts.map +1 -0
  41. package/dist/showcase-spec-parser.js +662 -0
  42. package/dist/showcase-spec-parser.js.map +1 -0
  43. package/dist/showcase-spec-platformer-artifacts.d.ts +3 -0
  44. package/dist/showcase-spec-platformer-artifacts.d.ts.map +1 -0
  45. package/dist/showcase-spec-platformer-artifacts.js +276 -0
  46. package/dist/showcase-spec-platformer-artifacts.js.map +1 -0
  47. package/dist/showcase-spec-racing-artifacts.d.ts +3 -0
  48. package/dist/showcase-spec-racing-artifacts.d.ts.map +1 -0
  49. package/dist/showcase-spec-racing-artifacts.js +273 -0
  50. package/dist/showcase-spec-racing-artifacts.js.map +1 -0
  51. package/dist/showcase-spec-replacement-apply.d.ts +10 -0
  52. package/dist/showcase-spec-replacement-apply.d.ts.map +1 -0
  53. package/dist/showcase-spec-replacement-apply.js +166 -0
  54. package/dist/showcase-spec-replacement-apply.js.map +1 -0
  55. package/dist/showcase-spec-replacement-candidates.d.ts +16 -0
  56. package/dist/showcase-spec-replacement-candidates.d.ts.map +1 -0
  57. package/dist/showcase-spec-replacement-candidates.js +244 -0
  58. package/dist/showcase-spec-replacement-candidates.js.map +1 -0
  59. package/dist/showcase-spec-replacement-game-geometry.d.ts +4 -0
  60. package/dist/showcase-spec-replacement-game-geometry.d.ts.map +1 -0
  61. package/dist/showcase-spec-replacement-game-geometry.js +175 -0
  62. package/dist/showcase-spec-replacement-game-geometry.js.map +1 -0
  63. package/dist/showcase-spec-replacement-manifest.d.ts +41 -0
  64. package/dist/showcase-spec-replacement-manifest.d.ts.map +1 -0
  65. package/dist/showcase-spec-replacement-manifest.js +62 -0
  66. package/dist/showcase-spec-replacement-manifest.js.map +1 -0
  67. package/dist/showcase-spec-replacement-values.d.ts +9 -0
  68. package/dist/showcase-spec-replacement-values.d.ts.map +1 -0
  69. package/dist/showcase-spec-replacement-values.js +41 -0
  70. package/dist/showcase-spec-replacement-values.js.map +1 -0
  71. package/dist/showcase-spec-replacement.d.ts +13 -0
  72. package/dist/showcase-spec-replacement.d.ts.map +1 -0
  73. package/dist/showcase-spec-replacement.js +144 -0
  74. package/dist/showcase-spec-replacement.js.map +1 -0
  75. package/dist/showcase-spec-types.d.ts +304 -0
  76. package/dist/showcase-spec-types.d.ts.map +1 -0
  77. package/dist/showcase-spec-types.js +2 -0
  78. package/dist/showcase-spec-types.js.map +1 -0
  79. package/package.json +21 -2
  80. package/templates/animation-channel/package.json +1 -1
  81. package/templates/animation-channel/tests/screenshot.spec.ts +16 -0
  82. package/templates/animation-studio/index.html +12 -0
  83. package/templates/animation-studio/node_modules.publish-aside/.vite/deps/_metadata.json +8 -0
  84. package/templates/animation-studio/node_modules.publish-aside/.vite/deps/package.json +3 -0
  85. package/templates/animation-studio/package.json +1 -1
  86. package/templates/animation-studio/scripts/animation-scene.ts +1 -1
  87. package/templates/animation-studio/scripts/asset-motion-probe.ts +7 -1
  88. package/templates/animation-studio/scripts/author-office-scene.ts +1 -1
  89. package/templates/animation-studio/scripts/build-characters.ts +1 -1
  90. package/templates/animation-studio/scripts/render-live.ts +24 -0
  91. package/templates/animation-studio/src/director/director-heuristics.ts +2 -2
  92. package/templates/animation-studio/src/director/{prompt-to-scene.ts → prompt-scene.ts} +74 -6
  93. package/templates/animation-studio/studio/src/App.tsx +146 -78
  94. package/templates/animation-studio/studio/src/components/Console.tsx +8 -2
  95. package/templates/animation-studio/studio/src/components/Inspector.tsx +57 -1
  96. package/templates/animation-studio/studio/src/components/Stage.tsx +10 -5
  97. package/templates/animation-studio/studio/src/components/Timeline.tsx +49 -2
  98. package/templates/animation-studio/studio/src/state/mapDocument.ts +13 -2
  99. package/templates/animation-studio/studio/src/state/sceneTool.ts +20 -9
  100. package/templates/animation-studio/studio/src/state/types.ts +8 -0
  101. package/templates/animation-studio/tests/route-health.spec.ts +33 -0
  102. package/templates/animation-studio/tests/screenshot.spec.ts +30 -0
  103. package/templates/character-controller/package.json +1 -1
  104. package/templates/character-controller/src/main.ts +18 -1
  105. package/templates/cinematic-scene/package.json +1 -1
  106. package/templates/cinematic-scene/tests/screenshot.spec.ts +3 -3
  107. package/templates/episode-builder/package.json +1 -1
  108. package/templates/episode-builder/tests/screenshot.spec.ts +15 -0
  109. package/templates/falling-blocks-starter/README.md +18 -0
  110. package/templates/falling-blocks-starter/index.html +23 -0
  111. package/templates/falling-blocks-starter/package.json +21 -0
  112. package/templates/falling-blocks-starter/playwright.config.ts +12 -0
  113. package/templates/falling-blocks-starter/public/aura-assets/showcaseBlockfallCabinet.679d52fe.glb +0 -0
  114. package/templates/falling-blocks-starter/public/aura-assets/showcaseBlockfallCabinet.thumb.svg +1 -0
  115. package/templates/falling-blocks-starter/src/aura-assets.ts +20 -0
  116. package/templates/falling-blocks-starter/src/main.ts +358 -0
  117. package/templates/falling-blocks-starter/tests/playable.spec.ts +85 -0
  118. package/templates/falling-blocks-starter/tests/route-health.spec.ts +34 -0
  119. package/templates/falling-blocks-starter/tsconfig.json +13 -0
  120. package/templates/fighting-game/package.json +1 -1
  121. package/templates/fighting-game/tests/screenshot.spec.ts +15 -0
  122. package/templates/mini-game/README.md +13 -0
  123. package/templates/mini-game/index.html +1 -1
  124. package/templates/mini-game/package.json +2 -2
  125. package/templates/mini-game/src/main.ts +251 -21
  126. package/templates/mini-game/tests/playable.spec.ts +49 -0
  127. package/templates/mini-game/tests/screenshot.spec.ts +37 -32
  128. package/templates/product-viewer/package.json +1 -1
  129. package/templates/product-viewer/tests/screenshot.spec.ts +4 -4
  130. package/templates/prompt-animation-channel/package.json +1 -1
  131. package/templates/prompt-animation-channel/tests/screenshot.spec.ts +15 -0
  132. package/templates/racing-starter/README.md +27 -0
  133. package/templates/racing-starter/index.html +23 -0
  134. package/templates/racing-starter/package.json +21 -0
  135. package/templates/racing-starter/playwright.config.ts +12 -0
  136. package/templates/racing-starter/public/aura-assets/showcaseCleanSportsCar.1c69283f.glb +0 -0
  137. package/templates/racing-starter/public/aura-assets/showcaseCleanSportsCar.thumb.svg +1 -0
  138. package/templates/racing-starter/public/aura-assets/showcaseReadableKartCircuit.5cbb912e.glb +0 -0
  139. package/templates/racing-starter/public/aura-assets/showcaseReadableKartCircuit.thumb.svg +1 -0
  140. package/templates/racing-starter/src/aura-assets.ts +36 -0
  141. package/templates/racing-starter/src/main.ts +280 -0
  142. package/templates/racing-starter/tests/playable.spec.ts +93 -0
  143. package/templates/racing-starter/tests/route-health.spec.ts +40 -0
  144. package/templates/racing-starter/tsconfig.json +13 -0
  145. package/templates/three-compat-architecture-interior/index.html +16 -0
  146. package/templates/three-compat-architecture-interior/package.json +21 -0
  147. package/templates/three-compat-architecture-interior/playwright.config.ts +14 -0
  148. package/templates/three-compat-architecture-interior/src/main.ts +27 -0
  149. package/templates/three-compat-architecture-interior/tests/route-health.spec.ts +16 -0
  150. package/templates/three-compat-architecture-interior/tests/screenshot.spec.ts +15 -0
  151. package/templates/three-compat-architecture-interior/tsconfig.json +19 -0
  152. package/templates/three-compat-asset-inspector/index.html +16 -0
  153. package/templates/three-compat-asset-inspector/package.json +21 -0
  154. package/templates/three-compat-asset-inspector/playwright.config.ts +14 -0
  155. package/templates/three-compat-asset-inspector/src/main.ts +17 -0
  156. package/templates/three-compat-asset-inspector/tests/route-health.spec.ts +16 -0
  157. package/templates/three-compat-asset-inspector/tests/screenshot.spec.ts +15 -0
  158. package/templates/three-compat-asset-inspector/tsconfig.json +19 -0
  159. package/templates/three-compat-character-viewer/index.html +16 -0
  160. package/templates/three-compat-character-viewer/package.json +21 -0
  161. package/templates/three-compat-character-viewer/playwright.config.ts +14 -0
  162. package/templates/three-compat-character-viewer/src/main.ts +17 -0
  163. package/templates/three-compat-character-viewer/tests/route-health.spec.ts +16 -0
  164. package/templates/three-compat-character-viewer/tests/screenshot.spec.ts +15 -0
  165. package/templates/three-compat-character-viewer/tsconfig.json +19 -0
  166. package/templates/three-compat-custom-threejs-migration/index.html +16 -0
  167. package/templates/three-compat-custom-threejs-migration/package.json +21 -0
  168. package/templates/three-compat-custom-threejs-migration/playwright.config.ts +14 -0
  169. package/templates/three-compat-custom-threejs-migration/src/main.ts +16 -0
  170. package/templates/three-compat-custom-threejs-migration/tests/route-health.spec.ts +16 -0
  171. package/templates/three-compat-custom-threejs-migration/tests/screenshot.spec.ts +15 -0
  172. package/templates/three-compat-custom-threejs-migration/tsconfig.json +19 -0
  173. package/templates/three-compat-large-scene/index.html +16 -0
  174. package/templates/three-compat-large-scene/package.json +21 -0
  175. package/templates/three-compat-large-scene/playwright.config.ts +14 -0
  176. package/templates/three-compat-large-scene/src/main.ts +31 -0
  177. package/templates/three-compat-large-scene/tests/route-health.spec.ts +16 -0
  178. package/templates/three-compat-large-scene/tests/screenshot.spec.ts +15 -0
  179. package/templates/three-compat-large-scene/tsconfig.json +19 -0
  180. package/templates/three-compat-material-authoring/index.html +16 -0
  181. package/templates/three-compat-material-authoring/package.json +21 -0
  182. package/templates/three-compat-material-authoring/playwright.config.ts +14 -0
  183. package/templates/three-compat-material-authoring/src/main.ts +33 -0
  184. package/templates/three-compat-material-authoring/tests/route-health.spec.ts +16 -0
  185. package/templates/three-compat-material-authoring/tests/screenshot.spec.ts +15 -0
  186. package/templates/three-compat-material-authoring/tsconfig.json +19 -0
  187. package/templates/three-compat-postprocess-scene/index.html +16 -0
  188. package/templates/three-compat-postprocess-scene/package.json +21 -0
  189. package/templates/three-compat-postprocess-scene/playwright.config.ts +14 -0
  190. package/templates/three-compat-postprocess-scene/src/main.ts +17 -0
  191. package/templates/three-compat-postprocess-scene/tests/route-health.spec.ts +16 -0
  192. package/templates/three-compat-postprocess-scene/tests/screenshot.spec.ts +15 -0
  193. package/templates/three-compat-postprocess-scene/tsconfig.json +19 -0
  194. package/templates/three-compat-premium-product-viewer/index.html +16 -0
  195. package/templates/three-compat-premium-product-viewer/package.json +21 -0
  196. package/templates/three-compat-premium-product-viewer/playwright.config.ts +14 -0
  197. package/templates/three-compat-premium-product-viewer/src/main.ts +18 -0
  198. package/templates/three-compat-premium-product-viewer/tests/route-health.spec.ts +16 -0
  199. package/templates/three-compat-premium-product-viewer/tests/screenshot.spec.ts +15 -0
  200. package/templates/three-compat-premium-product-viewer/tsconfig.json +19 -0
  201. package/templates/animation-channel/public/aura-assets/moon-garden-feature-frame.png +0 -0
  202. package/templates/animation-channel/tests/reports/prompt-animation/cartoon-sample-episode.png +0 -0
  203. package/templates/animation-studio/dist/episodes/scene/episode-3d.webm +0 -0
  204. package/templates/animation-studio/dist/episodes/scene/frames/action.png +0 -0
  205. package/templates/animation-studio/dist/episodes/scene/frames/dialogue.png +0 -0
  206. package/templates/animation-studio/dist/episodes/scene/frames/final.png +0 -0
  207. package/templates/animation-studio/dist/episodes/scene/frames/first.png +0 -0
  208. package/templates/animation-studio/dist/episodes/scene/frames/mouth-closed.png +0 -0
  209. package/templates/animation-studio/dist/episodes/scene/frames/mouth-open.png +0 -0
  210. package/templates/animation-studio/dist/episodes/scene/render-live-summary.json +0 -5616
  211. package/templates/animation-studio/dist/episodes/scene/skeleton-overlays/broken.png +0 -0
  212. package/templates/animation-studio/dist/episodes/scene/skeleton-overlays/chefs.png +0 -0
  213. package/templates/animation-studio/dist/episodes/scene/skeleton-overlays/customer.png +0 -0
  214. package/templates/animation-studio/dist/episodes/scene/skeleton-overlays/worker-1.png +0 -0
  215. package/templates/animation-studio/dist/episodes/scene/skeleton-overlays/worker-2.png +0 -0
  216. package/templates/animation-studio/dist/generated/second-scene.document.json +0 -1210
  217. package/templates/animation-studio/dist/generated/studio-edited.document.json +0 -1196
  218. package/templates/animation-studio/dist/scene/inshader-accept.document.json +0 -1
  219. package/templates/animation-studio/dist/scene/inshader-test.document.json +0 -1
  220. package/templates/animation-studio/dist/scene/integ.document.json +0 -1
  221. package/templates/animation-studio/dist/scene/working.document.json +0 -594
  222. package/templates/animation-studio/dist/scene/working.history.json +0 -1
  223. package/templates/animation-studio/studio/dist/assets/index-i8URxOOt.css +0 -1
  224. package/templates/animation-studio/studio/dist/assets/index-pC9hdZ-B.js +0 -11
  225. package/templates/animation-studio/studio/dist/index.html +0 -19
  226. package/templates/animation-studio/tests/reports/animation-studio/hifi-cast-validation.json +0 -938
@@ -61,6 +61,12 @@ export interface RuntimeCharacter {
61
61
  rigGrade?: "A" | "B" | "C" | "D";
62
62
  /** M7 — dominant motion source the render played (mocap/extracted/procedural…), when recorded. */
63
63
  motionSource?: string;
64
+ /** Default performance clip id. */
65
+ defaultClip?: string;
66
+ /** Mouth morph target index for lip-sync. */
67
+ mouthMorphIndex?: number;
68
+ /** Foot IK configuration (truthy when enabled). */
69
+ footIk?: unknown;
64
70
  }
65
71
 
66
72
  export interface RuntimeShotBlocking {
@@ -254,6 +260,8 @@ export function mapDocument(doc: RuntimeDocument): EpisodeDocument {
254
260
 
255
261
  const cast: CastMember[] = rChars.map((c) => {
256
262
  const { source, sourceLabel } = castProvenance(c);
263
+ const fidelity =
264
+ fidelityById.get(c.id) ?? { id: c.id, grade: "C", previz: true, reason: "previz: ungraded" };
257
265
  return {
258
266
  id: c.id,
259
267
  name: cap(c.id),
@@ -263,8 +271,11 @@ export function mapDocument(doc: RuntimeDocument): EpisodeDocument {
263
271
  lines: linesPerSpeaker(c.id),
264
272
  source,
265
273
  sourceLabel,
266
- fidelity:
267
- fidelityById.get(c.id) ?? { id: c.id, grade: "C", previz: true, reason: "previz: ungraded" }
274
+ fidelity,
275
+ defaultClip: c.defaultClip,
276
+ mouthMorphIndex: c.mouthMorphIndex,
277
+ footIk: !!c.footIk,
278
+ gradeAwareIntent: `${fidelity.grade}-grade`
268
279
  };
269
280
  });
270
281
 
@@ -16,16 +16,27 @@ export interface VerbSpec {
16
16
  desc: string;
17
17
  }
18
18
 
19
+ // The REAL CLI grammar (animation-scene.ts) — every entry here, inserted verbatim with its
20
+ // placeholders filled, is accepted by the CLI's switch/flag parser. These strings are also
21
+ // surfaced verbatim to LLMs, so they must never advertise a syntax the validator rejects.
19
22
  export const VERBS: VerbSpec[] = [
20
- { verb: "set", tail: "<name> --hdr <mood>", desc: "Define / re-light the active set" },
21
- { verb: "cast add", tail: "<name>", desc: "Cast a character into the scene" },
22
- { verb: "cast remove", tail: "<name>", desc: "Remove a character" },
23
- { verb: "shot add", tail: "--after <id>", desc: "Block a new shot" },
23
+ { verb: "new", tail: '--prompt "<scene>" [--full]', desc: "Start a new working scene from a prompt" },
24
+ { verb: "set", tail: '<studio|garage|office|kitchen|moon-garden|space-station|meadow> | --query "<setting>"', desc: "Choose the active set template" },
25
+ { verb: "cast add", tail: '--id <id> --query "<look>" [--scale <s>]', desc: "Cast a character (catalog resolve)" },
26
+ { verb: "prop add", tail: '--id <id> --query "<look>"', desc: "Register a prop from the catalog" },
27
+ { verb: "shot add", tail: "--id <id> --preset <preset> --duration <s>", desc: "Block a new shot" },
28
+ { verb: "shot remove", tail: "--id <id>", desc: "Remove a shot" },
24
29
  { verb: "shot retime", tail: "--id <id> --duration <s>", desc: "Change a shot's duration" },
25
- { verb: "cam", tail: "<wide|medium|close|orbit>", desc: "Set the active shot camera" },
26
- { verb: "light add", tail: "--type rim", desc: "Add a light to the set" },
27
- { verb: "fx add", tail: "<name>", desc: "Add an effect to the timeline" },
28
- { verb: "render", tail: "[--shot <id>]", desc: "Render a low-fi preview" }
30
+ { verb: "camera", tail: "--shot <id> --preset <establishing|medium|two-shot|close-up>", desc: "Set a shot's camera" },
31
+ { verb: "dialogue", tail: '--line <id> --speaker <id> --text "<line>" --start <s>', desc: "Write a dialogue line" },
32
+ { verb: "block", tail: "--character <id> --shot <id> --to <x,z> [--clip <clip>]", desc: "Move a character in a shot" },
33
+ { verb: "gesture", tail: "--character <id> --shot <id> --clip <clip>", desc: "Queue a gesture clip for a character" },
34
+ { verb: "dress", tail: "--prop <id> --at <x,z> [--scale <s>]", desc: "Place a registered prop on the set" },
35
+ { verb: "scale", tail: "--character <id> --to <s>", desc: "Rescale a character" },
36
+ { verb: "show", tail: "", desc: "Print the scene summary" },
37
+ { verb: "validate", tail: "", desc: "Check scene coherence" },
38
+ { verb: "undo", tail: "", desc: "Undo the last committed edit" },
39
+ { verb: "render", tail: "[--shot <id>]", desc: "Render a low-fi preview (shot or full sequence)" }
29
40
  ];
30
41
 
31
42
  export interface ParsedCommand {
@@ -47,7 +58,7 @@ export function parse(raw: string): ParsedCommand {
47
58
  const toks = head.split(/\s+/).filter(Boolean);
48
59
  let verb = toks[0] || "";
49
60
  let rest = toks.slice(1);
50
- if (["cast", "shot", "light", "fx"].includes(verb) && rest[0]) {
61
+ if (["cast", "shot", "prop"].includes(verb) && rest[0]) {
51
62
  verb += " " + rest[0];
52
63
  rest = rest.slice(1);
53
64
  }
@@ -39,6 +39,14 @@ export interface CastMember {
39
39
  sourceLabel: string;
40
40
  /** M7 — honest fidelity tier (A/B/C). C is "previz" — never presented as finished. */
41
41
  fidelity: CharacterFidelity;
42
+ /** Default performance clip id (e.g. "idle"). */
43
+ defaultClip?: string;
44
+ /** Mouth morph target index for lip-sync; -1 when absent. */
45
+ mouthMorphIndex?: number;
46
+ /** Whether foot IK is enabled for this cast member. */
47
+ footIk?: boolean;
48
+ /** Read-only grade-aware performance intent label. */
49
+ gradeAwareIntent?: string;
42
50
  }
43
51
 
44
52
  export interface SetEntity {
@@ -0,0 +1,33 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { expect, test } from "@playwright/test";
4
+
5
+ test.setTimeout(60_000);
6
+
7
+ // The animation-studio route is the generic scene player (render-live-route.ts ->
8
+ // scene-player.ts). Its readiness contract is window.__AURA_LIVE_ROUTE_READY__ /
9
+ // __AURA_LIVE_ROUTE_ERROR__, not the createAuraApp data-aura3d-ready attribute.
10
+ test("Aura3D animation studio live route reaches ready state", async ({ page }) => {
11
+ await page.goto("/");
12
+ await expect
13
+ .poll(
14
+ () =>
15
+ page.evaluate(() => {
16
+ const w = window as unknown as {
17
+ __AURA_LIVE_ROUTE_READY__?: { ready?: boolean; backend?: string };
18
+ __AURA_LIVE_ROUTE_ERROR__?: string;
19
+ };
20
+ if (w.__AURA_LIVE_ROUTE_ERROR__) return `error: ${w.__AURA_LIVE_ROUTE_ERROR__}`;
21
+ return w.__AURA_LIVE_ROUTE_READY__?.ready === true ? "ready" : "pending";
22
+ }),
23
+ { timeout: 45_000 }
24
+ )
25
+ .toBe("ready");
26
+ const proof = await page.evaluate(
27
+ () => (window as unknown as { __AURA_LIVE_ROUTE_READY__?: { ready?: boolean; backend?: string } }).__AURA_LIVE_ROUTE_READY__
28
+ );
29
+ expect(proof?.ready).toBe(true);
30
+ expect(typeof proof?.backend).toBe("string");
31
+ mkdirSync(resolve("tests/reports"), { recursive: true });
32
+ writeFileSync(resolve("tests/reports/route-health.json"), `${JSON.stringify({ ready: true, backend: proof?.backend }, null, 2)}\n`);
33
+ });
@@ -0,0 +1,30 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { expect, test } from "@playwright/test";
4
+
5
+ test.setTimeout(60_000);
6
+
7
+ // Waits on the scene player's real readiness contract (__AURA_LIVE_ROUTE_READY__),
8
+ // then captures the rendered route as visual evidence.
9
+ test("Aura3D animation studio screenshot shows content", async ({ page }) => {
10
+ await page.goto("/");
11
+ await expect
12
+ .poll(
13
+ () =>
14
+ page.evaluate(() => {
15
+ const w = window as unknown as {
16
+ __AURA_LIVE_ROUTE_READY__?: { ready?: boolean };
17
+ __AURA_LIVE_ROUTE_ERROR__?: string;
18
+ };
19
+ if (w.__AURA_LIVE_ROUTE_ERROR__) return `error: ${w.__AURA_LIVE_ROUTE_ERROR__}`;
20
+ return w.__AURA_LIVE_ROUTE_READY__?.ready === true ? "ready" : "pending";
21
+ }),
22
+ { timeout: 45_000 }
23
+ )
24
+ .toBe("ready");
25
+ const screenshot = await page.screenshot({ fullPage: false });
26
+ mkdirSync(resolve("tests/reports"), { recursive: true });
27
+ writeFileSync(resolve("tests/reports/screenshot.png"), screenshot);
28
+ writeFileSync(resolve("tests/reports/screenshot.json"), `${JSON.stringify({ bytes: screenshot.byteLength }, null, 2)}\n`);
29
+ expect(screenshot.byteLength).toBeGreaterThan(1000);
30
+ });
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@aura3d/animation": "1.3.2",
15
- "@aura3d/engine": "1.3.2",
15
+ "@aura3d/engine": "1.3.3",
16
16
  "@aura3d/physics": "1.3.2"
17
17
  },
18
18
  "devDependencies": {
@@ -1,6 +1,7 @@
1
1
  // Character controller preview: keyboard input -> kinematic speed -> @aura3d/animation locomotion
2
2
  // kit (idle/walk/run blended by speed) -> live proof object. Hold a direction key (W/A/S/D or
3
- // arrows) to walk; hold Shift to run.
3
+ // arrows) to walk; hold Shift to run. A minimal Aura3D stage renders beneath the HUD.
4
+ import { camera, createAuraApp, lights, material, primitives, scene } from "@aura3d/engine";
4
5
  import { createLocomotionKit } from "@aura3d/animation";
5
6
  import { defaultCharacterControllerTuning, stepCharacterSpeed, type CharacterControllerState } from "./controller.js";
6
7
 
@@ -32,6 +33,22 @@ hud.id = "character-controller-hud";
32
33
  hud.style.cssText = "font:14px monospace;padding:16px;color:#6cf;background:#0c0f16;min-height:140px";
33
34
  root.appendChild(hud);
34
35
 
36
+ // Minimal visual stage: a capsule stand-in on a floor so the route renders a real
37
+ // Aura3D scene alongside the locomotion HUD proof.
38
+ const stage = document.createElement("div");
39
+ stage.id = "character-controller-stage";
40
+ stage.style.cssText = "height:320px";
41
+ root.appendChild(stage);
42
+ createAuraApp(stage, {
43
+ scene: scene()
44
+ .background("#0c0f16")
45
+ .camera(camera.orbit({ target: [0, 1, 0], distance: 5 }))
46
+ .add(primitives.box({ name: "floor", size: [6, 0.1, 6], position: [0, -0.05, 0], material: material.pbr({ color: "#151b27", roughness: 0.9 }), receiveShadow: true }))
47
+ .add(primitives.capsule({ name: "character stand-in", size: [0.7, 1.7, 0.7], position: [0, 1.2, 0], material: material.pbr({ color: "#6cb1f0", roughness: 0.5 }), castShadow: true }))
48
+ .add(lights.ambient({ intensity: 0.35 }))
49
+ .add(lights.directional({ name: "key", position: [3, 5, 2], intensity: 1.4 }))
50
+ });
51
+
35
52
  let state: CharacterControllerState = { speed: 0 };
36
53
  let last = 0;
37
54
 
@@ -11,7 +11,7 @@
11
11
  "test": "playwright test tests/route-health.spec.ts tests/screenshot.spec.ts --workers=1"
12
12
  },
13
13
  "dependencies": {
14
- "@aura3d/engine": "1.3.2"
14
+ "@aura3d/engine": "1.3.3"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@playwright/test": "^1.52.0",
@@ -31,8 +31,8 @@ test("Aura3D cinematic scene screenshot shows the rainy neon hero prompt", async
31
31
  const luminance = r * 0.2126 + g * 0.7152 + b * 0.0722;
32
32
  if (luminance > 30) buckets.add(`${r >> 5}-${g >> 5}-${b >> 5}`);
33
33
  if (b > 110 && g > 90 && b > r * 1.22) cyanPixels += 1;
34
- if (r > 160 && g > 105 && b < 125) amberPixels += 1;
35
- if (r > 165 && g > 185 && b > 205) rainPixels += 1;
34
+ if (r > 145 && g > 105 && b < 180 && r >= g * 0.95 && g >= b * 0.65) amberPixels += 1;
35
+ if (r > 130 && g > 140 && b > 145 && Math.max(r, g, b) - Math.min(r, g, b) < 75) rainPixels += 1;
36
36
  if (y < target.height * 0.36 && ((b > 95 && g > 65 && b > r * 1.12) || (r > 105 && g > 62 && b < 95))) wetReflectionPixels += 1;
37
37
  if (x > target.width * 0.32 && x < target.width * 0.68 && y > target.height * 0.26 && y < target.height * 0.78 && luminance > 75) centerHeroPixels += 1;
38
38
  if (luminance > 8 && luminance < 36 && b >= r && x > target.width * 0.08 && x < target.width * 0.92) darkAlleyPixels += 1;
@@ -50,7 +50,7 @@ test("Aura3D cinematic scene screenshot shows the rainy neon hero prompt", async
50
50
  expect(profile.rainPixels).toBeGreaterThan(90);
51
51
  expect(profile.wetReflectionPixels).toBeGreaterThan(60);
52
52
  expect(profile.centerHeroPixels).toBeGreaterThan(600);
53
- expect(profile.darkAlleyPixels).toBeGreaterThan(180);
53
+ expect(profile.darkAlleyPixels).toBeGreaterThan(150);
54
54
  expect(profile.uniqueBuckets).toBeGreaterThan(22);
55
55
  expect(screenshot.byteLength).toBeGreaterThan(1000);
56
56
  });
@@ -11,7 +11,7 @@
11
11
  "test": "playwright test tests/route-health.spec.ts tests/storyboard-playback.spec.ts --workers=1"
12
12
  },
13
13
  "dependencies": {
14
- "@aura3d/engine": "1.3.2"
14
+ "@aura3d/engine": "1.3.3"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@playwright/test": "^1.52.0",
@@ -0,0 +1,15 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { expect, test } from "@playwright/test";
4
+
5
+ test.setTimeout(60_000);
6
+
7
+ test("Aura3D episode builder screenshot shows content", async ({ page }) => {
8
+ await page.goto("/");
9
+ await expect.poll(() => page.locator("body").getAttribute("data-aura3d-ready"), { timeout: 45_000 }).toBe("true");
10
+ const screenshot = await page.screenshot({ fullPage: false });
11
+ mkdirSync(resolve("tests/reports"), { recursive: true });
12
+ writeFileSync(resolve("tests/reports/screenshot.png"), screenshot);
13
+ writeFileSync(resolve("tests/reports/screenshot.json"), `${JSON.stringify({ bytes: screenshot.byteLength }, null, 2)}\n`);
14
+ expect(screenshot.byteLength).toBeGreaterThan(1000);
15
+ });
@@ -0,0 +1,18 @@
1
+ # Aura3D Falling Blocks Starter
2
+
3
+ Keyboard-playable falling-block starter using only the public
4
+ `@aura3d/engine` API.
5
+
6
+ - The arcade cabinet is a typed GLB asset in `src/aura-assets.ts`.
7
+ - `game.fallingBlocks(...)` owns board state, movement, rotation, hold,
8
+ gravity, hard drop, line clear, score, replay, and checksum behavior.
9
+ - `tests/playable.spec.ts` drives keyboard input and verifies move, rotate,
10
+ hold, reset, and line clear behavior.
11
+
12
+ Run:
13
+
14
+ ```bash
15
+ npm install
16
+ npm run dev
17
+ npm test
18
+ ```
@@ -0,0 +1,23 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Aura3D Falling Blocks Starter</title>
7
+ <style>
8
+ html,
9
+ body,
10
+ #app {
11
+ width: 100%;
12
+ height: 100%;
13
+ margin: 0;
14
+ overflow: hidden;
15
+ background: #05070a;
16
+ }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <div id="app"></div>
21
+ <script type="module" src="./src/main.ts"></script>
22
+ </body>
23
+ </html>
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "aura3d-falling-blocks-starter",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite --host 127.0.0.1",
8
+ "typecheck": "tsc --noEmit",
9
+ "build": "npm run typecheck && vite build",
10
+ "preview": "vite preview --host 127.0.0.1",
11
+ "test": "playwright test tests/playable.spec.ts --workers=1"
12
+ },
13
+ "dependencies": {
14
+ "@aura3d/engine": "1.0.0"
15
+ },
16
+ "devDependencies": {
17
+ "@playwright/test": "^1.52.0",
18
+ "typescript": "^5.8.3",
19
+ "vite": "^7.3.2"
20
+ }
21
+ }
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from "@playwright/test";
2
+
3
+ export default defineConfig({
4
+ webServer: {
5
+ command: "npm run dev -- --port 5179",
6
+ url: "http://127.0.0.1:5179",
7
+ reuseExistingServer: !process.env.CI
8
+ },
9
+ use: {
10
+ baseURL: "http://127.0.0.1:5179"
11
+ }
12
+ });
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180"><rect width="320" height="180" fill="#101720"/><path d="M80 126 160 46l80 80-80 28z" fill="#77a7ff"/><text x="160" y="160" text-anchor="middle" font-family="Arial" font-size="18" fill="#f4f7fb">showcaseBlockfallCabinet 2x2x3.27</text></svg>
@@ -0,0 +1,20 @@
1
+ import { defineAuraAssets } from "@aura3d/engine";
2
+
3
+ export const assets = defineAuraAssets({
4
+ cabinetModel: {
5
+ type: "model",
6
+ format: "glb",
7
+ url: "/aura-assets/showcaseBlockfallCabinet.679d52fe.glb",
8
+ bounds: [2, 2, 3.27],
9
+ hash: "sha256-679d52fe0c7bf99373fc873f3c3892548f6c5758ae9c81be91f09acae6a35a36",
10
+ metadata: {
11
+ materials: ["arcade_machine"],
12
+ animations: [],
13
+ textures: ["image-0", "image-1", "image-2", "image-3"],
14
+ license: "CC-BY-4.0",
15
+ author: "Dmitry Blagodaryov",
16
+ sourcePage: "https://huggingface.co/datasets/allenai/objaverse/blob/main/glbs/000-012/f73986356b6e4d72b7a889279837aec2.glb",
17
+ thumbnailUrl: "/aura-assets/showcaseBlockfallCabinet.thumb.svg"
18
+ }
19
+ }
20
+ } as const);