Contract 2.0.0 · package sha256
a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e· generated fromexamples/section-5/5.10-animations-and-follow.tsbyservices/onsite-scripter/scripts/build-contract-docs.mjs; edit the source, not this file.
Imports: values (has, validate, the Holo*Error classes, the pure helpers) from @holostep-configurators/runtime-client, types from @holostep-configurators/runtime-client/contract, /math and /testing names from those entries; boot from the runtime module the root's loadRuntimeAtFloor resolves to. A type your page defines is your app's: declare it there, never import it from the package.
import { mat4 } from '@holostep-configurators/runtime-client/math';
import type { Part, Pose, PoseInput, Session } from '@holostep-configurators/runtime-client/contract';
import type { Mat4 } from '@holostep-configurators/runtime-client/math';
declare const session: Session;
declare const signal: AbortSignal;
declare const pocketFollow: ReadonlyArray<{ source: string; bone: string }>;
declare const pocketId: string;
declare const frameId: string;
declare const mattressId: string;
declare const stretch: number; // the frame's stretch along its lid
declare const lidBones: readonly string[]; // 'frame', or 'framel' and 'framer' (app code)
declare const closed: ReadonlyMap<string, Pose>; // each mattress lid bone's pose, read after animations.reset
declare function lidOnFrame(closed: Pose, frameLid: Mat4, stretch: number): PoseInput;
// exact under the stretch: a lid turned inside a non-uniformly scaled frame is sheared, which no Pose holds
const worldMatrix = (part: Part): Mat4 => {
const { position, quaternion, scale } = part.parent ? part.pose : part.worldPose; // a model root's pose is its world pose
const local = mat4.compose({ position, quaternion, scale });
return part.parent ? mat4.multiply(worldMatrix(part.parent), local) : local;
};
for (const { source, bone } of pocketFollow) // from the base's attributes
session.find({ node: pocketId, name: source }).follow({ node: frameId, name: bone }, { offset: 'rest', signal });
session.onFrame((frame) => {
for (const name of lidBones) {
const frameLid = session.find({ node: frameId, name }).first(); // this frame's clip pose
const matLid = session.find({ node: mattressId, name }).first();
const rest = closed.get(name);
// a joint's local pose, from the frame's lid and the closed pose: it never compounds on this hook's write
if (frameLid && matLid && rest) frame.pose(matLid, lidOnFrame(rest, worldMatrix(frameLid), stretch));
}
}, { phase: 'late', signal });
await session.animations.play(frameId, 'open', { toggle: true });
Back to the examples · llms.txt