public static Validate()

in packages/sdk/src/animation/animationData.ts [181:228]


	public static Validate(data: AnimationDataLike) {
		const errors: string[] = [];

		// make sure data has at least one track
		if (data.tracks.length === 0) {
			errors.push("Data must contain at least one track");
		}

		const maxTrackLen = data.tracks.reduce(
			(max, t) => Math.max(max, t.keyframes[t.keyframes.length - 1]?.time),
			-Infinity);

		for (let ti = 0; ti < data.tracks.length; ti++) {
			const t = data.tracks[ti];

			// make sure keyframes are in order by time
			for (let ki = 0; ki < t.keyframes.length; ki++) {
				const k = t.keyframes[ki];

				if (ki === 0) {
					if (k.time < 0) {
						errors.push(`Track ${ti} keyframe ${ki} time cannot be less than 0`);
					}
				} else if (k.time <= t.keyframes[ki - 1].time) {
					errors.push(`Track ${ti} keyframe ${ki} is out of sequence`);
				}

				if (k.easing) {
					if (k.easing[0] < 0 || k.easing[0] > 1) {
						errors.push(`Track ${ti} keyframe ${ki} easing[0] must be between 0 and 1`);
					}
					if (k.easing[2] < 0 || k.easing[2] > 1) {
						errors.push(`Track ${ti} keyframe ${ki} easing[2] must be between 0 and 1`);
					}
				}

				if (k.value instanceof TargetPath && t.relative) {
					errors.push(`Relative track ${ti} cannot contain keyframe ${ki}'s realtime value`);
				}
			}

			if (t.keyframes[t.keyframes.length - 1]?.time !== maxTrackLen) {
				errors.push(`Track ${ti} is a different length from the others`);
			}
		}

		return errors.length > 0 ? errors : null;
	}