UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

153 lines (128 loc) 3.52 kB
import { assert } from "../../../core/assert.js"; import { computeHashFloat } from "../../../core/primitives/numbers/computeHashFloat.js"; /** * Single keyframe of {@link AnimationCurve}. * Note that {@link AnimationCurve} relies on {@link Keyframe}s to be static, so treat them as immutable. * Do not change keyframe values unless you understand the implications of doing so. * * @author Alex Goldring * @copyright Company Named Limited (c) 2025 */ export class Keyframe { /** * * @type {number} */ value = 0; /** * Timestamp/position for the value * @type {number} */ time = 0; /** * Incoming tangent, affects the slope of the curve from previous key * @type {number} */ inTangent = 0; /** * Outgoing tangent, affect the slope of the curve from this key to the next key * @type {number} */ outTangent = 0; /** * * @param {number} time * @param {number} value * @param {number} inTangent * @param {number} outTangent * @return {Keyframe} */ static from(time, value, inTangent = 0, outTangent = 0) { const r = new Keyframe(); r.set(time, value, inTangent, outTangent); return r; } /** * * @param {number} time * @param {number} value * @param {number} inTangent * @param {number} outTangent */ set(time, value, inTangent, outTangent) { assert.isNumber(time, 'time'); assert.notNaN(time, 'time'); assert.isNumber(value, 'value'); assert.notNaN(value, 'value'); assert.isNumber(inTangent, 'inTangent'); assert.notNaN(inTangent, 'inTangent'); assert.isFinite(inTangent, 'inTangent'); assert.isNumber(outTangent, 'outTangent'); assert.notNaN(outTangent, 'outTangent'); assert.isFinite(outTangent, 'outTangent'); this.time = time; this.value = value; this.inTangent = inTangent; this.outTangent = outTangent; } /** * * @param {Keyframe} other */ copy(other) { this.time = other.time; this.value = other.value; this.inTangent = other.inTangent; this.outTangent = other.outTangent; } /** * * @return {Keyframe} */ clone() { const r = new Keyframe(); r.copy(this); return r; } /** * * @param {Keyframe} other * @returns {boolean} */ equals(other) { return this.time === other.time && this.value === other.value && this.inTangent === other.inTangent && this.outTangent === other.outTangent; } /** * * @return {number} */ hash() { return computeHashFloat(this.time) ^ (computeHashFloat(this.value) * 31); } toJSON() { return { value: this.value, time: this.time, inTangent: this.inTangent, outTangent: this.outTangent } }; fromJSON({ value, time, inTangent, outTangent }) { this.set(time, value, inTangent, outTangent); } } /** * Useful for type checks * @readonly * @type {boolean} */ Keyframe.prototype.isKeyframe = true;