Skip to content

Commit c4d92a1

Browse files
Merge pull request #38 from posecode-dev/codex/refresh-moves-and-mannequin
Refresh movement pages and mannequin startup
2 parents 3c9edf7 + b984b9b commit c4d92a1

80 files changed

Lines changed: 158 additions & 4 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/posecode-render/src/index.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ export interface ViewerOptions {
8383
* skeleton, rebuilt to the character's exact proportions (see character.ts).
8484
*/
8585
characterUrl?: string;
86+
/**
87+
* Show the procedural figure while `characterUrl` loads. Defaults to true
88+
* for embeds and offline-friendly consumers. Set false when a brief empty
89+
* stage is preferable to flashing the procedural figure before the skinned
90+
* character appears. The procedural figure is still revealed if loading
91+
* fails, so the viewer never remains permanently blank.
92+
*/
93+
showProceduralWhileLoading?: boolean;
8694
/**
8795
* Mocap clip library: clip name (as written in a document's `clip "<name>"`
8896
* directive) → FBX/GLB asset URL. When a loaded document names a clip found
@@ -174,6 +182,9 @@ export function createViewer(
174182

175183
let mannequin: Mannequin = buildMannequin();
176184
enableShadows(mannequin.root);
185+
if (opts.characterUrl && opts.showProceduralWhileLoading === false) {
186+
setMannequinMeshesVisible(mannequin.root, false);
187+
}
177188
scene.add(mannequin.root);
178189

179190
// Skinned character layer (optional). While loading (and on failure) the
@@ -768,8 +779,9 @@ export function createViewer(
768779
else char.sync(mannequin);
769780
})
770781
.catch(() => {
771-
// Keep the procedural figure. Deliberately silent: an offline embed
772-
// or a blocked CDN should degrade, not error.
782+
// Reveal the fallback if it was hidden during loading. Deliberately
783+
// silent: an offline embed or blocked CDN should degrade, not error.
784+
setMannequinMeshesVisible(mannequin.root, true);
773785
});
774786
}
775787

@@ -785,6 +797,12 @@ function enableShadows(root: THREE.Object3D): void {
785797
});
786798
}
787799

800+
function setMannequinMeshesVisible(root: THREE.Object3D, visible: boolean): void {
801+
root.traverse((obj) => {
802+
if ((obj as THREE.Mesh).isMesh) obj.visible = visible;
803+
});
804+
}
805+
788806
/** Free GPU resources for a discarded subtree (prop set swapped on reload). */
789807
function disposeTree(root: THREE.Object3D): void {
790808
root.traverse((obj) => {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
:root{--bg:#0b0c0d;--panel:#111315;--panel-2:#171a1d;--border:#292d30;--border-2:#3a3f43;
2+
--text:#f2f1eb;--text-2:#aaa9a2;--muted:#74746f;--accent:#d4ff3f;
3+
--accent-ink:#0b0c0d;--accent-line:rgba(212,255,63,.42);--radius:3px}
4+
body{background:var(--bg);color:var(--text)}
5+
.wrap{max-width:1180px;padding-left:28px;padding-right:28px}
6+
header.site-nav{position:sticky;top:0;z-index:10;margin-bottom:0;padding:18px 0;
7+
background:rgba(11,12,13,.94);backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px)}
8+
nav.links{gap:24px}
9+
main{padding-top:clamp(54px,8vw,96px);padding-bottom:80px}
10+
.eyebrow{color:var(--text-2);margin-bottom:16px}
11+
h1{max-width:13ch;font-size:clamp(46px,7vw,82px);letter-spacing:-.055em;line-height:.94;
12+
margin-bottom:24px;text-wrap:balance}
13+
h2{font-size:clamp(24px,3vw,34px);letter-spacing:-.035em;margin:58px 0 18px}
14+
p{max-width:760px;font-size:16px;margin-bottom:18px}
15+
code{border-radius:2px}
16+
pre.code-block{background:#0e1011;border-radius:2px;padding:20px 22px}
17+
.card{border-radius:0;background:transparent}
18+
.btn{background:var(--accent);border-radius:3px;padding:12px 19px}
19+
.btn:hover{filter:none;transform:translateY(-1px)}
20+
.steps{gap:0;border-top:1px solid var(--border)}
21+
.steps li{border:0;border-bottom:1px solid var(--border);border-radius:0;padding:20px 0;background:transparent}
22+
.chip-list{gap:0;border-top:1px solid var(--border);border-left:1px solid var(--border)}
23+
.chip-list a{background:transparent;border:0;border-right:1px solid var(--border);
24+
border-bottom:1px solid var(--border);border-radius:0;padding:8px 13px}
25+
.chip-list a:hover{color:var(--bg);background:var(--text);border-color:var(--border)}
26+
.domain-group{margin:64px 0 0}
27+
.move-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:0;border-top:1px solid var(--border);
28+
border-left:1px solid var(--border)}
29+
.move-card{display:flex;min-height:126px;flex-direction:column;justify-content:space-between;
30+
border:0;border-right:1px solid var(--border);border-bottom:1px solid var(--border);border-radius:0;
31+
padding:19px 20px;background:transparent}
32+
.move-card:hover{background:var(--text);border-color:var(--border)}
33+
.move-card .mc-name{font-size:16px;letter-spacing:-.2px}
34+
.move-card .mc-meta{font-family:var(--mono);font-size:10.5px;margin-top:16px}
35+
.move-card:hover .mc-name{color:var(--bg)}
36+
.move-card:hover .mc-meta{color:#555853}
37+
footer.site-footer{padding:34px 0 48px}
38+
@media(max-width:820px){
39+
nav.links a:nth-child(n+4){display:none}
40+
.move-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
41+
}
42+
@media(max-width:600px){
43+
.wrap{padding-left:18px;padding-right:18px}
44+
header.site-nav{padding:14px 0}
45+
nav.links{gap:14px}
46+
nav.links a:nth-child(n+3){display:none}
47+
main{padding-top:48px}
48+
h1{font-size:clamp(44px,14vw,62px)}
49+
.move-grid{grid-template-columns:1fr}
50+
.move-card{min-height:104px}
51+
.domain-group{margin-top:48px}
52+
}

playground/public/llm-guide.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
footer.site-footer p{font-size:12.5px;color:var(--muted);margin:0 0 6px;max-width:70ch}
9999
@media(max-width:600px){.wrap{padding:0 18px}}
100100
</style>
101+
<link rel="stylesheet" href="/content-theme.css" />
101102

102103
<script>
103104
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };

playground/public/moves/arm-circles.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
footer.site-footer p{font-size:12.5px;color:var(--muted);margin:0 0 6px;max-width:70ch}
9999
@media(max-width:600px){.wrap{padding:0 18px}}
100100
</style>
101+
<link rel="stylesheet" href="/content-theme.css" />
101102
<script type="application/ld+json">{"@context":"https://schema.org","@type":"HowTo","name":"How to do a Arm circles","description":"How to do the arm circles (warm-up): 3 phases targeting the deltoids, body weight, beginner level. Animated 3D guide generated from Posecode, a text-to-motion language for LLMs.","step":[{"@type":"HowToStep","name":"Up & forward","text":"Sweep the arms up and forward"},{"@type":"HowToStep","name":"Out to sides","text":"Open the arms out wide to the sides"},{"@type":"HowToStep","name":"Down & round","text":"Lower and continue the circle back to the start"}]}</script>
102103
<script>
103104
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };

playground/public/moves/bent-over-row.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
footer.site-footer p{font-size:12.5px;color:var(--muted);margin:0 0 6px;max-width:70ch}
9999
@media(max-width:600px){.wrap{padding:0 18px}}
100100
</style>
101+
<link rel="stylesheet" href="/content-theme.css" />
101102
<script type="application/ld+json">{"@context":"https://schema.org","@type":"HowTo","name":"How to do a Bent-over row","description":"How to do the bent-over row (fitness): 4 phases targeting the lats, body weight, intermediate level. Animated 3D guide generated from Posecode, a text-to-motion language for LLMs.","step":[{"@type":"HowToStep","name":"Set the hinge","text":"Hinge to a flat back, let the arms hang straight down"},{"@type":"HowToStep","name":"Row","text":"Drive the elbows up past the ribs, squeeze the shoulder blades"},{"@type":"HowToStep","name":"Lower","text":"Lower the bar under control, keep the back flat"},{"@type":"HowToStep","name":"Stand","text":"Stand up tall between sets"}]}</script>
102103
<script>
103104
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };

playground/public/moves/biceps.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
footer.site-footer p{font-size:12.5px;color:var(--muted);margin:0 0 6px;max-width:70ch}
9999
@media(max-width:600px){.wrap{padding:0 18px}}
100100
</style>
101+
<link rel="stylesheet" href="/content-theme.css" />
101102
<script type="application/ld+json">{"@context":"https://schema.org","@type":"HowTo","name":"How to do a Biceps curl","description":"How to do the biceps curl (fitness): 2 phases targeting the biceps, body weight, beginner level. Animated 3D guide generated from Posecode, a text-to-motion language for LLMs.","step":[{"@type":"HowToStep","name":"Curl","text":"Curl up, keep the elbows tucked at your sides"},{"@type":"HowToStep","name":"Lower","text":"Lower under control: don't swing"}]}</script>
102103
<script>
103104
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };

playground/public/moves/bicycle-crunch.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
footer.site-footer p{font-size:12.5px;color:var(--muted);margin:0 0 6px;max-width:70ch}
9999
@media(max-width:600px){.wrap{padding:0 18px}}
100100
</style>
101+
<link rel="stylesheet" href="/content-theme.css" />
101102
<script type="application/ld+json">{"@context":"https://schema.org","@type":"HowTo","name":"How to do a Bicycle crunch","description":"How to do the bicycle crunch (fitness): 4 phases targeting the obliques, body weight, intermediate level. Animated 3D guide generated from Posecode, a text-to-motion language for LLMs.","step":[{"@type":"HowToStep","name":"Set","text":"Hands by the ears, knees over the hips, shoulders lifted"},{"@type":"HowToStep","name":"Right to left","text":"Right elbow toward the left knee; the right leg extends long"},{"@type":"HowToStep","name":"Left to right","text":"Switch: left elbow toward the right knee"},{"@type":"HowToStep","name":"Center","text":"Return to center, knees stacked over the hips"}]}</script>
102103
<script>
103104
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };

