'use strict';

/**
 * @file TimelineEditor.ts
 * @description Timeline System for Cutscenes, Cinematics, and Sequencing
 * PRO-1.4: Professional Editor Features
 *
 * Features:
 * - Multi-track timeline
 * - Track types: animation, audio, event, property, activation
 * - Keyframe animation with curves
 * - Clips with blending
 * - Markers and events
 * - Playback control
 * - Recording mode
 * - Debugger integration
 */
// ============================================================
// Easing Implementation
// ============================================================
const easingFunctions = {
    linear: (t) => t,
    easeIn: (t) => t * t,
    easeOut: (t) => t * (2 - t),
    easeInOut: (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),
    easeInQuad: (t) => t * t,
    easeOutQuad: (t) => t * (2 - t),
    easeInOutQuad: (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),
    easeInCubic: (t) => t * t * t,
    easeOutCubic: (t) => --t * t * t + 1,
    easeInOutCubic: (t) => (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1),
    easeInQuart: (t) => t * t * t * t,
    easeOutQuart: (t) => 1 - --t * t * t * t,
    easeInOutQuart: (t) => (t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t),
    easeInQuint: (t) => t * t * t * t * t,
    easeOutQuint: (t) => 1 + --t * t * t * t * t,
    easeInOutQuint: (t) => (t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t),
    easeInSine: (t) => 1 - Math.cos((t * Math.PI) / 2),
    easeOutSine: (t) => Math.sin((t * Math.PI) / 2),
    easeInOutSine: (t) => -(Math.cos(Math.PI * t) - 1) / 2,
    easeInExpo: (t) => (t === 0 ? 0 : Math.pow(2, 10 * t - 10)),
    easeOutExpo: (t) => (t === 1 ? 1 : 1 - Math.pow(2, -10 * t)),
    easeInOutExpo: (t) => {
        if (t === 0)
            return 0;
        if (t === 1)
            return 1;
        if (t < 0.5)
            return Math.pow(2, 20 * t - 10) / 2;
        return (2 - Math.pow(2, -20 * t + 10)) / 2;
    },
    easeInCirc: (t) => 1 - Math.sqrt(1 - t * t),
    easeOutCirc: (t) => Math.sqrt(1 - --t * t),
    easeInOutCirc: (t) => t < 0.5 ? (1 - Math.sqrt(1 - 4 * t * t)) / 2 : (Math.sqrt(1 - Math.pow(-2 * t + 2, 2)) + 1) / 2,
    easeInBack: (t) => {
        const c1 = 1.70158;
        const c3 = c1 + 1;
        return c3 * t * t * t - c1 * t * t;
    },
    easeOutBack: (t) => {
        const c1 = 1.70158;
        const c3 = c1 + 1;
        return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
    },
    easeInOutBack: (t) => {
        const c1 = 1.70158;
        const c2 = c1 * 1.525;
        return t < 0.5
            ? (Math.pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2)) / 2
            : (Math.pow(2 * t - 2, 2) * ((c2 + 1) * (t * 2 - 2) + c2) + 2) / 2;
    },
    easeInElastic: (t) => {
        if (t === 0)
            return 0;
        if (t === 1)
            return 1;
        const c4 = (2 * Math.PI) / 3;
        return -Math.pow(2, 10 * t - 10) * Math.sin((t * 10 - 10.75) * c4);
    },
    easeOutElastic: (t) => {
        if (t === 0)
            return 0;
        if (t === 1)
            return 1;
        const c4 = (2 * Math.PI) / 3;
        return Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
    },
    easeInOutElastic: (t) => {
        if (t === 0)
            return 0;
        if (t === 1)
            return 1;
        const c5 = (2 * Math.PI) / 4.5;
        return t < 0.5
            ? -(Math.pow(2, 20 * t - 10) * Math.sin((20 * t - 11.125) * c5)) / 2
            : (Math.pow(2, -20 * t + 10) * Math.sin((20 * t - 11.125) * c5)) / 2 + 1;
    },
    easeInBounce: (t) => 1 - easingFunctions.easeOutBounce(1 - t),
    easeOutBounce: (t) => {
        const n1 = 7.5625;
        const d1 = 2.75;
        if (t < 1 / d1) {
            return n1 * t * t;
        }
        else if (t < 2 / d1) {
            return n1 * (t -= 1.5 / d1) * t + 0.75;
        }
        else if (t < 2.5 / d1) {
            return n1 * (t -= 2.25 / d1) * t + 0.9375;
        }
        else {
            return n1 * (t -= 2.625 / d1) * t + 0.984375;
        }
    },
    easeInOutBounce: (t) => t < 0.5
        ? (1 - easingFunctions.easeOutBounce(1 - 2 * t)) / 2
        : (1 + easingFunctions.easeOutBounce(2 * t - 1)) / 2,
};
function applyEasing(t, easing = 'linear') {
    return easingFunctions[easing](t);
}
// ============================================================
// Curve Evaluation
// ============================================================
function evaluateCurve(curve, time) {
    const keyframes = curve.keyframes;
    if (keyframes.length === 0)
        return 0;
    if (keyframes.length === 1)
        return keyframes[0].value;
    // Handle pre/post infinity
    const firstKey = keyframes[0];
    const lastKey = keyframes[keyframes.length - 1];
    if (time <= firstKey.time) {
        return firstKey.value;
    }
    if (time >= lastKey.time) {
        return lastKey.value;
    }
    // Find surrounding keyframes
    let prevKey = firstKey;
    let nextKey = lastKey;
    for (let i = 0; i < keyframes.length - 1; i++) {
        if (time >= keyframes[i].time && time <= keyframes[i + 1].time) {
            prevKey = keyframes[i];
            nextKey = keyframes[i + 1];
            break;
        }
    }
    // Calculate local t
    const duration = nextKey.time - prevKey.time;
    const localT = duration > 0 ? (time - prevKey.time) / duration : 0;
    // Apply easing
    const easedT = applyEasing(localT, prevKey.easing || 'linear');
    // Interpolate
    if (prevKey.tangentMode === 'constant') {
        return prevKey.value;
    }
    // Bezier interpolation if tangents are specified
    if (prevKey.outTangent && nextKey.inTangent) {
        return bezierInterpolate(prevKey.value, prevKey.value + prevKey.outTangent.y * duration, nextKey.value + nextKey.inTangent.y * duration, nextKey.value, easedT);
    }
    // Linear interpolation
    return prevKey.value + (nextKey.value - prevKey.value) * easedT;
}
function bezierInterpolate(p0, p1, p2, p3, t) {
    const mt = 1 - t;
    return mt * mt * mt * p0 + 3 * mt * mt * t * p1 + 3 * mt * t * t * p2 + t * t * t * p3;
}
// ============================================================
// Timeline Player
// ============================================================
class TimelinePlayer {
    constructor(definition) {
        this.state = 'stopped';
        this.currentTime = 0;
        this.speed = 1;
        this.direction = 1; // 1 = forward, -1 = backward
        /** Active clips per track */
        this.activeClips = new Map();
        /** Previous time for detecting clip transitions */
        this.previousTime = 0;
        /** Event listeners */
        this.listeners = new Map();
        /** Property bindings */
        this.propertyBindings = new Map();
        this.audioNodes = new Map();
        /** Debug mode */
        this.debugMode = false;
        this.history = [];
        this.definition = definition;
    }
    // ─── Playback Control ────────────────────────────
    play() {
        if (this.state === 'playing')
            return;
        this.state = 'playing';
        this.emit('play');
    }
    pause() {
        if (this.state !== 'playing')
            return;
        this.state = 'paused';
        this.emit('pause');
    }
    stop() {
        this.state = 'stopped';
        this.currentTime = 0;
        this.previousTime = 0;
        this.activeClips.clear();
        this.stopAllAudio();
        this.emit('stop');
    }
    seek(time) {
        this.previousTime = this.currentTime;
        this.currentTime = Math.max(0, Math.min(time, this.definition.duration));
        this.emit('seek', { time: this.currentTime });
    }
    seekToMarker(markerName) {
        const marker = this.definition.markers.find((m) => m.name === markerName);
        if (marker) {
            this.seek(marker.time);
            return true;
        }
        return false;
    }
    setSpeed(speed) {
        this.speed = speed;
        this.direction = speed >= 0 ? 1 : -1;
    }
    getSpeed() {
        return this.speed;
    }
    // ─── Update ──────────────────────────────────────
    update(dt) {
        if (this.state !== 'playing')
            return;
        this.previousTime = this.currentTime;
        this.currentTime += dt * this.speed;
        // Handle wrap modes
        if (this.currentTime >= this.definition.duration) {
            switch (this.definition.wrapMode) {
                case 'once':
                    this.currentTime = this.definition.duration;
                    this.state = 'stopped';
                    this.emit('complete');
                    break;
                case 'loop':
                    this.currentTime = this.currentTime % this.definition.duration;
                    this.emit('loop');
                    this.activeClips.clear();
                    break;
                case 'pingPong':
                    this.direction *= -1;
                    this.currentTime =
                        this.definition.duration - (this.currentTime - this.definition.duration);
                    this.emit('loop');
                    break;
                case 'clampForever':
                    this.currentTime = this.definition.duration;
                    break;
            }
        }
        else if (this.currentTime < 0) {
            switch (this.definition.wrapMode) {
                case 'once':
                    this.currentTime = 0;
                    this.state = 'stopped';
                    this.emit('complete');
                    break;
                case 'loop':
                    this.currentTime = this.definition.duration + this.currentTime;
                    this.emit('loop');
                    this.activeClips.clear();
                    break;
                case 'pingPong':
                    this.direction *= -1;
                    this.currentTime = -this.currentTime;
                    this.emit('loop');
                    break;
                case 'clampForever':
                    this.currentTime = 0;
                    break;
            }
        }
        // Process tracks
        this.processTracks();
        // Check markers
        this.processMarkers();
    }
    processTracks() {
        for (const track of this.definition.tracks) {
            if (track.muted)
                continue;
            this.processTrack(track);
        }
    }
    processTrack(track) {
        let activeSet = this.activeClips.get(track.id);
        if (!activeSet) {
            activeSet = new Set();
            this.activeClips.set(track.id, activeSet);
        }
        for (const clip of track.clips) {
            if (clip.muted)
                continue;
            const clipEnd = clip.startTime + clip.duration;
            const wasActive = activeSet.has(clip.id);
            const isActive = this.currentTime >= clip.startTime && this.currentTime < clipEnd;
            // Clip enter
            if (isActive && !wasActive) {
                activeSet.add(clip.id);
                this.onClipEnter(track, clip);
            }
            // Clip exit
            if (!isActive && wasActive) {
                activeSet.delete(clip.id);
                this.onClipExit(track, clip);
            }
            // Clip update
            if (isActive) {
                const localTime = (this.currentTime - clip.startTime) * (clip.speed || 1);
                this.updateClip(track, clip, localTime);
            }
        }
    }
    onClipEnter(track, clip) {
        this.emit('clip-enter', { track, clip });
        // Handle audio clips
        if (clip.type === 'audio') {
            this.playAudioClip(clip);
        }
    }
    onClipExit(track, clip) {
        this.emit('clip-exit', { track, clip });
        // Handle event clips with on-exit fire mode
        if (clip.type === 'event' && clip.fireMode === 'on-exit') {
            this.fireEventClip(clip);
        }
        // Stop audio
        if (clip.type === 'audio') {
            this.stopAudioClip(clip.id);
        }
    }
    updateClip(track, clip, localTime) {
        switch (clip.type) {
            case 'animation':
                this.updateAnimationClip(clip, localTime);
                break;
            case 'property':
                this.updatePropertyClip(clip, localTime);
                break;
            case 'event':
                this.updateEventClip(clip, localTime);
                break;
            case 'transform':
                this.updateTransformClip(clip, localTime);
                break;
            case 'camera':
                this.updateCameraClip(clip, localTime);
                break;
            case 'audio':
                this.updateAudioClip(clip, localTime);
                break;
        }
    }
    updateAnimationClip(clip, localTime) {
        for (const curve of clip.curves) {
            const value = evaluateCurve(curve, localTime);
            this.applyProperty(curve.property, value);
        }
    }
    updatePropertyClip(clip, localTime) {
        for (const curve of clip.curves) {
            const value = evaluateCurve(curve, localTime);
            this.applyProperty(clip.propertyPath + '.' + curve.property, value);
        }
    }
    updateEventClip(clip, localTime) {
        if (clip.fireMode === 'every-frame') {
            this.fireEventClip(clip);
        }
        else if (clip.fireMode === 'once' && localTime < 0.016) {
            // Fire once at the start (within one frame)
            this.fireEventClip(clip);
        }
    }
    updateTransformClip(clip, localTime) {
        if (clip.positionCurve) {
            const x = evaluateCurve(clip.positionCurve.x, localTime);
            const y = evaluateCurve(clip.positionCurve.y, localTime);
            const z = evaluateCurve(clip.positionCurve.z, localTime);
            this.applyProperty(`${clip.trackId}.position`, { x, y, z });
        }
        if (clip.rotationCurve) {
            const x = evaluateCurve(clip.rotationCurve.x, localTime);
            const y = evaluateCurve(clip.rotationCurve.y, localTime);
            const z = evaluateCurve(clip.rotationCurve.z, localTime);
            this.applyProperty(`${clip.trackId}.rotation`, { x, y, z });
        }
        if (clip.scaleCurve) {
            const x = evaluateCurve(clip.scaleCurve.x, localTime);
            const y = evaluateCurve(clip.scaleCurve.y, localTime);
            const z = evaluateCurve(clip.scaleCurve.z, localTime);
            this.applyProperty(`${clip.trackId}.scale`, { x, y, z });
        }
    }
    updateCameraClip(clip, localTime) {
        if (clip.fieldOfView) {
            const fov = evaluateCurve(clip.fieldOfView, localTime);
            this.applyProperty(`${clip.trackId}.fov`, fov);
        }
        if (clip.dof) {
            const focusDistance = evaluateCurve(clip.dof.focusDistance, localTime);
            const aperture = evaluateCurve(clip.dof.aperture, localTime);
            const focalLength = evaluateCurve(clip.dof.focalLength, localTime);
            this.applyProperty(`${clip.trackId}.dof`, { focusDistance, aperture, focalLength });
        }
        if (clip.shake) {
            const amplitude = evaluateCurve(clip.shake.amplitude, localTime);
            const frequency = evaluateCurve(clip.shake.frequency, localTime);
            this.applyProperty(`${clip.trackId}.shake`, { amplitude, frequency });
        }
    }
    updateAudioClip(clip, localTime) {
        if (clip.volumeCurve) {
            evaluateCurve(clip.volumeCurve, localTime);
            // Apply volume to audio node
            this.audioNodes.get(clip.id);
            // Volume adjustment would go here
        }
    }
    fireEventClip(clip) {
        this.emit('event', {
            eventName: clip.eventName,
            payload: clip.payload,
        });
    }
    // ─── Audio ───────────────────────────────────────
    playAudioClip(clip) {
        // Audio playback would be implemented with Web Audio API
        // This is a placeholder for the interface
    }
    stopAudioClip(clipId) {
        const node = this.audioNodes.get(clipId);
        if (node) {
            node.stop();
            this.audioNodes.delete(clipId);
        }
    }
    stopAllAudio() {
        for (const node of this.audioNodes.values()) {
            node.stop();
        }
        this.audioNodes.clear();
    }
    // ─── Markers ─────────────────────────────────────
    processMarkers() {
        for (const marker of this.definition.markers) {
            // Check if we crossed the marker
            const crossedForward = this.previousTime < marker.time && this.currentTime >= marker.time;
            const crossedBackward = this.previousTime > marker.time && this.currentTime <= marker.time;
            if (crossedForward || crossedBackward) {
                this.emit('marker', { marker });
                if (marker.type === 'signal' && marker.signalName) {
                    this.emit('signal', {
                        signalName: marker.signalName,
                        payload: marker.signalPayload,
                    });
                }
                if (marker.type === 'jump' && marker.jumpTarget) {
                    const targetMarker = this.definition.markers.find((m) => m.name === marker.jumpTarget);
                    if (targetMarker) {
                        // Check condition if present
                        if (!marker.jumpCondition || this.evaluateCondition(marker.jumpCondition)) {
                            this.seek(targetMarker.time);
                        }
                    }
                }
            }
        }
    }
    evaluateCondition(condition) {
        // Simple condition evaluation - could be extended
        return true;
    }
    // ─── Property Binding ────────────────────────────
    bindProperty(path, setter) {
        this.propertyBindings.set(path, setter);
    }
    unbindProperty(path) {
        this.propertyBindings.delete(path);
    }
    applyProperty(path, value) {
        const binding = this.propertyBindings.get(path);
        if (binding) {
            binding(value);
        }
    }
    // ─── Events ──────────────────────────────────────
    on(event, listener) {
        let listeners = this.listeners.get(event);
        if (!listeners) {
            listeners = [];
            this.listeners.set(event, listeners);
        }
        listeners.push(listener);
    }
    off(event, listener) {
        const listeners = this.listeners.get(event);
        if (listeners) {
            const idx = listeners.indexOf(listener);
            if (idx >= 0) {
                listeners.splice(idx, 1);
            }
        }
    }
    emit(type, data) {
        const event = {
            type,
            time: this.currentTime,
            data,
        };
        if (this.debugMode) {
            this.history.push(event);
            if (this.history.length > 100) {
                this.history.shift();
            }
        }
        const listeners = this.listeners.get(type);
        if (listeners) {
            for (const listener of listeners) {
                listener(event);
            }
        }
    }
    // ─── State Queries ───────────────────────────────
    getState() {
        return this.state;
    }
    getCurrentTime() {
        return this.currentTime;
    }
    getDuration() {
        return this.definition.duration;
    }
    getProgress() {
        return this.definition.duration > 0 ? this.currentTime / this.definition.duration : 0;
    }
    isPlaying() {
        return this.state === 'playing';
    }
    isPaused() {
        return this.state === 'paused';
    }
    isStopped() {
        return this.state === 'stopped';
    }
    getDefinition() {
        return this.definition;
    }
    // ─── Debugging ───────────────────────────────────
    getHistory() {
        return [...this.history];
    }
    clearHistory() {
        this.history = [];
    }
    getDebugInfo() {
        let activeClipCount = 0;
        for (const set of this.activeClips.values()) {
            activeClipCount += set.size;
        }
        return {
            state: this.state,
            time: this.currentTime,
            duration: this.definition.duration,
            progress: this.getProgress(),
            speed: this.speed,
            activeClipCount,
        };
    }
}
class TimelineRecorder {
    constructor(player, options) {
        this.recording = false;
        this.recordedKeyframes = new Map();
        this.lastSampleTime = 0;
        this.player = player;
        this.options = options;
    }
    startRecording() {
        this.recording = true;
        this.recordedKeyframes.clear();
        this.lastSampleTime = 0;
    }
    stopRecording() {
        this.recording = false;
        return new Map(this.recordedKeyframes);
    }
    isRecording() {
        return this.recording;
    }
    recordValue(property, value) {
        if (!this.recording)
            return;
        const time = this.player.getCurrentTime();
        const sampleRate = this.options.sampleRate || 30;
        const minInterval = 1 / sampleRate;
        // Check if enough time has passed
        if (time - this.lastSampleTime < minInterval)
            return;
        let keyframes = this.recordedKeyframes.get(property);
        if (!keyframes) {
            keyframes = [];
            this.recordedKeyframes.set(property, keyframes);
        }
        keyframes.push({
            id: `key_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
            time,
            value,
            easing: 'linear',
        });
        this.lastSampleTime = time;
    }
    getRecordedKeyframes() {
        return new Map(this.recordedKeyframes);
    }
}
// ============================================================
// Factory Functions
// ============================================================
function createTimelineDefinition(name, duration = 10) {
    return {
        id: `timeline_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name,
        description: '',
        duration,
        fps: 60,
        wrapMode: 'once',
        tracks: [],
        markers: [],
    };
}
function createTimelinePlayer(definition) {
    return new TimelinePlayer(definition);
}
function createTimelineRecorder(player, options) {
    return new TimelineRecorder(player, options);
}
function createTrack(name, type) {
    const baseTrack = {
        id: `track_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name,
        type,
        muted: false,
        locked: false,
        collapsed: false,
        clips: [],
    };
    switch (type) {
        case 'animation':
            return { ...baseTrack, type: 'animation' };
        case 'audio':
            return { ...baseTrack, type: 'audio', volume: 1 };
        case 'event':
            return { ...baseTrack, type: 'event' };
        case 'property':
            return {
                ...baseTrack,
                type: 'property',
                targetEntity: '',
                propertyPath: '',
            };
        case 'activation':
            return {
                ...baseTrack,
                type: 'activation',
                targetEntity: '',
            };
        case 'transform':
            return {
                ...baseTrack,
                type: 'transform',
                targetEntity: '',
                space: 'local',
            };
        case 'camera':
            return {
                ...baseTrack,
                type: 'camera',
                cameraEntity: '',
            };
        case 'group':
            return { ...baseTrack, type: 'group', children: [] };
        default:
            return baseTrack;
    }
}
function createAnimationClip(trackId, startTime, duration) {
    return {
        id: `clip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name: 'Animation Clip',
        type: 'animation',
        trackId,
        startTime,
        duration,
        curves: [],
    };
}
function createAudioClip(trackId, startTime, duration, audioSource) {
    return {
        id: `clip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name: 'Audio Clip',
        type: 'audio',
        trackId,
        startTime,
        duration,
        audioSource,
        volume: 1,
    };
}
function createEventClip(trackId, time, eventName) {
    return {
        id: `clip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name: eventName,
        type: 'event',
        trackId,
        startTime: time,
        duration: 0.01, // Instant
        eventName,
        fireMode: 'once',
    };
}
function createPropertyClip(trackId, startTime, duration, propertyPath) {
    return {
        id: `clip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name: 'Property Clip',
        type: 'property',
        trackId,
        startTime,
        duration,
        propertyPath,
        curves: [],
    };
}
function createTransformClip(trackId, startTime, duration) {
    return {
        id: `clip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name: 'Transform Clip',
        type: 'transform',
        trackId,
        startTime,
        duration,
    };
}
function createCameraClip(trackId, startTime, duration) {
    return {
        id: `clip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name: 'Camera Clip',
        type: 'camera',
        trackId,
        startTime,
        duration,
    };
}
function createAnimationCurve(property) {
    return {
        id: `curve_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        property,
        keyframes: [],
    };
}
function createKeyframe(time, value, easing = 'linear') {
    return {
        id: `key_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        time,
        value,
        easing,
    };
}
function createMarker(name, time) {
    return {
        id: `marker_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name,
        time,
        type: 'marker',
    };
}
function createSignalMarker(name, time, signalName, payload) {
    return {
        id: `marker_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        name,
        time,
        type: 'signal',
        signalName,
        signalPayload: payload,
    };
}

exports.TimelinePlayer = TimelinePlayer;
exports.TimelineRecorder = TimelineRecorder;
exports.applyEasing = applyEasing;
exports.createAnimationClip = createAnimationClip;
exports.createAnimationCurve = createAnimationCurve;
exports.createAudioClip = createAudioClip;
exports.createCameraClip = createCameraClip;
exports.createEventClip = createEventClip;
exports.createKeyframe = createKeyframe;
exports.createMarker = createMarker;
exports.createPropertyClip = createPropertyClip;
exports.createSignalMarker = createSignalMarker;
exports.createTimelineDefinition = createTimelineDefinition;
exports.createTimelinePlayer = createTimelinePlayer;
exports.createTimelineRecorder = createTimelineRecorder;
exports.createTrack = createTrack;
exports.createTransformClip = createTransformClip;
exports.evaluateCurve = evaluateCurve;
//# sourceMappingURL=TimelineEditor.js.map
