Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified docs/media/deadlift.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/media/jumping-jacks.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/media/lateral-raise.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/media/squat.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions playground/src/clips.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Showcase mocap-clip map: clip name (as written in a doc's `clip "<name>"`
* directive) → retargeted animation asset URL. Shared by the playground viewer
* and the landing hero so both play the same Mixamo-sourced motion for the
* marketing surfaces, while the procedural DSL stays the source of truth for
* every un-clipped movement.
*
* The FBX binaries live in `public/clips/` (gitignored, served from storage/CDN
* in production). A movement plays its clip only when it declares `clip "<name>"`
* AND the skinned character is active; anything missing falls back to procedural.
*/
export const SHOWCASE_CLIPS: Record<string, string> = {
walk: "/clips/walk.fbx",
squat: "/clips/back-squat.fbx",
"bicycle-crunch": "/clips/bicycle-crunch.fbx",
"jab-cross": "/clips/jab-cross.fbx",
"jumping-jacks": "/clips/jumping-jacks.fbx",
shuffling: "/clips/shuffling.fbx",
};
4 changes: 4 additions & 0 deletions playground/src/landing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { parse } from "posecode-parser";
import { inject } from "@vercel/analytics";
import { PRESETS } from "./presets.js";
import { SHOWCASE_CLIPS } from "./clips.js";
import llmPrompt from "../../spec/llm-authoring.md?raw";

inject();
Expand All @@ -32,6 +33,9 @@ function initHero(): void {
// Realistic skinned figure without flashing the procedural fallback.
characterUrl: "/models/character.glb",
showProceduralWhileLoading: false,
// Marketing surface: the hero movement declares `clip "jumping-jacks"`, so
// it plays the retargeted Mixamo mocap for maximum polish on first paint.
clips: SHOWCASE_CLIPS,
});
const phaseEl = document.getElementById("hero-phase");
viewer.onPhase(({ phaseName }) => {
Expand Down
14 changes: 2 additions & 12 deletions playground/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from "./nice-share.js";
import type { PosecodeEditor } from "./editor.js";
import { PRESETS } from "./presets.js";
import { SHOWCASE_CLIPS } from "./clips.js";
import { renderWarnings } from "./warnings.js";
import llmPrompt from "../../spec/llm-authoring.md?raw";

Expand Down Expand Up @@ -548,18 +549,7 @@ void import("posecode-render").then(({ createViewer }) => {
// clips.ts). Only fetched when a loaded movement names the clip, so this
// never slows the default page. Disabled with the classic figure, which has
// no skinned mesh to retarget onto.
...(classicFigure
? {}
: {
clips: {
walk: "/clips/walk.fbx",
squat: "/clips/back-squat.fbx",
"bicycle-crunch": "/clips/bicycle-crunch.fbx",
"jab-cross": "/clips/jab-cross.fbx",
"jumping-jacks": "/clips/jumping-jacks.fbx",
shuffling: "/clips/shuffling.fbx",
},
}),
...(classicFigure ? {} : { clips: SHOWCASE_CLIPS }),
});
// Exposed for capture/e2e tooling (frame capture drives README GIFs).
(window as unknown as Record<string, unknown>).__posecodeViewer = viewer;
Expand Down
10 changes: 7 additions & 3 deletions scripts/capture-gifs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ if (targets.length === 0) {

const server = await createServer({
configFile: resolve(repoRoot, "playground/vite.config.ts"),
server: { port: 0 },
server: { port: 0, host: "127.0.0.1" },
logLevel: "error",
});
await server.listen();
const port = server.config.server.port ?? server.httpServer.address().port;
// Use the ACTUAL bound port: with `port: 0`, config.server.port stays 0 (and
// `0 ?? …` keeps 0), so read the listening socket instead.
const port = server.httpServer.address().port;
const origin = `http://127.0.0.1:${port}`;

const browser = await chromium.launch({ executablePath: chromiumPath() });
Expand All @@ -66,7 +68,9 @@ page.on("pageerror", (e) => console.error("[page]", e.message));

for (const t of targets) {
const [w, h] = t.size;
await page.goto(`${origin}/play/${t.id}`, { waitUntil: "load" });
// `/play/<id>` is a production rewrite (vercel); in the vite dev server used
// here it doesn't resolve, so use the SPA entry + hash which loads the doc.
await page.goto(`${origin}/play.html#doc=${t.id}`, { waitUntil: "load" });
await page.reload({ waitUntil: "load" });
await page.waitForFunction(() => window.__posecodeViewer?.duration > 0, null, {
timeout: 60000,
Expand Down
Loading