playground/public/moves/bow.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
footer.site-footer p{font-size:12.5px;color:var(--muted);margin:0 0 6px;max-width:70ch}
9999
@media(max-width:600px){.wrap{padding:0 18px}}
100100
</style>
101+
<link rel="stylesheet" href="/content-theme.css" />
101102
<script type="application/ld+json">{"@context":"https://schema.org","@type":"HowTo","name":"How to do a Standing bow","description":"How to do the standing bow (martial arts): 2 phases targeting the hamstrings, body weight, beginner level. Animated 3D guide generated from Posecode, a text-to-motion language for LLMs.","step":[{"@type":"HowToStep","name":"Bow","text":"Hinge forward from the hips into a respectful bow, back flat"},{"@type":"HowToStep","name":"Rise","text":"Return smoothly to standing"}]}</script>
102103
<script>
103104
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };

playground/public/moves/box-squat.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
footer.site-footer p{font-size:12.5px;color:var(--muted);margin:0 0 6px;max-width:70ch}
9999
@media(max-width:600px){.wrap{padding:0 18px}}
100100
</style>
101+
<link rel="stylesheet" href="/content-theme.css" />
101102
<script type="application/ld+json">{"@context":"https://schema.org","@type":"HowTo","name":"How to do a Box squat","description":"How to do the box squat (fitness): 2 phases targeting the quadriceps, chair, beginner level. Animated 3D guide generated from Posecode, a text-to-motion language for LLMs.","step":[{"@type":"HowToStep","name":"Sit back","text":"Push the hips back and sit lightly onto the box"},{"@type":"HowToStep","name":"Stand","text":"Drive up to standing without bouncing off the box"}]}</script>
102103
<script>
103104
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };

playground/public/moves/box-step-taps.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
footer.site-footer p{font-size:12.5px;color:var(--muted);margin:0 0 6px;max-width:70ch}
9999
@media(max-width:600px){.wrap{padding:0 18px}}
100100
</style>
101+
<link rel="stylesheet" href="/content-theme.css" />
101102
<script type="application/ld+json">{"@context":"https://schema.org","@type":"HowTo","name":"How to do a Box step taps","description":"How to do the box step taps (warm-up): 4 phases targeting the hip flexors, box, beginner level. Animated 3D guide generated from Posecode, a text-to-motion language for LLMs.","step":[{"@type":"HowToStep","name":"Right tap","text":"Tap the right foot lightly on top of the box"},{"@type":"HowToStep","name":"Right down","text":"Return the right foot to the floor"},{"@type":"HowToStep","name":"Left tap","text":"Tap the left foot on the box"},{"@type":"HowToStep","name":"Left down","text":"Back to the floor: keep a light, quick rhythm"}]}</script>
102103
<script>
103104
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };

0 commit comments

Comments
 (0)