@@ -27,7 +27,7 @@ import {
2727 type ClipSource ,
2828} from "./clips.js" ;
2929import { depenetrate } from "./depenetrate.js" ;
30- import { alignFloorPalms , levelPlantedFeet , wrapGrip , relaxHands } from "./contacts.js" ;
30+ import { alignFloorPalms , levelPlantedFeet , wrapGrip , relaxHands , swingArms } from "./contacts.js" ;
3131
3232const DEG = Math . PI / 180 ;
3333
@@ -270,6 +270,8 @@ export function createViewer(
270270 // Finger bones the loaded document explicitly poses (make-a-fist, finger-spell,
271271 // hand-wave): the L4.1 resting-hand curl leaves these alone.
272272 let authoredFingers = new Set < string > ( ) ;
273+ // Shoulders the document poses: L4.2 arm-swing leaves these to the author.
274+ let authoredShoulders = new Set < string > ( ) ;
273275 // The last loaded document, kept so the viewer can re-solve base pose and
274276 // ground anchors when the character (with its own proportions) arrives.
275277 let lastIR : PosecodeIR | null = null ;
@@ -596,6 +598,8 @@ export function createViewer(
596598 // lower-body poses (squat, lunge, deadlift) don't balance on the toes.
597599 // Runs before the floor clamp so the leveled sole is what rests on y=0.
598600 levelPlantedFeet ( mannequin , info . groundLock ) ;
601+ // L4.2 aliveness: contralateral arm swing during locomotion (free arms only).
602+ swingArms ( mannequin , authoredShoulders , gripSidesOf ( info . grips ) ) ;
599603 // L4.1 aliveness: relax idle hands into a natural curl (grips still wrap).
600604 relaxHands ( mannequin , gripSidesOf ( info . grips ) , authoredFingers ) ;
601605 // Safety net: nothing above ever intentionally pushes part of the body
@@ -697,6 +701,8 @@ export function createViewer(
697701 groundFigureOf ( mannequin ) ;
698702 levelPlantedFeet ( mannequin , ir . phases [ 0 ] ?. groundLock ?? [ ] ) ;
699703 authoredFingers = new Set ( timeline . bonesUsed . filter ( isFingerId ) ) ;
704+ authoredShoulders = new Set ( timeline . bonesUsed . filter ( ( id ) => id . startsWith ( "shoulder_" ) ) ) ;
705+ swingArms ( mannequin , authoredShoulders , gripSidesOf ( ir . phases [ 0 ] ?. grips ?? [ ] ) ) ;
700706 relaxHands ( mannequin , gripSidesOf ( ir . phases [ 0 ] ?. grips ?? [ ] ) , authoredFingers ) ;
701707 captureGroundTargets ( ) ;
702708 baseRootPos . copy ( mannequin . root . position ) ;
0 commit comments