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.
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/package.json +11 -9
- package/templates/{cartoon-channel → animation-channel}/README.md +11 -11
- package/templates/{cartoon-studio → animation-channel}/index.html +1 -1
- package/templates/{cartoon-channel → animation-channel}/package.json +2 -2
- package/templates/{cartoon-channel → animation-channel}/src/episode.ts +22 -22
- package/templates/{cartoon-channel → animation-channel}/src/experimental/README.md +5 -5
- package/templates/{cartoon-channel → animation-channel}/src/experimental/concept-episode-2-5d.css +3 -3
- package/templates/{cartoon-channel → animation-channel}/src/experimental/concept-episode-2-5d.ts +7 -7
- package/templates/{cartoon-channel → animation-channel}/src/experimental/image-puppet-episode.css +4 -4
- package/templates/{cartoon-channel → animation-channel}/src/experimental/image-puppet-episode.ts +6 -6
- package/templates/{cartoon-channel → animation-channel}/src/experimental/puppet-episode-2d.css +3 -3
- package/templates/{cartoon-channel → animation-channel}/src/experimental/puppet-episode-2d.ts +7 -7
- package/templates/{cartoon-channel → animation-channel}/src/main.ts +32 -32
- package/templates/{cartoon-channel → animation-channel}/src/render-plan.ts +13 -13
- package/templates/{cartoon-channel → animation-channel}/src/sample-episode-visual.css +34 -34
- package/templates/{cartoon-channel → animation-channel}/src/sample-episode-visual.ts +20 -20
- package/templates/{cartoon-channel → animation-channel}/tests/concept-2-5d-animation.spec.ts +3 -3
- package/templates/{cartoon-channel → animation-channel}/tests/concept-2-5d.spec.ts +6 -6
- package/templates/{cartoon-channel → animation-channel}/tests/image-puppet-animation.spec.ts +3 -3
- package/templates/{cartoon-channel → animation-channel}/tests/image-puppet.spec.ts +5 -5
- package/templates/{cartoon-channel → animation-channel}/tests/puppet-2d-animation.spec.ts +3 -3
- package/templates/{cartoon-channel → animation-channel}/tests/puppet-2d.spec.ts +4 -4
- package/templates/{prompt-cartoon-channel → animation-channel}/tests/route-health.spec.ts +1 -1
- package/templates/{cartoon-channel → animation-channel}/tests/sample-episode-visual.spec.ts +5 -5
- package/templates/{cartoon-channel → animation-channel}/tests/storyboard-playback.spec.ts +7 -7
- package/templates/animation-studio/AGENTS.md +71 -0
- package/templates/{cartoon-studio → animation-studio}/ASSET-LICENSES.md +7 -7
- package/templates/{cartoon-studio → animation-studio}/README.md +6 -6
- package/templates/animation-studio/aura.assets.json +669 -0
- package/templates/animation-studio/dist/episodes/scene/episode-3d.webm +0 -0
- package/templates/animation-studio/dist/episodes/scene/frames/action.png +0 -0
- package/templates/animation-studio/dist/episodes/scene/frames/dialogue.png +0 -0
- package/templates/animation-studio/dist/episodes/scene/frames/final.png +0 -0
- package/templates/animation-studio/dist/episodes/scene/frames/first.png +0 -0
- package/templates/animation-studio/dist/episodes/scene/frames/mouth-closed.png +0 -0
- package/templates/animation-studio/dist/episodes/scene/frames/mouth-open.png +0 -0
- package/templates/animation-studio/dist/episodes/scene/render-live-summary.json +10284 -0
- package/templates/animation-studio/dist/episodes/scene/skeleton-overlays/worker-1.png +0 -0
- package/templates/animation-studio/dist/episodes/scene/skeleton-overlays/worker-2.png +0 -0
- package/templates/animation-studio/dist/generated/second-scene.document.json +1210 -0
- package/templates/animation-studio/dist/generated/studio-edited.document.json +1196 -0
- package/templates/animation-studio/dist/scene/inshader-accept.document.json +1 -0
- package/templates/animation-studio/dist/scene/inshader-test.document.json +1 -0
- package/templates/animation-studio/dist/scene/integ.document.json +1 -0
- package/templates/animation-studio/dist/scene/working.document.json +723 -0
- package/templates/animation-studio/dist/scene/working.history.json +1 -0
- package/templates/{cartoon-studio → animation-studio}/live-route.html +1 -1
- package/templates/{cartoon-studio → animation-studio}/package-lock.json +2 -2
- package/templates/animation-studio/package.json +32 -0
- package/templates/animation-studio/public/aura-assets/cast-a.catalog.glb +0 -0
- package/templates/animation-studio/public/aura-assets/cast-b.catalog.glb +0 -0
- package/templates/animation-studio/public/aura-assets/luma.catalog.glb +0 -0
- package/templates/animation-studio/public/aura-assets/luma2.catalog.glb +0 -0
- package/templates/animation-studio/public/aura-assets/miko.catalog.glb +0 -0
- package/templates/{cartoon-studio → animation-studio}/public/aura-assets/moonGarden.gltf +1 -1
- package/templates/animation-studio/public/aura-assets/mushroom.catalog.glb +0 -0
- package/templates/animation-studio/public/aura-assets/rusty.catalog.glb +0 -0
- package/templates/animation-studio/public/cast-library/cast-library.json +71 -0
- package/templates/animation-studio/public/clip-library/gesture.json +173903 -0
- package/templates/animation-studio/public/clip-library/idle.json +23035 -0
- package/templates/animation-studio/public/clip-library/manifest.json +154 -0
- package/templates/animation-studio/public/clip-library/nod.json +173903 -0
- package/templates/animation-studio/public/clip-library/point.json +69879 -0
- package/templates/animation-studio/public/clip-library/react.json +66084 -0
- package/templates/animation-studio/public/clip-library/run.json +9648 -0
- package/templates/animation-studio/public/clip-library/talk.json +69879 -0
- package/templates/animation-studio/public/clip-library/walk.json +8283 -0
- package/templates/animation-studio/public/hifi-cast/BrainStem.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/CesiumMan.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/RiggedFigure.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/kaykit/Barbarian.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/kaykit/Knight.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/kaykit/Mage.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/kaykit/Rogue.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/kaykit/Rogue_Hooded.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/khronos-report.json +295 -0
- package/templates/animation-studio/public/hifi-cast/quaternius-report.json +449 -0
- package/templates/animation-studio/public/hifi-cast/rpm/cesiumman.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/rpm/fox.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/rpm/riggedfigure.glb +0 -0
- package/templates/animation-studio/public/hifi-cast/rpm-report.json +301 -0
- package/templates/animation-studio/scripts/anim.ts +103 -0
- package/templates/animation-studio/scripts/animation-scene.ts +457 -0
- package/templates/animation-studio/scripts/asset-motion-probe.ts +450 -0
- package/templates/animation-studio/scripts/asset-render-probe.ts +152 -0
- package/templates/animation-studio/scripts/author-office-scene.ts +65 -0
- package/templates/animation-studio/scripts/build-cast-library.ts +97 -0
- package/templates/animation-studio/scripts/build-characters.ts +1543 -0
- package/templates/animation-studio/scripts/build-clip-library.ts +972 -0
- package/templates/animation-studio/scripts/clip-decision-cli.ts +51 -0
- package/templates/animation-studio/scripts/determinism-check.ts +48 -0
- package/templates/animation-studio/scripts/generate-scene.ts +95 -0
- package/templates/animation-studio/scripts/hifi-cast-validate.ts +572 -0
- package/templates/animation-studio/scripts/motion-evidence-cli.ts +150 -0
- package/templates/animation-studio/scripts/motion-evidence.ts +362 -0
- package/templates/animation-studio/scripts/preview-server.ts +52 -0
- package/templates/animation-studio/scripts/regen-manifest.ts +156 -0
- package/templates/animation-studio/scripts/render-core.ts +360 -0
- package/templates/animation-studio/scripts/render-live.ts +813 -0
- package/templates/animation-studio/scripts/render-parallel.ts +70 -0
- package/templates/animation-studio/scripts/render-server.ts +119 -0
- package/templates/animation-studio/scripts/resolve-asset.ts +669 -0
- package/templates/animation-studio/scripts/skeleton-overlay-cli.ts +82 -0
- package/templates/animation-studio/scripts/skeleton-overlay.ts +293 -0
- package/templates/animation-studio/scripts/studio-tools-demo.ts +45 -0
- package/templates/animation-studio/scripts/texture-bake.ts +297 -0
- package/templates/{cartoon-studio → animation-studio}/scripts/validate-characters.ts +0 -0
- package/templates/animation-studio/scripts/verify-extracted-overlay-cli.ts +264 -0
- package/templates/animation-studio/src/animation-episode-validator.ts +97 -0
- package/templates/animation-studio/src/animation-performance.ts +556 -0
- package/templates/animation-studio/src/aura-assets.ts +71 -0
- package/templates/animation-studio/src/character.ts +40 -0
- package/templates/animation-studio/src/director/compile-episode-document.ts +45 -0
- package/templates/animation-studio/src/director/director-heuristics.ts +697 -0
- package/templates/animation-studio/src/director/prompt-to-scene.ts +369 -0
- package/templates/animation-studio/src/empty-document.ts +77 -0
- package/templates/animation-studio/src/episode-document.ts +442 -0
- package/templates/animation-studio/src/examples/moon-garden.example.ts +183 -0
- package/templates/animation-studio/src/fidelity.ts +129 -0
- package/templates/animation-studio/src/graph.ts +14 -0
- package/templates/animation-studio/src/procedural-hdri.ts +243 -0
- package/templates/animation-studio/src/profile.ts +97 -0
- package/templates/animation-studio/src/render-live-route.ts +42 -0
- package/templates/animation-studio/src/render-modes.ts +137 -0
- package/templates/animation-studio/src/scene-player.ts +867 -0
- package/templates/animation-studio/src/set-templates.ts +361 -0
- package/templates/animation-studio/src/studio/episode-document-store.ts +72 -0
- package/templates/animation-studio/src/studio/scene-tool-registry.ts +86 -0
- package/templates/animation-studio/src/studio/scene-tools.ts +169 -0
- package/templates/animation-studio/tests/reports/animation-studio/hifi-cast-validation.json +938 -0
- package/templates/animation-studio/tsconfig.json +26 -0
- package/templates/{cartoon-studio → animation-studio}/vite.config.ts +6 -1
- package/templates/character-controller/README.md +33 -0
- package/templates/character-controller/index.html +19 -0
- package/templates/character-controller/package.json +23 -0
- package/templates/character-controller/playwright.config.ts +14 -0
- package/templates/character-controller/src/controller.ts +44 -0
- package/templates/character-controller/src/main.ts +62 -0
- package/templates/character-controller/tests/route-health.spec.ts +26 -0
- package/templates/character-controller/tests/screenshot.spec.ts +9 -0
- package/templates/character-controller/tsconfig.json +15 -0
- package/templates/cinematic-scene/package.json +1 -1
- package/templates/episode-builder/README.md +4 -4
- package/templates/episode-builder/package.json +1 -1
- package/templates/episode-builder/src/aura-assets.ts +1 -1
- package/templates/episode-builder/src/builder.ts +4 -4
- package/templates/episode-builder/src/episode.ts +21 -21
- package/templates/episode-builder/src/main.ts +20 -20
- package/templates/episode-builder/src/render-plan.ts +13 -13
- package/templates/episode-builder/tests/storyboard-playback.spec.ts +7 -7
- package/templates/fighting-game/package.json +1 -1
- package/templates/mini-game/package.json +1 -1
- package/templates/product-viewer/package.json +1 -1
- package/templates/{prompt-cartoon-channel → prompt-animation-channel}/README.md +5 -5
- package/templates/{cartoon-channel → prompt-animation-channel}/index.html +1 -1
- package/templates/{prompt-cartoon-channel → prompt-animation-channel}/package.json +2 -2
- package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/aura-assets.ts +1 -1
- package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/episode.ts +22 -22
- package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/main.ts +28 -28
- package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/render-plan.ts +13 -13
- package/templates/{cartoon-channel → prompt-animation-channel}/tests/route-health.spec.ts +1 -1
- package/templates/{prompt-cartoon-channel → prompt-animation-channel}/tests/storyboard-playback.spec.ts +8 -8
- package/templates/cartoon-studio/aura.assets.json +0 -400
- package/templates/cartoon-studio/package.json +0 -33
- package/templates/cartoon-studio/public/aura-assets/luma.authored.glb +0 -0
- package/templates/cartoon-studio/public/aura-assets/miko.authored.glb +0 -0
- package/templates/cartoon-studio/scripts/build-characters.ts +0 -738
- package/templates/cartoon-studio/scripts/build-dialogue-audio.ts +0 -262
- package/templates/cartoon-studio/scripts/episode.ts +0 -323
- package/templates/cartoon-studio/scripts/render-live.ts +0 -873
- package/templates/cartoon-studio/src/aura-assets.ts +0 -64
- package/templates/cartoon-studio/src/characters.ts +0 -65
- package/templates/cartoon-studio/src/episode-renderer.ts +0 -605
- package/templates/cartoon-studio/src/episode.ts +0 -306
- package/templates/cartoon-studio/src/main.ts +0 -400
- package/templates/cartoon-studio/src/render-live-route.ts +0 -913
- package/templates/cartoon-studio/src/render-plan.ts +0 -567
- package/templates/cartoon-studio/src/review.ts +0 -99
- package/templates/cartoon-studio/src/studio.ts +0 -101
- package/templates/cartoon-studio/test-results/.last-run.json +0 -4
- package/templates/cartoon-studio/tests/episode-render.spec.ts +0 -44
- package/templates/cartoon-studio/tests/motion-quality.spec.ts +0 -45
- package/templates/cartoon-studio/tests/route-health.spec.ts +0 -7
- package/templates/cartoon-studio/tests/storyboard-playback.spec.ts +0 -99
- package/templates/cartoon-studio/tests/visual-review.spec.ts +0 -21
- package/templates/cartoon-studio/tsconfig.json +0 -14
- package/templates/prompt-cartoon-channel/index.html +0 -13
- package/templates/prompt-cartoon-channel/src/sets.ts +0 -14
- /package/templates/{cartoon-channel → animation-channel}/aura.assets.json +0 -0
- /package/templates/{cartoon-channel → animation-channel}/playwright.config.ts +0 -0
- /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/luma.047f5e5f.glb +0 -0
- /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/luma.thumb.svg +0 -0
- /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/miko.047f5e5f.glb +0 -0
- /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/miko.thumb.svg +0 -0
- /package/templates/{cartoon-channel → animation-channel}/public/aura-assets/moon-garden-feature-frame.png +0 -0
- /package/templates/{cartoon-channel → animation-channel}/src/aura-assets.ts +0 -0
- /package/templates/{cartoon-channel → animation-channel}/src/characters.ts +0 -0
- /package/templates/{cartoon-channel → animation-channel}/src/contract.ts +0 -0
- /package/templates/{cartoon-channel → animation-channel}/src/sets.ts +0 -0
- /package/templates/{cartoon-channel → animation-channel}/test-results/.last-run.json +0 -0
- /package/templates/{cartoon-channel → animation-channel}/tests/reports/prompt-animation/cartoon-sample-episode.png +0 -0
- /package/templates/{cartoon-channel → animation-channel}/tsconfig.json +0 -0
- /package/templates/{cartoon-studio → animation-studio}/playwright.config.ts +0 -0
- /package/templates/{cartoon-studio → animation-studio}/public/aura-assets/luma.thumb.svg +0 -0
- /package/templates/{cartoon-studio → animation-studio}/public/aura-assets/miko.thumb.svg +0 -0
- /package/templates/{cartoon-studio → animation-studio}/src/contract.ts +0 -0
- /package/templates/{prompt-cartoon-channel → prompt-animation-channel}/playwright.config.ts +0 -0
- /package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/characters.ts +0 -0
- /package/templates/{prompt-cartoon-channel → prompt-animation-channel}/src/contract.ts +0 -0
- /package/templates/{cartoon-studio → prompt-animation-channel}/src/sets.ts +0 -0
- /package/templates/{prompt-cartoon-channel → prompt-animation-channel}/tsconfig.json +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"types": [
|
|
9
|
+
"vite/client",
|
|
10
|
+
"node"
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"src"
|
|
15
|
+
],
|
|
16
|
+
"//": "The real-3D generative subsystem (render-live-route + scene-player + the EpisodeDocument schema, Director and Studio) needs engine exports newer than the published @aura3d/engine and runs only via the tsx scripts (npm run episode:render-3d / studio / generate), which alias @aura3d/* to a monorepo build. Excluded from the default scaffold typecheck/build.",
|
|
17
|
+
"exclude": [
|
|
18
|
+
"src/render-live-route.ts",
|
|
19
|
+
"src/scene-player.ts",
|
|
20
|
+
"src/episode-document.ts",
|
|
21
|
+
"src/examples/moon-garden.example.ts",
|
|
22
|
+
"src/animation-episode-validator.ts",
|
|
23
|
+
"src/director",
|
|
24
|
+
"src/studio"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -6,8 +6,13 @@ import { defineConfig } from "vite";
|
|
|
6
6
|
// build and the episode render output can coexist in `dist/` without clobbering each
|
|
7
7
|
// other. (Order-independent: build and render no longer destroy one another.)
|
|
8
8
|
export default defineConfig({
|
|
9
|
+
// The legacy SVG-puppet `index.html` → `src/main.ts` route was deleted. The real
|
|
10
|
+
// live-3D render route is the only entry: `live-route.html` → `src/render-live-route.ts`.
|
|
9
11
|
build: {
|
|
10
12
|
outDir: "dist",
|
|
11
|
-
emptyOutDir: false
|
|
13
|
+
emptyOutDir: false,
|
|
14
|
+
rollupOptions: {
|
|
15
|
+
input: "live-route.html"
|
|
16
|
+
}
|
|
12
17
|
}
|
|
13
18
|
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Aura3D Character Controller (template)
|
|
2
|
+
|
|
3
|
+
Input-driven locomotion: keyboard → kinematic speed → `@aura3d/animation` locomotion kit
|
|
4
|
+
(idle/walk/run blended by speed via `BlendTree1D` + the locomotion state graph) → live proof.
|
|
5
|
+
|
|
6
|
+
Hold **W/A/S/D** (or arrows) to walk; hold **Shift** to run.
|
|
7
|
+
|
|
8
|
+
## Commands
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install
|
|
12
|
+
npm run dev # live preview route (exposes window.__AURA3D_CHARACTER_CONTROLLER_PROOF__)
|
|
13
|
+
npm run build
|
|
14
|
+
npm test # route-health + screenshot
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## How it composes the engine
|
|
18
|
+
|
|
19
|
+
- `src/controller.ts` — pure kinematic `stepCharacterSpeed` (accel/decel toward walk/run targets).
|
|
20
|
+
- `src/main.ts` — keyboard input → `stepCharacterSpeed` → `createLocomotionKit(...).sample(speed)` →
|
|
21
|
+
blended clip weights + state, exposed as a proof object.
|
|
22
|
+
|
|
23
|
+
## Physics capsule path (optional)
|
|
24
|
+
|
|
25
|
+
For a grounded 3D capsule instead of the kinematic model, swap `stepCharacterSpeed` for
|
|
26
|
+
`@aura3d/physics` `createFightingCharacterController()` and feed its resulting speed into the same
|
|
27
|
+
locomotion kit. That requires a physics world + a rigged GLB character (see
|
|
28
|
+
`docs/animation/runtime-support.md`).
|
|
29
|
+
|
|
30
|
+
## Non-goals
|
|
31
|
+
|
|
32
|
+
Not a Unity Mecanim / Unreal Control Rig replacement; no motion matching, no full-body IK, no
|
|
33
|
+
ragdoll. See `docs/project/known-limits.md`.
|
|
@@ -0,0 +1,19 @@
|
|
|
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 Character Controller</title>
|
|
7
|
+
<style>
|
|
8
|
+
html, body { margin: 0; background: #0c0f16; color: #e6e6e6; font-family: system-ui, sans-serif; }
|
|
9
|
+
#app { padding: 24px; }
|
|
10
|
+
h1 { font-size: 18px; font-weight: 600; }
|
|
11
|
+
</style>
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
<div id="app">
|
|
15
|
+
<h1>Aura3D Character Controller — locomotion blend</h1>
|
|
16
|
+
</div>
|
|
17
|
+
<script type="module" src="/src/main.ts"></script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aura3d-character-controller",
|
|
3
|
+
"version": "0.1.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/route-health.spec.ts tests/screenshot.spec.ts --workers=1"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@aura3d/animation": "1.3.0",
|
|
15
|
+
"@aura3d/engine": "1.3.0",
|
|
16
|
+
"@aura3d/physics": "1.3.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@playwright/test": "^1.52.0",
|
|
20
|
+
"typescript": "^5.9.3",
|
|
21
|
+
"vite": "^7.2.4"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineConfig } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
testDir: "./tests",
|
|
5
|
+
use: {
|
|
6
|
+
baseURL: "http://127.0.0.1:4173"
|
|
7
|
+
},
|
|
8
|
+
webServer: {
|
|
9
|
+
command: "npm exec vite -- --host 127.0.0.1 --port 4173 --strictPort",
|
|
10
|
+
url: "http://127.0.0.1:4173",
|
|
11
|
+
reuseExistingServer: !process.env.CI,
|
|
12
|
+
timeout: 120_000
|
|
13
|
+
}
|
|
14
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Pure kinematic speed model for the character-controller template. Deterministic + testable;
|
|
2
|
+
// the browser route feeds this speed into the @aura3d/animation locomotion kit. (The full physics
|
|
3
|
+
// capsule path via @aura3d/physics `createFightingCharacterController` is documented in the README.)
|
|
4
|
+
|
|
5
|
+
export interface CharacterControllerTuning {
|
|
6
|
+
readonly walkSpeed: number;
|
|
7
|
+
readonly runSpeed: number;
|
|
8
|
+
readonly acceleration: number;
|
|
9
|
+
readonly deceleration: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const defaultCharacterControllerTuning: CharacterControllerTuning = {
|
|
13
|
+
walkSpeed: 1.6,
|
|
14
|
+
runSpeed: 4.4,
|
|
15
|
+
acceleration: 12,
|
|
16
|
+
deceleration: 16
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export interface CharacterMoveInput {
|
|
20
|
+
/** A direction key is held. */
|
|
21
|
+
readonly move: boolean;
|
|
22
|
+
/** The run modifier is held. */
|
|
23
|
+
readonly run: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface CharacterControllerState {
|
|
27
|
+
readonly speed: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Advance toward the target speed (walk/run/stop) with accel/decel. Pure + deterministic. */
|
|
31
|
+
export function stepCharacterSpeed(
|
|
32
|
+
state: CharacterControllerState,
|
|
33
|
+
input: CharacterMoveInput,
|
|
34
|
+
dt: number,
|
|
35
|
+
tuning: CharacterControllerTuning = defaultCharacterControllerTuning
|
|
36
|
+
): CharacterControllerState {
|
|
37
|
+
const target = input.move ? (input.run ? tuning.runSpeed : tuning.walkSpeed) : 0;
|
|
38
|
+
const rate = target > state.speed ? tuning.acceleration : tuning.deceleration;
|
|
39
|
+
const step = Math.max(0, rate) * Math.max(0, dt);
|
|
40
|
+
let speed = state.speed;
|
|
41
|
+
if (Math.abs(target - speed) <= step) speed = target;
|
|
42
|
+
else speed += Math.sign(target - speed) * step;
|
|
43
|
+
return { speed: Math.max(0, speed) };
|
|
44
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Character controller preview: keyboard input -> kinematic speed -> @aura3d/animation locomotion
|
|
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.
|
|
4
|
+
import { createLocomotionKit } from "@aura3d/animation";
|
|
5
|
+
import { defaultCharacterControllerTuning, stepCharacterSpeed, type CharacterControllerState } from "./controller.js";
|
|
6
|
+
|
|
7
|
+
interface CharacterControllerProof {
|
|
8
|
+
speed: number;
|
|
9
|
+
state: string;
|
|
10
|
+
moving: boolean;
|
|
11
|
+
running: boolean;
|
|
12
|
+
clipWeights: ReadonlyArray<{ clip: string; weight: number }>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
declare global {
|
|
16
|
+
interface Window {
|
|
17
|
+
__AURA3D_CHARACTER_CONTROLLER_PROOF__?: CharacterControllerProof;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const tuning = defaultCharacterControllerTuning;
|
|
22
|
+
const kit = createLocomotionKit({ idleClip: "Idle", walkClip: "Walk", runClip: "Run", walkSpeed: tuning.walkSpeed, runSpeed: tuning.runSpeed });
|
|
23
|
+
|
|
24
|
+
const moveKeys = new Set(["KeyW", "KeyA", "KeyS", "KeyD", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"]);
|
|
25
|
+
const held = new Set<string>();
|
|
26
|
+
window.addEventListener("keydown", (event) => held.add(event.code));
|
|
27
|
+
window.addEventListener("keyup", (event) => held.delete(event.code));
|
|
28
|
+
|
|
29
|
+
const root = document.getElementById("app") ?? document.body;
|
|
30
|
+
const hud = document.createElement("pre");
|
|
31
|
+
hud.id = "character-controller-hud";
|
|
32
|
+
hud.style.cssText = "font:14px monospace;padding:16px;color:#6cf;background:#0c0f16;min-height:140px";
|
|
33
|
+
root.appendChild(hud);
|
|
34
|
+
|
|
35
|
+
let state: CharacterControllerState = { speed: 0 };
|
|
36
|
+
let last = 0;
|
|
37
|
+
|
|
38
|
+
function frame(time: number): void {
|
|
39
|
+
const dt = last === 0 ? 1 / 60 : Math.min(0.05, (time - last) / 1000);
|
|
40
|
+
last = time;
|
|
41
|
+
const move = [...held].some((code) => moveKeys.has(code));
|
|
42
|
+
const run = held.has("ShiftLeft") || held.has("ShiftRight");
|
|
43
|
+
state = stepCharacterSpeed(state, { move, run }, dt, tuning);
|
|
44
|
+
const sample = kit.sample(state.speed, dt);
|
|
45
|
+
const proof: CharacterControllerProof = {
|
|
46
|
+
speed: Number(state.speed.toFixed(3)),
|
|
47
|
+
state: sample.state,
|
|
48
|
+
moving: sample.moving,
|
|
49
|
+
running: sample.running,
|
|
50
|
+
clipWeights: sample.clipWeights.map((w) => ({ clip: w.clip, weight: Number(w.weight.toFixed(3)) }))
|
|
51
|
+
};
|
|
52
|
+
window.__AURA3D_CHARACTER_CONTROLLER_PROOF__ = proof;
|
|
53
|
+
hud.textContent = [
|
|
54
|
+
"Aura3D Character Controller — hold W/A/S/D (Shift = run)",
|
|
55
|
+
`speed: ${proof.speed}`,
|
|
56
|
+
`state: ${proof.state}`,
|
|
57
|
+
`clips: ${proof.clipWeights.map((w) => `${w.clip} ${w.weight}`).join(" ")}`
|
|
58
|
+
].join("\n");
|
|
59
|
+
requestAnimationFrame(frame);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
requestAnimationFrame(frame);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
test("character controller route exposes a live locomotion proof", async ({ page }) => {
|
|
4
|
+
const errors: string[] = [];
|
|
5
|
+
page.on("pageerror", (error) => errors.push(error.message));
|
|
6
|
+
|
|
7
|
+
await page.goto("/");
|
|
8
|
+
await page.waitForFunction(() => Boolean((window as unknown as { __AURA3D_CHARACTER_CONTROLLER_PROOF__?: unknown }).__AURA3D_CHARACTER_CONTROLLER_PROOF__));
|
|
9
|
+
|
|
10
|
+
// idle at rest
|
|
11
|
+
const idle = await page.evaluate(() => (window as unknown as { __AURA3D_CHARACTER_CONTROLLER_PROOF__?: { state: string } }).__AURA3D_CHARACTER_CONTROLLER_PROOF__);
|
|
12
|
+
expect(idle!.state).toBe("idle");
|
|
13
|
+
|
|
14
|
+
// holding a movement key accelerates into walk/run
|
|
15
|
+
await page.keyboard.down("KeyD");
|
|
16
|
+
await page.waitForTimeout(600);
|
|
17
|
+
const moving = await page.evaluate(() => (window as unknown as { __AURA3D_CHARACTER_CONTROLLER_PROOF__?: { state: string; speed: number; clipWeights: { weight: number }[] } }).__AURA3D_CHARACTER_CONTROLLER_PROOF__);
|
|
18
|
+
await page.keyboard.up("KeyD");
|
|
19
|
+
|
|
20
|
+
expect(moving!.speed).toBeGreaterThan(0.1);
|
|
21
|
+
expect(["walk", "run"]).toContain(moving!.state);
|
|
22
|
+
const sum = moving!.clipWeights.reduce((acc, w) => acc + w.weight, 0);
|
|
23
|
+
expect(sum).toBeGreaterThan(0.9);
|
|
24
|
+
expect(sum).toBeLessThan(1.1);
|
|
25
|
+
expect(errors).toEqual([]);
|
|
26
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
test("captures the character controller preview", async ({ page }) => {
|
|
4
|
+
await page.goto("/");
|
|
5
|
+
await page.waitForFunction(() => Boolean((window as unknown as { __AURA3D_CHARACTER_CONTROLLER_PROOF__?: unknown }).__AURA3D_CHARACTER_CONTROLLER_PROOF__));
|
|
6
|
+
const hud = page.locator("#character-controller-hud");
|
|
7
|
+
await expect(hud).toContainText("Character Controller");
|
|
8
|
+
await page.screenshot({ path: "test-results/character-controller-preview.png" });
|
|
9
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"types": ["node"],
|
|
11
|
+
"verbatimModuleSyntax": false,
|
|
12
|
+
"allowImportingTsExtensions": false
|
|
13
|
+
},
|
|
14
|
+
"include": ["src", "scripts"]
|
|
15
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Aura3D Episode Builder Template
|
|
2
2
|
|
|
3
|
-
> **Status: example / experimental.** The flagship
|
|
4
|
-
> [`
|
|
3
|
+
> **Status: example / experimental.** The flagship animation pipeline is the
|
|
4
|
+
> [`animation-studio`](../animation-studio) template. This template is a
|
|
5
5
|
> contract/example only.
|
|
6
6
|
|
|
7
7
|
This template demonstrates a guided prompt-to-episode builder on top of the
|
|
@@ -27,7 +27,7 @@ Replace primitive characters with typed GLB assets by running:
|
|
|
27
27
|
```bash
|
|
28
28
|
npx @aura3d/cli@latest assets add ./assets/miko.glb --name miko
|
|
29
29
|
npx @aura3d/cli@latest assets add ./assets/luma.glb --name luma
|
|
30
|
-
npx @aura3d/cli@latest assets validate-
|
|
30
|
+
npx @aura3d/cli@latest assets validate-animation
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
Then import `assets.miko` and `assets.luma` from `src/aura-assets.ts` and pass them to `model(assets.miko)` and `model(assets.luma)`.
|
|
@@ -45,6 +45,6 @@ Do not replace this with a string asset id or a raw loader.
|
|
|
45
45
|
|
|
46
46
|
This scaffold intentionally does not claim publish readiness from source alone.
|
|
47
47
|
Before closing build, route, asset, screenshot, render, or visual-quality gates,
|
|
48
|
-
archive the matching `npm run build`, `assets validate-
|
|
48
|
+
archive the matching `npm run build`, `assets validate-animation`, browser
|
|
49
49
|
evidence, screenshot hashes, render outputs, and human or automated review
|
|
50
50
|
artifacts.
|
|
@@ -9,6 +9,6 @@ export const assets = defineAuraAssets({
|
|
|
9
9
|
*
|
|
10
10
|
* npx @aura3d/cli@latest assets add ./assets/miko.glb --name miko
|
|
11
11
|
* npx @aura3d/cli@latest assets add ./assets/luma.glb --name luma
|
|
12
|
-
* npx @aura3d/cli@latest assets validate-
|
|
12
|
+
* npx @aura3d/cli@latest assets validate-animation
|
|
13
13
|
*/
|
|
14
14
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { episode,
|
|
1
|
+
import { episode, publicAnimationAssetInstructions, typedAnimationAssetSummary } from "./episode";
|
|
2
2
|
import { publishReadiness } from "./render-plan";
|
|
3
3
|
|
|
4
4
|
export const episodeBuilderSupport = {
|
|
@@ -26,9 +26,9 @@ export const episodeBuilderSupport = {
|
|
|
26
26
|
renderQueueItems: episode.renderQueue.items.length
|
|
27
27
|
},
|
|
28
28
|
typedAssets: {
|
|
29
|
-
requiredCharacters:
|
|
30
|
-
missingCharacters:
|
|
31
|
-
commands:
|
|
29
|
+
requiredCharacters: typedAnimationAssetSummary.requiredCharacterAssets,
|
|
30
|
+
missingCharacters: typedAnimationAssetSummary.missingCharacterAssets,
|
|
31
|
+
commands: publicAnimationAssetInstructions
|
|
32
32
|
}
|
|
33
33
|
} as const;
|
|
34
34
|
|
|
@@ -4,37 +4,37 @@ import { AURAVOICE_AURA3D_PROMPT_ANIMATION_CONTRACT_ID } from "./contract";
|
|
|
4
4
|
|
|
5
5
|
export const episodeContractId = AURAVOICE_AURA3D_PROMPT_ANIMATION_CONTRACT_ID;
|
|
6
6
|
|
|
7
|
-
export type
|
|
7
|
+
export type AnimationAssetKey = "miko" | "luma" | "glowBroom" | "glowStones" | "moonLilies";
|
|
8
8
|
|
|
9
|
-
type
|
|
9
|
+
type TypedAnimationAssets = Partial<Record<AnimationAssetKey, AuraAssetRef<"model">>>;
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const typedAnimationAssets = assets as TypedAnimationAssets;
|
|
12
12
|
|
|
13
|
-
export const
|
|
14
|
-
export const
|
|
15
|
-
export const
|
|
13
|
+
export const requiredAnimationCharacterAssets = ["miko", "luma"] as const;
|
|
14
|
+
export const optionalAnimationPropAssets = ["glowBroom", "glowStones", "moonLilies"] as const;
|
|
15
|
+
export const publicAnimationAssetInstructions = [
|
|
16
16
|
"npx @aura3d/cli@latest assets add ./assets/miko.glb --name miko",
|
|
17
17
|
"npx @aura3d/cli@latest assets add ./assets/luma.glb --name luma",
|
|
18
|
-
"npx @aura3d/cli@latest assets validate-
|
|
18
|
+
"npx @aura3d/cli@latest assets validate-animation"
|
|
19
19
|
] as const;
|
|
20
20
|
|
|
21
|
-
export const
|
|
22
|
-
export const
|
|
23
|
-
requiredCharacterAssets:
|
|
24
|
-
optionalPropAssets:
|
|
25
|
-
typedCharacterAssetCount:
|
|
26
|
-
missingCharacterAssets:
|
|
21
|
+
export const missingAnimationCharacterAssets = requiredAnimationCharacterAssets.filter((key) => !typedAnimationAssets[key]);
|
|
22
|
+
export const typedAnimationAssetSummary = {
|
|
23
|
+
requiredCharacterAssets: requiredAnimationCharacterAssets,
|
|
24
|
+
optionalPropAssets: optionalAnimationPropAssets,
|
|
25
|
+
typedCharacterAssetCount: requiredAnimationCharacterAssets.length - missingAnimationCharacterAssets.length,
|
|
26
|
+
missingCharacterAssets: missingAnimationCharacterAssets
|
|
27
27
|
} as const;
|
|
28
28
|
|
|
29
|
-
function typedAsset(key:
|
|
30
|
-
return
|
|
29
|
+
function typedAsset(key: AnimationAssetKey): AuraAssetRef<"model"> | undefined {
|
|
30
|
+
return typedAnimationAssets[key];
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export const youtubeDraftMetadata = {
|
|
34
34
|
contractId: episodeContractId,
|
|
35
35
|
title: "Moon Garden Cleanup | Aura3D Episode Builder",
|
|
36
36
|
description: "Two tiny robots clean a glowing moon garden with soft captions and reduced-flash visuals.",
|
|
37
|
-
tags: ["Aura3D", "kids
|
|
37
|
+
tags: ["Aura3D", "kids animation", "moon garden", "robots"],
|
|
38
38
|
madeForKids: true,
|
|
39
39
|
thumbnailCaptureTime: 10,
|
|
40
40
|
defaultLanguage: "en",
|
|
@@ -77,15 +77,15 @@ export const episodeSampleDescription = {
|
|
|
77
77
|
shotCount: 3,
|
|
78
78
|
speakingCharacters: ["miko", "luma"],
|
|
79
79
|
captionSource: "captions are derived one-to-one from the AuraVoice dialogue track",
|
|
80
|
-
performanceSource: "body, facial, gesture, blocking, and gaze cues are generated from the
|
|
80
|
+
performanceSource: "body, facial, gesture, blocking, and gaze cues are generated from the animation director",
|
|
81
81
|
musicAmbience: ["music:moon-garden-lullaby", "ambience:moon-garden-night"],
|
|
82
82
|
sfxCue: "sfx:glow-stone-chime",
|
|
83
83
|
thumbnailCaptureTime: youtubeDraftMetadata.thumbnailCaptureTime,
|
|
84
84
|
thumbnailSource: "same Aura3D scene state and AuraVoice timestamp as the render queue capture",
|
|
85
85
|
typedAssetSource: "./src/aura-assets",
|
|
86
|
-
requiredTypedAssets:
|
|
87
|
-
missingTypedAssets:
|
|
88
|
-
assetCommands:
|
|
86
|
+
requiredTypedAssets: requiredAnimationCharacterAssets,
|
|
87
|
+
missingTypedAssets: missingAnimationCharacterAssets,
|
|
88
|
+
assetCommands: publicAnimationAssetInstructions,
|
|
89
89
|
reviewPackageRequiredPaths: ["video", "captions", "thumbnail", "timeline", "audio-stems", "evidence-json", "youtube-draft-metadata"],
|
|
90
90
|
accessibilityProof: ["captions", "reduced motion", "high contrast"]
|
|
91
91
|
} as const;
|
|
@@ -167,7 +167,7 @@ export const episode = compilePromptEpisodePlan({
|
|
|
167
167
|
}
|
|
168
168
|
],
|
|
169
169
|
styleGuide: {
|
|
170
|
-
visualStyle: "rounded bedtime sci-fi
|
|
170
|
+
visualStyle: "rounded bedtime sci-fi animation with toy-like robot silhouettes",
|
|
171
171
|
palette: ["#081b2a", "#7de2ff", "#ffe18e", "#40ffbf", "#f8fff2"],
|
|
172
172
|
shapeLanguage: "circles, capsules, crescent props, and chunky moon-garden forms",
|
|
173
173
|
lighting: "soft blue night key, warm prop glows, no hard flashes",
|
|
@@ -20,11 +20,11 @@ import { assets } from "./aura-assets";
|
|
|
20
20
|
import {
|
|
21
21
|
episode,
|
|
22
22
|
episodeContractId,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
type
|
|
23
|
+
missingAnimationCharacterAssets,
|
|
24
|
+
publicAnimationAssetInstructions,
|
|
25
|
+
requiredAnimationCharacterAssets,
|
|
26
|
+
typedAnimationAssetSummary,
|
|
27
|
+
type AnimationAssetKey
|
|
28
28
|
} from "./episode";
|
|
29
29
|
import {
|
|
30
30
|
accessibilityProofMetadata,
|
|
@@ -49,7 +49,7 @@ import { episodeBuilderSupport, installEpisodeBuilderPanel } from "./builder";
|
|
|
49
49
|
|
|
50
50
|
declare global {
|
|
51
51
|
interface Window {
|
|
52
|
-
|
|
52
|
+
__AURA3D_ANIMATION_TEMPLATE__?: {
|
|
53
53
|
readonly contractId: string;
|
|
54
54
|
readonly template: string;
|
|
55
55
|
readonly storyBible: unknown;
|
|
@@ -78,7 +78,7 @@ const firstCaption = episode.captionTrack.cues[0];
|
|
|
78
78
|
const thumbnailCapture = renderOutputPackage.thumbnailCapture;
|
|
79
79
|
const thumbnailCaption = captionCueAtTime(episode.captionTrack, thumbnailCapture.time);
|
|
80
80
|
const storyBible = episode.storyBible;
|
|
81
|
-
const
|
|
81
|
+
const typedAnimationAssets = assets as Partial<Record<AnimationAssetKey, AuraAssetRef<"model">>>;
|
|
82
82
|
|
|
83
83
|
const captionOverlay = document.createElement("div");
|
|
84
84
|
captionOverlay.id = "caption-overlay";
|
|
@@ -114,12 +114,12 @@ const shotPlaybackPlan = createShotPlaybackPlan({
|
|
|
114
114
|
});
|
|
115
115
|
|
|
116
116
|
const playbackProbeTimes = [1, 21, 43] as const;
|
|
117
|
-
const playbackProbeSamples = playbackProbeTimes.map((time) =>
|
|
117
|
+
const playbackProbeSamples = playbackProbeTimes.map((time) => sampleAnimationRouteAt(time));
|
|
118
118
|
captionOverlay.dataset.shotId = playbackProbeSamples[0]?.shotId ?? "";
|
|
119
119
|
captionOverlay.dataset.captionId = playbackProbeSamples[0]?.captionId ?? firstCaption?.captionId ?? "";
|
|
120
|
-
document.body.dataset.
|
|
121
|
-
document.body.dataset.
|
|
122
|
-
document.body.dataset.
|
|
120
|
+
document.body.dataset.animationShotCount = String(episode.shotTimeline.shots.length);
|
|
121
|
+
document.body.dataset.animationCaptionCount = String(episode.captionTrack.cues.length);
|
|
122
|
+
document.body.dataset.animationStoryBibleProps = String(storyBible.props.length);
|
|
123
123
|
document.body.dataset.episodeBuilderFormats = episodeBuilderSupport.formats.map((format) => format.id).join(",");
|
|
124
124
|
installEpisodeBuilderPanel(document.body);
|
|
125
125
|
|
|
@@ -155,7 +155,7 @@ const app = createAuraApp("#app", {
|
|
|
155
155
|
diagnostics: true
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
window.
|
|
158
|
+
window.__AURA3D_ANIMATION_TEMPLATE__ = {
|
|
159
159
|
contractId: episodeContractId,
|
|
160
160
|
template: "episode-builder",
|
|
161
161
|
storyBible,
|
|
@@ -164,10 +164,10 @@ window.__AURA3D_CARTOON_TEMPLATE__ = {
|
|
|
164
164
|
playbackProbeTimes,
|
|
165
165
|
playbackProbeSamples,
|
|
166
166
|
renderQueueItems: renderPlan.items.length,
|
|
167
|
-
typedAssets:
|
|
168
|
-
requiredTypedAssets:
|
|
169
|
-
missingTypedAssets:
|
|
170
|
-
assetCommands:
|
|
167
|
+
typedAssets: typedAnimationAssetSummary,
|
|
168
|
+
requiredTypedAssets: requiredAnimationCharacterAssets,
|
|
169
|
+
missingTypedAssets: missingAnimationCharacterAssets,
|
|
170
|
+
assetCommands: publicAnimationAssetInstructions,
|
|
171
171
|
bridgeIssues,
|
|
172
172
|
promptAnimationEvidence,
|
|
173
173
|
publishReadiness,
|
|
@@ -179,7 +179,7 @@ window.__AURA3D_CARTOON_TEMPLATE__ = {
|
|
|
179
179
|
},
|
|
180
180
|
sampleRenderSourceWorkflow,
|
|
181
181
|
sampleAt(time: number) {
|
|
182
|
-
return
|
|
182
|
+
return sampleAnimationRouteAt(time);
|
|
183
183
|
}
|
|
184
184
|
};
|
|
185
185
|
|
|
@@ -198,13 +198,13 @@ installShotPlayback(app, shotPlaybackPlan, {
|
|
|
198
198
|
function createCharacterBody(
|
|
199
199
|
id: "miko" | "luma",
|
|
200
200
|
name: string,
|
|
201
|
-
assetKey:
|
|
201
|
+
assetKey: AnimationAssetKey,
|
|
202
202
|
position: readonly [number, number, number],
|
|
203
203
|
fallbackScale: readonly [number, number, number],
|
|
204
204
|
modelScale: number,
|
|
205
205
|
color: string
|
|
206
206
|
) {
|
|
207
|
-
const asset =
|
|
207
|
+
const asset = typedAnimationAssets[assetKey];
|
|
208
208
|
const runtime = game.runtimeNode(id, { tags: ["character", id, asset ? "typed-asset" : "primitive-fallback"] });
|
|
209
209
|
if (asset) {
|
|
210
210
|
return model(asset, { name: `${name} typed character asset` })
|
|
@@ -233,7 +233,7 @@ function createMouthCard(id: "miko:mouth" | "luma:mouth", name: string, position
|
|
|
233
233
|
.runtime(game.runtimeNode(id, { tags: ["mouth", "primitive", name.toLowerCase()] }));
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
-
function
|
|
236
|
+
function sampleAnimationRouteAt(time: number) {
|
|
237
237
|
const bridgeSample = sampleAuraVoiceBridgeAtTime(auraVoicePackage, time);
|
|
238
238
|
const playbackSample = sampleShotPlaybackPlan(shotPlaybackPlan, time);
|
|
239
239
|
const caption = captionCueAtTime(episode.captionTrack, time);
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
createAuraVoiceVisemeTrack,
|
|
6
6
|
createCaptionTimingProof,
|
|
7
7
|
createGlbBlendshapeVisemeCue,
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
createAnimationPerformanceCoverage,
|
|
9
|
+
createAnimationRenderOutputPackageMetadata,
|
|
10
10
|
createPrimitiveMouthVisemeCues,
|
|
11
11
|
createPromptAnimationDeterministicScreenshotFixtureMetadata,
|
|
12
12
|
evaluatePromptAnimationPublishReadiness,
|
|
@@ -21,10 +21,10 @@ import {
|
|
|
21
21
|
episode,
|
|
22
22
|
episodeAudioCues,
|
|
23
23
|
episodeContractId,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
missingAnimationCharacterAssets,
|
|
25
|
+
publicAnimationAssetInstructions,
|
|
26
|
+
requiredAnimationCharacterAssets,
|
|
27
|
+
typedAnimationAssetSummary,
|
|
28
28
|
youtubeDraftMetadata
|
|
29
29
|
} from "./episode";
|
|
30
30
|
|
|
@@ -34,7 +34,7 @@ export const renderContractId = episodeContractId;
|
|
|
34
34
|
|
|
35
35
|
export const renderPlan = episode.renderQueue;
|
|
36
36
|
|
|
37
|
-
export const renderOutputPackage =
|
|
37
|
+
export const renderOutputPackage = createAnimationRenderOutputPackageMetadata({
|
|
38
38
|
episodePlan: episode.episodePlan,
|
|
39
39
|
shotTimeline: episode.shotTimeline,
|
|
40
40
|
renderQueue: renderPlan,
|
|
@@ -255,7 +255,7 @@ export const phonemeVisemeDubSyncSourceProof = {
|
|
|
255
255
|
executionBoundary: "Source harness only; actual phoneme, viseme, and dub playback proof requires rendered frame/video evidence."
|
|
256
256
|
} as const;
|
|
257
257
|
|
|
258
|
-
export const performanceCoverage =
|
|
258
|
+
export const performanceCoverage = createAnimationPerformanceCoverage(episode.performance, episode.dialogueTrack);
|
|
259
259
|
|
|
260
260
|
export const reviewPackagePaths = renderOutputPackage.reviewPackagePaths;
|
|
261
261
|
|
|
@@ -283,10 +283,10 @@ export const sampleRenderSourceWorkflow = {
|
|
|
283
283
|
resolution: episode.episodePlan.runtime.resolution,
|
|
284
284
|
shotCount: episode.shotTimeline.shots.length,
|
|
285
285
|
speakingCharacterIds: Array.from(new Set(episode.dialogueTrack.lines.map((line) => line.speakerId))),
|
|
286
|
-
requiredTypedAssets:
|
|
287
|
-
typedAssetSummary:
|
|
288
|
-
missingTypedCharacterAssets:
|
|
289
|
-
assetCommands:
|
|
286
|
+
requiredTypedAssets: requiredAnimationCharacterAssets,
|
|
287
|
+
typedAssetSummary: typedAnimationAssetSummary,
|
|
288
|
+
missingTypedCharacterAssets: missingAnimationCharacterAssets,
|
|
289
|
+
assetCommands: publicAnimationAssetInstructions,
|
|
290
290
|
audioStemRoles: audioStemManifest.stems.map((stem) => stem.role),
|
|
291
291
|
requiresNoManualTimingEdits: true,
|
|
292
292
|
doesNotClaimRenderedArtifacts: true,
|
|
@@ -357,7 +357,7 @@ export const sampleRenderSourceWorkflow = {
|
|
|
357
357
|
"Fresh scaffold npm run build output",
|
|
358
358
|
"Browser route health and storyboard playback output",
|
|
359
359
|
"Typed character GLBs added through src/aura-assets.ts",
|
|
360
|
-
"npx @aura3d/cli@latest assets validate-
|
|
360
|
+
"npx @aura3d/cli@latest assets validate-animation output",
|
|
361
361
|
"Actual 60-second MP4/WebM render artifact",
|
|
362
362
|
"Actual thumbnail artifact captured from the same Aura3D scene state",
|
|
363
363
|
"Actual captions/timeline/audio-stems/evidence JSON files with hashes",
|