import { IAsset, AssetBase } from '@awayjs/core'; import { JointPose } from './JointPose'; /** * A collection of pose objects, determining the pose for an entire skeleton. * The jointPoses vector object corresponds to a skeleton's joints vector object, however, there is no * reference to a skeleton's instance, since several skeletons can be influenced by the same pose (eg: animation * clips are added to any animator with a valid skeleton) * * @see away.animators.Skeleton * @see away.animators.JointPose */ export class SkeletonPose extends AssetBase implements IAsset { public static assetType: string = '[asset SkeletonPose]'; /** * A flat list of pose objects that comprise the skeleton pose. The pose indices correspond to the target skeleton's joint indices. * * @see away.animators.Skeleton#joints */ public jointPoses: Array; /** * The total number of joint poses in the skeleton pose. */ public get numJointPoses(): number { return this.jointPoses.length; } /** * Creates a new SkeletonPose object. */ constructor() { super(); this.jointPoses = new Array(); } /** * @inheritDoc */ public get assetType(): string { return SkeletonPose.assetType; } /** * Returns the joint pose object with the given joint name, otherwise returns a null object. * * @param jointName The name of the joint object whose pose is to be found. * @return The pose object with the given joint name. */ public jointPoseFromName(jointName: string): JointPose { const jointPoseIndex: number = this.jointPoseIndexFromName(jointName); if (jointPoseIndex != -1) return this.jointPoses[jointPoseIndex]; else return null; } /** * Returns the pose index, given the joint name. -1 is returned if the joint name is not found in the pose. * * @param The name of the joint object whose pose is to be found. * @return The index of the pose object in the jointPoses Array * * @see #jointPoses */ public jointPoseIndexFromName(jointName: string): number { // this is implemented as a linear search, rather than a possibly // more optimal method (Dictionary lookup, for example) because: // a) it is assumed that it will be called once for each joint // b) it is assumed that it will be called only during load, and not during main loop // c) maintaining a dictionary (for safety) would dictate an interface to access JointPoses, // rather than direct array access. this would be sub-optimal. let jointPoseIndex: number; let jointPose: JointPose; for (var i: number; i < this.jointPoses.length; i++) { jointPose = this.jointPoses[i]; if (jointPose.name == jointName) return jointPoseIndex; jointPoseIndex++; } return -1; } /** * Creates a copy of the SkeletonPose object, with a dulpicate of its component joint poses. * * @return SkeletonPose */ public clone(): SkeletonPose { const clone: SkeletonPose = new SkeletonPose(); const numJointPoses: number = this.jointPoses.length; for (let i: number = 0; i < numJointPoses; i++) { const cloneJointPose: JointPose = new JointPose(); const thisJointPose: JointPose = this.jointPoses[i]; cloneJointPose.name = thisJointPose.name; cloneJointPose.copyFrom(thisJointPose); clone.jointPoses[i] = cloneJointPose; } return clone; } /** * @inheritDoc */ public dispose(): void { this.jointPoses.length = 0; } }