create-aura3d 1.0.5

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 (83) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +27 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/index.d.ts +16 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +70 -0
  8. package/dist/index.js.map +1 -0
  9. package/package.json +55 -0
  10. package/templates/cartoon-channel/README.md +42 -0
  11. package/templates/cartoon-channel/index.html +13 -0
  12. package/templates/cartoon-channel/package.json +21 -0
  13. package/templates/cartoon-channel/playwright.config.ts +13 -0
  14. package/templates/cartoon-channel/src/aura-assets.ts +14 -0
  15. package/templates/cartoon-channel/src/characters.ts +28 -0
  16. package/templates/cartoon-channel/src/contract.ts +1 -0
  17. package/templates/cartoon-channel/src/episode.ts +300 -0
  18. package/templates/cartoon-channel/src/main.ts +322 -0
  19. package/templates/cartoon-channel/src/render-plan.ts +405 -0
  20. package/templates/cartoon-channel/src/sets.ts +14 -0
  21. package/templates/cartoon-channel/tests/route-health.spec.ts +7 -0
  22. package/templates/cartoon-channel/tests/storyboard-playback.spec.ts +74 -0
  23. package/templates/cartoon-channel/tsconfig.json +12 -0
  24. package/templates/cinematic-scene/README.md +11 -0
  25. package/templates/cinematic-scene/index.html +13 -0
  26. package/templates/cinematic-scene/package.json +21 -0
  27. package/templates/cinematic-scene/playwright.config.ts +14 -0
  28. package/templates/cinematic-scene/public/aura-assets/hero-fixture.glb +0 -0
  29. package/templates/cinematic-scene/public/aura-assets/hero.thumb.svg +1 -0
  30. package/templates/cinematic-scene/src/aura-assets.ts +17 -0
  31. package/templates/cinematic-scene/src/main.ts +27 -0
  32. package/templates/cinematic-scene/tests/route-health.spec.ts +16 -0
  33. package/templates/cinematic-scene/tests/screenshot.spec.ts +56 -0
  34. package/templates/cinematic-scene/tsconfig.json +15 -0
  35. package/templates/fighting-game/README.md +64 -0
  36. package/templates/fighting-game/index.html +13 -0
  37. package/templates/fighting-game/package.json +21 -0
  38. package/templates/fighting-game/playwright.config.ts +12 -0
  39. package/templates/fighting-game/src/aura-assets.ts +11 -0
  40. package/templates/fighting-game/src/game/fighters.ts +152 -0
  41. package/templates/fighting-game/src/game/moves.ts +70 -0
  42. package/templates/fighting-game/src/game/stage.ts +98 -0
  43. package/templates/fighting-game/src/main.ts +417 -0
  44. package/templates/fighting-game/src/styles.css +124 -0
  45. package/templates/fighting-game/tests/gameplay-smoke.spec.ts +23 -0
  46. package/templates/fighting-game/tests/route-health.spec.ts +11 -0
  47. package/templates/fighting-game/tsconfig.json +19 -0
  48. package/templates/mini-game/README.md +10 -0
  49. package/templates/mini-game/index.html +13 -0
  50. package/templates/mini-game/package.json +21 -0
  51. package/templates/mini-game/playwright.config.ts +14 -0
  52. package/templates/mini-game/public/aura-assets/player-fixture.glb +0 -0
  53. package/templates/mini-game/public/aura-assets/player.thumb.svg +8 -0
  54. package/templates/mini-game/src/aura-assets.ts +17 -0
  55. package/templates/mini-game/src/main.ts +27 -0
  56. package/templates/mini-game/tests/route-health.spec.ts +16 -0
  57. package/templates/mini-game/tests/screenshot.spec.ts +63 -0
  58. package/templates/mini-game/tsconfig.json +15 -0
  59. package/templates/product-viewer/README.md +16 -0
  60. package/templates/product-viewer/index.html +16 -0
  61. package/templates/product-viewer/package.json +21 -0
  62. package/templates/product-viewer/playwright.config.ts +14 -0
  63. package/templates/product-viewer/public/aura-assets/product-fixture.glb +0 -0
  64. package/templates/product-viewer/public/aura-assets/product.thumb.svg +1 -0
  65. package/templates/product-viewer/src/aura-assets.ts +17 -0
  66. package/templates/product-viewer/src/main.ts +27 -0
  67. package/templates/product-viewer/tests/route-health.spec.ts +16 -0
  68. package/templates/product-viewer/tests/screenshot.spec.ts +60 -0
  69. package/templates/product-viewer/tsconfig.json +15 -0
  70. package/templates/prompt-cartoon-channel/README.md +42 -0
  71. package/templates/prompt-cartoon-channel/index.html +13 -0
  72. package/templates/prompt-cartoon-channel/package.json +21 -0
  73. package/templates/prompt-cartoon-channel/playwright.config.ts +13 -0
  74. package/templates/prompt-cartoon-channel/src/aura-assets.ts +14 -0
  75. package/templates/prompt-cartoon-channel/src/characters.ts +28 -0
  76. package/templates/prompt-cartoon-channel/src/contract.ts +1 -0
  77. package/templates/prompt-cartoon-channel/src/episode.ts +300 -0
  78. package/templates/prompt-cartoon-channel/src/main.ts +314 -0
  79. package/templates/prompt-cartoon-channel/src/render-plan.ts +405 -0
  80. package/templates/prompt-cartoon-channel/src/sets.ts +14 -0
  81. package/templates/prompt-cartoon-channel/tests/route-health.spec.ts +7 -0
  82. package/templates/prompt-cartoon-channel/tests/storyboard-playback.spec.ts +74 -0
  83. package/templates/prompt-cartoon-channel/tsconfig.json +12 -0
