{"version":3,"file":"Timeline.mjs","sources":["../../src/animate/Timeline.ts"],"sourcesContent":["import { Tween, TweenProps, EaseMethod } from './Tween';\nimport type { AnimateDisplayObject } from './DisplayObject';\n\n/**\n * The Timeline class represents a series of tweens, tied to keyframes.\n */\nexport class Timeline extends Array<Tween>\n{\n    /**\n     * The target DisplayObject.\n     */\n    public target: AnimateDisplayObject;\n    /**\n     * Current properties in the tween, to make building the timeline more\n     * efficient.\n     */\n    private _currentProps: TweenProps;\n\n    /**\n     * Creates a new Timeline. Must be used instead of a constructor because extending the Array\n     * class is a pain: https://blog.simontest.net/extend-array-with-typescript-965cc1134b3\n     * @param target - The target for this string of tweens.\n     * @returns A new Timeline instance.\n     */\n    public static create(target: AnimateDisplayObject): Timeline\n    {\n        const out = Object.create(Timeline.prototype) as Timeline;\n\n        out.target = target;\n        out._currentProps = {};\n\n        return out;\n    }\n\n    // exists to be private to prevent usage\n    private constructor()\n    {\n        super();\n    }\n\n    /**\n     * Adds one or more tweens (or timelines) to this timeline. The tweens will be paused (to\n     * remove them from the normal ticking system and managed by this timeline. Adding a tween to\n     * multiple timelines will result in unexpected behaviour.\n     * @param tween - The tween(s) to add. Accepts multiple arguments.\n     * @return Tween The first tween that was passed in.\n     */\n    public addTween(properties: TweenProps, startFrame: number, duration: number, ease?: EaseMethod): void\n    {\n        this.extendLastFrame(startFrame - 1);\n        // figure out what the starting values for this tween should be\n        // ownership of startProps is passed to the new Tween - this object should not be reused\n        const startProps: TweenProps = Object.assign({}, this._currentProps);\n\n        for (const prop in properties)\n        {\n            const p = prop as keyof TweenProps;\n\n            // if we have not already set that property in an earlier tween, handle that property\n            if (!Object.hasOwnProperty.call(this._currentProps, prop))\n            {\n                const startValue = (startProps[p] as any) = this.getPropFromShorthand(p);\n\n                // go through previous tweens to set the value so that when the timeline loops\n                // around, the values are set properly - having each tween know what came before\n                // allows us to set to a specific frame without running through the entire timeline\n                for (let i = this.length - 1; i >= 0; --i)\n                {\n                    (this[i].startProps[p] as any) = startValue;\n                    (this[i].endProps[p] as any) = startValue;\n                }\n            }\n        }\n        // create the new Tween and add it to the list\n        const tween = new Tween(this.target, startProps, properties, startFrame, duration, ease);\n\n        // if we have this frame already, replace it\n        if (startFrame === this[this.length - 1].startFrame)\n        {\n            this[this.length - 1] = tween;\n        }\n        // otherwise add it to the list\n        else\n        {\n            this.push(tween);\n        }\n        // update starting values for the next tween - if tweened values included 'p', then Tween\n        // parsed that to add additional data that is required\n        Object.assign(this._currentProps, tween.endProps);\n    }\n\n    /**\n     * Add a single keyframe that doesn't tween.\n     * Note that this has some capability to insert keyframes into the middle of a timeline, in order to\n     * handle how masks are published, it should only be relied upon to add keyframes to the end of a timeline.\n     * @param properties - The properties to set.\n     * @param startFrame - The starting frame index.\n     * @param duration - The number of frames to hold beyond startFrame (0 is single frame)\n     */\n    public addKeyframe(properties: TweenProps, startFrame: number, duration = 0): void\n    {\n        // see if we need to go back in and insert properties\n        if (this.length && this[this.length - 1].startFrame >= startFrame)\n        {\n            for (let i = this.length - 1; i >= 0; --i)\n            {\n                const prev = this[i];\n\n                // insert into an existing frame that shares the same keyframe\n                if (prev.startFrame === startFrame)\n                {\n                    // update the start props\n                    Object.assign(prev.startProps, properties);\n                    // carry the new props over unless they're already overridden by end props\n                    prev.endProps = Object.assign({}, prev.startProps, prev.endProps);\n                    // go through any later keyframes to update them the same way\n                    for (let k = i + 1; k < this.length; ++k)\n                    {\n                        const next = this[k];\n\n                        next.startProps = Object.assign({}, properties, next.startProps);\n                        next.endProps = Object.assign({}, next.startProps, next.endProps);\n                    }\n                    break;\n                }\n                // insert into the middle of an extended keyframe (but *not* one that tweens)\n                else if (prev.startFrame < startFrame && prev.endFrame > startFrame && prev.isTweenlessFrame)\n                {\n                    prev.endFrame = startFrame - 1;\n                    const startProps = Object.assign({}, prev.endProps, properties);\n                    // create the new Tween and add it to the list\n                    const tween = new Tween(this.target, startProps, null, startFrame, duration);\n\n                    this.splice(i, 0, tween);\n                    // go through any later keyframes to update them with our inserted props\n                    for (let k = i + 1; k < this.length; ++k)\n                    {\n                        const next = this[k];\n\n                        next.startProps = Object.assign({}, properties, next.startProps);\n                        next.endProps = Object.assign({}, next.startProps, next.endProps);\n                    }\n                    break;\n                }\n                // insert in a gap between frames (which shouldn't really happen, but just in case)\n                else if (prev.endFrame < startFrame)\n                {\n                    const startProps = Object.assign({}, prev.endProps, properties);\n                    // create the new Tween and add it to the list\n                    const tween = new Tween(this.target, startProps, null, startFrame, duration);\n\n                    this.splice(i, 0, tween);\n\n                    // go through any later keyframes to update them with our inserted props\n                    for (let k = i + 1; k < this.length; ++k)\n                    {\n                        const next = this[k];\n\n                        next.startProps = Object.assign({}, properties, next.startProps);\n                        next.endProps = Object.assign({}, next.startProps, next.endProps);\n                    }\n                    break;\n                }\n            }\n            // save in current props, but don't take priority over existing values since we went back in time\n            Object.assign(this._currentProps, properties, this._currentProps);\n        }\n        else\n        {\n            this.extendLastFrame(startFrame - 1);\n            const startProps = Object.assign({}, this._currentProps, properties);\n            // create the new Tween and add it to the list\n            const tween = new Tween(this.target, startProps, null, startFrame, duration);\n\n            this.push(tween);\n            Object.assign(this._currentProps, tween.endProps);\n        }\n    }\n\n    /**\n     * Extend the last frame of the tween.\n     * @param endFrame - The ending frame index.\n     */\n    public extendLastFrame(endFrame: number): void\n    {\n        if (this.length)\n        {\n            const prevTween = this[this.length - 1];\n\n            if (prevTween.endFrame < endFrame)\n            {\n                if (prevTween.isTweenlessFrame)\n                {\n                    prevTween.endFrame = endFrame;\n                    prevTween.duration = endFrame - prevTween.startFrame;\n                }\n                else\n                {\n                    this.addKeyframe(\n                        this._currentProps,\n                        prevTween.endFrame + 1,\n                        endFrame - (prevTween.endFrame + 1),\n                    );\n                }\n            }\n        }\n    }\n\n    /**\n     * Get the value for a property\n     * @param prop\n     */\n    private getPropFromShorthand<P extends keyof TweenProps>(prop: P): TweenProps[P]\n    {\n        const target = this.target;\n\n        switch (prop)\n        {\n            case 'x':\n                return target.position.x as any;\n            case 'y':\n                return target.position.y as any;\n            case 'sx':\n                return target.scale.x as any;\n            case 'sy':\n                return target.scale.y as any;\n            case 'kx':\n                return target.skew.x as any;\n            case 'ky':\n                return target.skew.y as any;\n            case 'r':\n                return target.rotation as any;\n            case 'a':\n                return target.alpha as any;\n            case 'v':\n                return target.visible as any;\n            case 'm':\n                return target.mask as any;\n                // case 't':\n                //   return target.tint;\n                // not sure if we'll actually handle graphics this way?\n                // g: return null;\n        }\n\n        return null;\n    }\n\n    public destroy(): void\n    {\n        this._currentProps = null;\n        this.length = 0;\n    }\n}\n"],"names":[],"mappings":"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"}