using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
/*******************************************************************************
*Create By CG
*Function Timeline正播倒播辅助类
*******************************************************************************/
namespace CG.UTility
{
[RequireComponent(typeof(PlayableDirector))]
public class TimelineDirectorCtrl : MonoBehaviour
{
#region ENUM
public enum Status
{
NULL,
PLAYING,
PAUSED,
STOPPED,
}
public enum Direction
{
NULL,
FORWARD,
BACKWARD
}
#endregion
[SerializeField]
private PlayableDirector m_playableDirector;
[Range(0f, 1f)]
public float PlaySpeed = 1f;
///
/// 播放模式
///
public WrapMode WrapMode = WrapMode.Once;
///
/// 开始播放事件, 返回时 时间点,和触发时方向
///
public Action OnPlay;
///
/// 暂停播放事件, 返回时 时间点,和触发时方向
///
public Action OnPause;
///
/// 停止播放事件, 返回时 时间点,和触发时方向
///
public Action OnStop;
///
/// 继续播放事件, 返回时 时间点,和触发时方向
///
public Action OnContinue;
///
/// Timeline长度
///
public double Duration { get; private set; } = -1f;
///
/// 当前播放状态(如果用不到可是删除,现在这个字段只是一个状态的记录)
///
public Status CurrentPlayStatus { get; private set; } = Status.NULL;
///
/// 当前播放方向(如果用不到可是删除,现在这个字段只是一个状态的记录)
///
public Direction CurrentPlayDirection { get; private set; } = Direction.NULL;
///
/// 当前播放进度
///
public double CurrentTime { get; private set; } = 0d;
private Tweener m_timeTween;
private void Awake()
{
m_playableDirector = GetComponent();
m_playableDirector.playOnAwake = false;
Duration = m_playableDirector.duration;
CurrentPlayStatus = Status.STOPPED;
}
public void SetDuration()
{
Duration = m_playableDirector.duration;
}
///
/// 继续播放
///
public void Continue()
{
OnContinue?.Invoke(CurrentTime, CurrentPlayDirection);
CurrentPlayStatus = Status.PLAYING;
CurrentPlayDirection = Direction.FORWARD;
m_timeTween.Kill();
RatioExecute(Duration);
}
///
/// 从暂停时间点正向播放到指定时间点, 应用在倒播中途暂停后切换为正播
///
public void ContinuePlayForwardByPausePoint(double time,Action finishCall)
{
OnContinue?.Invoke(CurrentTime, CurrentPlayDirection);
CurrentPlayStatus = Status.PLAYING;
CurrentPlayDirection = Direction.FORWARD;
m_timeTween.Kill();
RatioExecute(time);
m_timeTween.OnComplete(()=> { finishCall?.Invoke(); });
}
///
/// 从暂停时间点反向播放到指定时间点, 应用在正播中途暂停后切换为倒播
///
public void ContinuePlayBackwardByPausePoint(double time, Action finishCall)
{
OnContinue?.Invoke(CurrentTime, CurrentPlayDirection);
CurrentPlayStatus = Status.PLAYING;
CurrentPlayDirection = Direction.BACKWARD;
m_timeTween.Kill();
RatioExecute(time);
m_timeTween.OnComplete(() => { finishCall?.Invoke(); });
}
///
/// 从开始播放
///
public void PlayForward()
{
OnPlay?.Invoke(CurrentTime, CurrentPlayDirection);
m_timeTween.Kill();
CurrentTime = 0d;
RatioExecute(Duration);
}
///
/// 从结尾倒放
///
public void PlayBackward()
{
OnPlay?.Invoke(CurrentTime, CurrentPlayDirection);
m_timeTween.Kill();
CurrentTime = Duration;
RatioExecute(0);
}
///
/// 暂停播放
///
public void Pause()
{
OnPause?.Invoke(CurrentTime, CurrentPlayDirection);
m_timeTween.Pause();
}
///
/// 暂停在某个时间点
///
public void StopInTime(double time)
{
m_timeTween.Kill();
CurrentTime = time;
m_playableDirector.time = CurrentTime;
m_playableDirector.Evaluate();
}
///
/// 停止播放
///
public void Stop()
{
OnStop?.Invoke(CurrentTime, CurrentPlayDirection);
m_timeTween.Kill();
CurrentTime = 0d;
if (m_playableDirector)
{
m_playableDirector.time = CurrentTime;
m_playableDirector.Evaluate();
}
DOTween.KillAll();
}
private void RatioExecute(double target)
{
// 使用DoTween最当前时间进行线性过渡
m_timeTween = DOTween.To(() => CurrentTime, x => CurrentTime = x, target, PlaySpeed).SetSpeedBased().SetEase(Ease.Linear);
// 做出限制避免bug
CurrentTime = Clamp(CurrentTime, 0d, Duration);
m_timeTween.OnUpdate(() =>
{
// 直接取样
if (m_playableDirector != null)
{
m_playableDirector.time = CurrentTime;
m_playableDirector.Evaluate();
}
});
m_timeTween.Play();
}
///
/// 针对Double的Clamp
///
public static double Clamp(double value, double min, double max)
{
if (value < min)
value = min;
else if (value > max)
value = max;
return value;
}
}
}