@@ -0,0 +1,322 @@
1
+ import {
2
+ camera,
3
+ captionCueAtTime,
4
+ createAuraApp,
5
+ createShotPlaybackPlan,
6
+ effects,
7
+ game,
8
+ installShotPlayback,
9
+ labels,
10
+ lights,
11
+ material,
12
+ model,
13
+ primitives,
14
+ sampleAuraVoiceBridgeAtTime,
15
+ sampleShotPlaybackPlan,
16
+ scene,
17
+ type AuraAssetRef
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
+ type CartoonAssetKey
28
+ } from "./episode";
29
+ import {
30
+ accessibilityProofMetadata,
31
+ auraVoicePackage,
32
+ bridgeIssues,
33
+ bridgeSampleAtThumbnail,
34
+ captionFrameSyncSourceProof,
35
+ captionTimingProof,
36
+ deterministicScreenshotFixtures,
37
+ glbVisemeRuntimeExample,
38
+ promptAnimationEvidence,
39
+ primitiveMouthRuntimeExample,
40
+ phonemeVisemeDubSyncSourceProof,
41
+ publishReadiness,
42
+ renderOutputPackage,
43
+ renderPlan,
44
+ sampleRenderSourceWorkflow,
45
+ visemeFrameSyncSourceProof,
46
+ visemeTrack
47
+ } from "./render-plan";
48
+
49
+ declare global {
50
+ interface Window {
51
+ __AURA3D_CARTOON_TEMPLATE__?: {
52
+ readonly contractId: string;
53
+ readonly template: string;
54
+ readonly storyBible: unknown;
55
+ readonly shotIds: readonly string[];
56
+ readonly captionIds: readonly string[];
57
+ readonly playbackProbeTimes: readonly number[];
58
+ readonly playbackProbeSamples: readonly unknown[];
59
+ readonly renderQueueItems: number;
60
+ readonly typedAssets: unknown;
61
+ readonly requiredTypedAssets: readonly string[];
62
+ readonly missingTypedAssets: readonly string[];
63
+ readonly assetCommands: readonly string[];
64
+ readonly bridgeIssues: readonly unknown[];
65
+ readonly promptAnimationEvidence: unknown;
66
+ readonly publishReadiness: unknown;
67
+ readonly sourceProofs: unknown;
68
+ readonly sampleRenderSourceWorkflow: unknown;
69
+ sampleAt(time: number): unknown;
70
+ };
71
+ }
72
+ }
73
+
74
+ const firstStoryboardShot = episode.storyboard.scenes[0]?.shots[0];
75
+ const firstCaption = episode.captionTrack.cues[0];
76
+ const thumbnailCapture = renderOutputPackage.thumbnailCapture;
77
+ const thumbnailCaption = captionCueAtTime(episode.captionTrack, thumbnailCapture.time);
78
+ const storyBible = episode.storyBible;
79
+ const typedCartoonAssets = assets as Partial<Record<CartoonAssetKey, AuraAssetRef<"model">>>;
80
+
81
+ const captionOverlay = document.createElement("div");
82
+ captionOverlay.id = "caption-overlay";
83
+ captionOverlay.textContent = firstCaption?.text ?? firstStoryboardShot?.storyBeat ?? "Aura3D cartoon channel";
84
+ captionOverlay.style.cssText = [
85
+ "position:fixed",
86
+ "left:50%",
87
+ "bottom:28px",
88
+ "transform:translateX(-50%)",
89
+ "max-width:min(840px,calc(100vw - 32px))",
90
+ "padding:12px 18px",
91
+ "border-radius:14px",
92
+ "background:rgba(3,12,20,0.88)",
93
+ "color:#f8fff2",
94
+ "font:700 18px/1.35 ui-rounded, Trebuchet MS, sans-serif",
95
+ "letter-spacing:0.01em",
96
+ "text-align:center",
97
+ "box-shadow:0 10px 30px rgba(0,0,0,0.28)",
98
+ "z-index:10"
99
+ ].join(";");
100
+ document.body.appendChild(captionOverlay);
101
+
102
+ const shotPlaybackPlan = createShotPlaybackPlan({
103
+ timeline: episode.shotTimeline,
104
+ performance: episode.performance,
105
+ captions: episode.captionTrack,
106
+ visemes: visemeTrack,
107
+ runtimeNodeByCharacterId: {
108
+ miko: "miko",
109
+ luma: "luma"
110
+ },
111
+ loop: true
112
+ });
113
+
114
+ const playbackProbeTimes = [1, 21, 43] as const;
115
+ const playbackProbeSamples = playbackProbeTimes.map((time) => sampleCartoonRouteAt(time));
116
+ captionOverlay.dataset.shotId = playbackProbeSamples[0]?.shotId ?? "";
117
+ captionOverlay.dataset.captionId = playbackProbeSamples[0]?.captionId ?? firstCaption?.captionId ?? "";
118
+ document.body.dataset.cartoonShotCount = String(episode.shotTimeline.shots.length);
119
+ document.body.dataset.cartoonCaptionCount = String(episode.captionTrack.cues.length);
120
+ document.body.dataset.cartoonStoryBibleProps = String(storyBible.props.length);
121
+
122
+ const app = createAuraApp("#app", {
123
+ scene: scene()
124
+ .background("#081b2a")
125
+ .add(createCharacterBody("miko", "Miko", "miko", [-0.8, 0.75, 0], [0.32, 0.42, 0.32], 0.72, "#7de2ff"))
126
+ .add(createMouthCard("miko:mouth", "Miko", [-0.8, 0.8, 0.32], "#f8fff2"))
127
+ .add(createCharacterBody("luma", "Luma", "luma", [0.8, 0.72, 0], [0.3, 0.38, 0.3], 0.68, "#ffe18e"))
128
+ .add(createMouthCard("luma:mouth", "Luma", [0.8, 0.77, 0.32], "#40ffbf"))
129
+ .add(
130
+ primitives
131
+ .box({ name: "moon garden path", material: material.pbr({ color: "#182d3f", roughness: 0.78 }) })
132
+ .position(0, 0.05, 0)
133
+ .scale([2.8, 0.04, 0.8])
134
+ )
135
+ .add(
136
+ primitives
137
+ .sphere({ name: "glow stones primitive fallback", material: material.emissive({ color: "#ffe18e", intensity: 0.42 }) })
138
+ .position(0.18, 0.16, 0.28)
139
+ .scale([0.16, 0.08, 0.16])
140
+ )
141
+ .add(
142
+ primitives
143
+ .box({ name: "moon lilies primitive fallback", material: material.pbr({ color: "#f8fff2", roughness: 0.5 }) })
144
+ .position(-0.38, 0.2, 0.18)
145
+ .scale([0.12, 0.24, 0.04])
146
+ )
147
+ .add(labels.hud({ text: firstCaption?.text ?? firstStoryboardShot?.storyBeat ?? "Aura3D cartoon channel", position: "bottom-center" }))
148
+ .add(lights.studio({ intensity: 1.2 }))
149
+ .add(effects.bloom({ intensity: 0.18, color: "#7de2ff" }))
150
+ .camera(camera.perspective({ position: [0, 1.4, 4.2], target: [0, 0.7, 0], fov: 42 })),
151
+ diagnostics: true,
152
+ metadata: {
153
+ contractId: episodeContractId,
154
+ template: "cartoon-channel",
155
+ runtimePlayback: "app.onFrame updates runtime nodes; createAuraApp is called once",
156
+ renderQueueItems: renderPlan.items.length,
157
+ renderPackageId: renderOutputPackage.packageId,
158
+ storyBibleId: storyBible.episodeId,
159
+ storyBibleProps: storyBible.props.map((prop) => prop.id),
160
+ styleGuide: storyBible.styleGuide.visualStyle,
161
+ shotListCount: storyBible.shotList.length,
162
+ playbackProbeSamples: playbackProbeSamples.map((sample) => ({
163
+ time: sample.time,
164
+ frame: sample.frame,
165
+ shotId: sample.shotId,
166
+ captionId: sample.captionId,
167
+ nodeUpdateCount: sample.nodeUpdates.length
168
+ })),
169
+ thumbnailCaptureSceneStateId: thumbnailCapture.sourceSceneStateId,
170
+ thumbnailCaptureTime: thumbnailCapture.time,
171
+ thumbnailCaptionId: thumbnailCaption?.captionId,
172
+ deterministicCaptureItems: renderPlan.items.filter((item) => item.sourceSceneState).length,
173
+ deterministicScreenshotFixtures,
174
+ typedAssets: typedCartoonAssetSummary,
175
+ requiredTypedAssets: requiredCartoonCharacterAssets,
176
+ missingTypedAssets: missingCartoonCharacterAssets,
177
+ assetCommands: publicCartoonAssetInstructions,
178
+ bridgeIssueCount: bridgeIssues.length,
179
+ bridgeSampleAtThumbnail: {
180
+ time: bridgeSampleAtThumbnail.time,
181
+ frame: bridgeSampleAtThumbnail.frame,
182
+ shotId: bridgeSampleAtThumbnail.shot?.shotId,
183
+ dialogueLineId: bridgeSampleAtThumbnail.dialogue?.lineId
184
+ },
185
+ promptAnimationEvidence: {
186
+ publishReady: promptAnimationEvidence.publishReady,
187
+ assetStatus: promptAnimationEvidence.assetStatus,
188
+ captions: promptAnimationEvidence.captions,
189
+ visemes: promptAnimationEvidence.visemes,
190
+ audio: promptAnimationEvidence.audio,
191
+ deterministicCapture: promptAnimationEvidence.deterministicCapture,
192
+ routeHealth: promptAnimationEvidence.routeHealth
193
+ },
194
+ publishReadiness: {
195
+ ready: publishReadiness.ready,
196
+ issueCount: publishReadiness.issues.length
197
+ },
198
+ captionTimingProof: {
199
+ status: captionTimingProof.status,
200
+ maxDriftFrames: captionTimingProof.maxDriftFrames,
201
+ coveredLineIds: captionTimingProof.coveredLineIds
202
+ },
203
+ captionFrameSyncSourceProof,
204
+ visemeFrameSyncSourceProof,
205
+ sampleRenderSourceWorkflow,
206
+ accessibilityProof: {
207
+ captions: accessibilityProofMetadata?.captions.status,
208
+ reducedMotion: accessibilityProofMetadata?.reducedMotion.status,
209
+ highContrast: accessibilityProofMetadata?.highContrast.status
210
+ },
211
+ primitiveMouthRuntimeExample,
212
+ glbVisemeRuntimeExample
213
+ }
214
+ });
215
+
216
+ window.__AURA3D_CARTOON_TEMPLATE__ = {
217
+ contractId: episodeContractId,
218
+ template: "cartoon-channel",
219
+ storyBible,
220
+ shotIds: episode.shotTimeline.shots.map((shot) => shot.shotId),
221
+ captionIds: episode.captionTrack.cues.map((caption) => caption.captionId),
222
+ playbackProbeTimes,
223
+ playbackProbeSamples,
224
+ renderQueueItems: renderPlan.items.length,
225
+ typedAssets: typedCartoonAssetSummary,
226
+ requiredTypedAssets: requiredCartoonCharacterAssets,
227
+ missingTypedAssets: missingCartoonCharacterAssets,
228
+ assetCommands: publicCartoonAssetInstructions,
229
+ bridgeIssues,
230
+ promptAnimationEvidence,
231
+ publishReadiness,
232
+ sourceProofs: {
233
+ captionFrameSyncSourceProof,
234
+ visemeFrameSyncSourceProof,
235
+ phonemeVisemeDubSyncSourceProof
236
+ },
237
+ sampleRenderSourceWorkflow,
238
+ sampleAt(time: number) {
239
+ return sampleCartoonRouteAt(time);
240
+ }
241
+ };
242
+
243
+ installShotPlayback(app, shotPlaybackPlan, {
244
+ primitiveMouthNodeByCharacterId: {
245
+ miko: "miko:mouth",
246
+ luma: "luma:mouth"
247
+ },
248
+ onCaption(caption, framePlan) {
249
+ captionOverlay.textContent = caption?.text ?? firstCaption?.text ?? "";
250
+ captionOverlay.dataset.shotId = framePlan.shotId ?? "";
251
+ captionOverlay.dataset.captionId = caption?.captionId ?? "";
252
+ }
253
+ });
254
+
255
+ function createCharacterBody(
256
+ id: "miko" | "luma",
257
+ name: string,
258
+ assetKey: CartoonAssetKey,
259
+ position: readonly [number, number, number],
260
+ fallbackScale: readonly [number, number, number],
261
+ modelScale: number,
262
+ color: string
263
+ ) {
264
+ const asset = typedCartoonAssets[assetKey];
265
+ const runtime = game.runtimeNode(id, { tags: ["character", id, asset ? "typed-asset" : "primitive-fallback"] });
266
+ if (asset) {
267
+ return model(asset, { name: `${name} typed character asset` })
268
+ .position(position[0], position[1], position[2])
269
+ .scale(modelScale)
270
+ .runtime(runtime);
271
+ }
272
+ return primitives
273
+ .sphere({
274
+ name: `${name} primitive fallback body - add ${assetKey} with the Aura3D CLI`,
275
+ material: material.pbr({ color, roughness: 0.54 })
276
+ })
277
+ .position(position[0], position[1], position[2])
278
+ .scale(fallbackScale)
279
+ .runtime(runtime);
280
+ }
281
+
282
+ function createMouthCard(id: "miko:mouth" | "luma:mouth", name: string, position: readonly [number, number, number], color: string) {
283
+ return primitives
284
+ .box({
285
+ name: `${name} primitive mouth card`,
286
+ material: material.emissive({ color, intensity: 0.32 })
287
+ })
288
+ .position(position[0], position[1], position[2])
289
+ .scale([0.22, 0.035, 0.025])
290
+ .runtime(game.runtimeNode(id, { tags: ["mouth", "primitive", name.toLowerCase()] }));
291
+ }
292
+
293
+ function sampleCartoonRouteAt(time: number) {
294
+ const bridgeSample = sampleAuraVoiceBridgeAtTime(auraVoicePackage, time);
295
+ const playbackSample = sampleShotPlaybackPlan(shotPlaybackPlan, time);
296
+ const caption = captionCueAtTime(episode.captionTrack, time);
297
+ const speakingCharacterId = bridgeSample.dialogue?.speakerId;
298
+ return {
299
+ time,
300
+ frame: bridgeSample.frame,
301
+ shotId: bridgeSample.shot?.shotId,
302
+ sceneId: bridgeSample.shot?.sceneId,
303
+ captionId: caption?.captionId,
304
+ captionText: caption?.text,
305
+ cameraMove: bridgeSample.shot?.camera.move,
306
+ transitionOut: bridgeSample.shot?.transitionOut,
307
+ dialogueLineId: bridgeSample.dialogue?.lineId,
308
+ visemeId: bridgeSample.viseme?.primaryVisemeId,
309
+ nodeUpdates: playbackSample.nodeUpdates.map((update) => ({
310
+ characterId: update.characterId,
311
+ action: speakingCharacterId === update.characterId ? "speak" : update.action,
312
+ emotion: update.emotion,
313
+ position: update.position
314
+ })),
315
+ sourceShotCharacters: (bridgeSample.shot?.characters ?? []).map((character) => ({
316
+ characterId: character.characterId,
317
+ action: speakingCharacterId === character.characterId ? "speak" : character.action,
318
+ emotion: character.emotion,
319
+ position: character.position
320
+ }))
321
+ };
322
+ }