230 lines
6.5 KiB
C#
230 lines
6.5 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// 播放模式
|
|
/// </summary>
|
|
public WrapMode WrapMode = WrapMode.Once;
|
|
|
|
/// <summary>
|
|
/// 开始播放事件, 返回时 时间点,和触发时方向
|
|
/// </summary>
|
|
public Action<double, Direction> OnPlay;
|
|
|
|
/// <summary>
|
|
/// 暂停播放事件, 返回时 时间点,和触发时方向
|
|
/// </summary>
|
|
public Action<double, Direction> OnPause;
|
|
|
|
/// <summary>
|
|
/// 停止播放事件, 返回时 时间点,和触发时方向
|
|
/// </summary>
|
|
public Action<double, Direction> OnStop;
|
|
|
|
/// <summary>
|
|
/// 继续播放事件, 返回时 时间点,和触发时方向
|
|
/// </summary>
|
|
public Action<double, Direction> OnContinue;
|
|
|
|
/// <summary>
|
|
/// Timeline长度
|
|
/// </summary>
|
|
public double Duration { get; private set; } = -1f;
|
|
|
|
/// <summary>
|
|
/// 当前播放状态(如果用不到可是删除,现在这个字段只是一个状态的记录)
|
|
/// </summary>
|
|
public Status CurrentPlayStatus { get; private set; } = Status.NULL;
|
|
|
|
/// <summary>
|
|
/// 当前播放方向(如果用不到可是删除,现在这个字段只是一个状态的记录)
|
|
/// </summary>
|
|
public Direction CurrentPlayDirection { get; private set; } = Direction.NULL;
|
|
|
|
/// <summary>
|
|
/// 当前播放进度
|
|
/// </summary>
|
|
public double CurrentTime { get; private set; } = 0d;
|
|
|
|
private Tweener m_timeTween;
|
|
|
|
private void Awake()
|
|
{
|
|
m_playableDirector = GetComponent<PlayableDirector>();
|
|
m_playableDirector.playOnAwake = false;
|
|
Duration = m_playableDirector.duration;
|
|
CurrentPlayStatus = Status.STOPPED;
|
|
}
|
|
public void SetDuration()
|
|
{
|
|
Duration = m_playableDirector.duration;
|
|
}
|
|
/// <summary>
|
|
/// 继续播放
|
|
/// </summary>
|
|
public void Continue()
|
|
{
|
|
OnContinue?.Invoke(CurrentTime, CurrentPlayDirection);
|
|
CurrentPlayStatus = Status.PLAYING;
|
|
CurrentPlayDirection = Direction.FORWARD;
|
|
m_timeTween.Kill();
|
|
RatioExecute(Duration);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从暂停时间点正向播放到指定时间点, 应用在倒播中途暂停后切换为正播
|
|
/// </summary>
|
|
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(); });
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从暂停时间点反向播放到指定时间点, 应用在正播中途暂停后切换为倒播
|
|
/// </summary>
|
|
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(); });
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从开始播放
|
|
/// </summary>
|
|
public void PlayForward()
|
|
{
|
|
OnPlay?.Invoke(CurrentTime, CurrentPlayDirection);
|
|
|
|
m_timeTween.Kill();
|
|
CurrentTime = 0d;
|
|
RatioExecute(Duration);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从结尾倒放
|
|
/// </summary>
|
|
public void PlayBackward()
|
|
{
|
|
OnPlay?.Invoke(CurrentTime, CurrentPlayDirection);
|
|
|
|
m_timeTween.Kill();
|
|
CurrentTime = Duration;
|
|
RatioExecute(0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 暂停播放
|
|
/// </summary>
|
|
public void Pause()
|
|
{
|
|
OnPause?.Invoke(CurrentTime, CurrentPlayDirection);
|
|
|
|
m_timeTween.Pause();
|
|
|
|
}
|
|
/// <summary>
|
|
/// 暂停在某个时间点
|
|
/// </summary>
|
|
public void StopInTime(double time)
|
|
{
|
|
m_timeTween.Kill();
|
|
CurrentTime = time;
|
|
m_playableDirector.time = CurrentTime;
|
|
m_playableDirector.Evaluate();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止播放
|
|
/// </summary>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 针对Double的Clamp
|
|
/// </summary>
|
|
public static double Clamp(double value, double min, double max)
|
|
{
|
|
if (value < min)
|
|
value = min;
|
|
else if (value > max)
|
|
value = max;
|
|
return value;
|
|
}
|
|
}
|
|
} |