256 lines
7.2 KiB
C#
256 lines
7.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Playables;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace BF
|
|
{
|
|
public class TimeLineItem
|
|
{
|
|
public struct FrameData
|
|
{
|
|
public double time;
|
|
public System.Action e;
|
|
|
|
public FrameData(double t, System.Action a)
|
|
{
|
|
time = t;
|
|
e = a;
|
|
}
|
|
}
|
|
|
|
private bool play;
|
|
private double time;
|
|
private PlayableDirector director;
|
|
private Dictionary<string, PlayableBinding> tracks;
|
|
private Dictionary<GameObject, List<Component>> componentCache;
|
|
private List<FrameData> frameDatas;
|
|
|
|
public Action onComplete;
|
|
|
|
public TimeLineItem()
|
|
{
|
|
}
|
|
|
|
public double Duration {
|
|
get { return director.duration; }
|
|
}
|
|
|
|
public TimeLineItem(PlayableDirector pd)
|
|
{
|
|
director = pd;
|
|
frameDatas = new List<FrameData>();
|
|
tracks = new Dictionary<string, PlayableBinding>();
|
|
componentCache = new Dictionary<GameObject, List<Component>>();
|
|
GetTracks();
|
|
}
|
|
|
|
private void GetTracks()
|
|
{
|
|
if (null == director.playableAsset ||
|
|
null == director.playableAsset.outputs)
|
|
return;
|
|
|
|
foreach (var at in director.playableAsset.outputs)
|
|
{
|
|
if (!tracks.ContainsKey(at.streamName))
|
|
{
|
|
tracks.Add(at.streamName, at);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckBindingType(UnityEngine.Object bindingObj, UnityEngine.Object obj)
|
|
{
|
|
if (bindingObj.GetType() == typeof(UnityEngine.Timeline.AnimationTrack))
|
|
{
|
|
if (obj is GameObject)
|
|
{
|
|
var gameObject = obj as GameObject;
|
|
if (!gameObject.HasComponent<Animator>())
|
|
{
|
|
List<Component> components;
|
|
if (componentCache.TryGetValue(gameObject, out components))
|
|
{
|
|
components.Add(gameObject.AddComponent<Animator>());
|
|
}
|
|
else
|
|
{
|
|
componentCache.Add(gameObject, new List<Component>() { gameObject.AddComponent<Animator>() });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckRemoveCacheComponents(UnityEngine.Object obj)
|
|
{
|
|
if (null != obj && obj is GameObject)
|
|
{
|
|
var gameObject = obj as GameObject;
|
|
List<Component> components;
|
|
if (componentCache.TryGetValue(gameObject, out components))
|
|
{
|
|
foreach (var component in components)
|
|
{
|
|
Object.Destroy(component);
|
|
}
|
|
}
|
|
componentCache.Remove(gameObject);
|
|
}
|
|
}
|
|
|
|
public void FrameMove(double delta)
|
|
{
|
|
if (play && time > 0)
|
|
{
|
|
time -= delta;
|
|
ExecuteEvent(Duration - time);
|
|
if (time <= 0)
|
|
{
|
|
if (null != onComplete)
|
|
onComplete();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void RegisterEvent(double time, Action e)
|
|
{
|
|
frameDatas.TryAdd(new FrameData(time, e));
|
|
frameDatas.Sort(FrameSort);
|
|
}
|
|
|
|
private int FrameSort(FrameData a, FrameData b)
|
|
{
|
|
return a.time <= b.time ? -1 : 1;
|
|
}
|
|
|
|
private void ClearEvent()
|
|
{
|
|
frameDatas.Clear();
|
|
}
|
|
|
|
private void ExecuteEvent(double time)
|
|
{
|
|
for (int i = 0; i < frameDatas.Count; i++)
|
|
{
|
|
if (time >= frameDatas[i].time)
|
|
{
|
|
var e = frameDatas[i].e;
|
|
if (null != e)
|
|
e();
|
|
|
|
frameDatas.RemoveAt(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Play()
|
|
{
|
|
play = true;
|
|
time = Duration;
|
|
director.Play();
|
|
}
|
|
|
|
public void Pause()
|
|
{
|
|
play = false;
|
|
director.Pause();
|
|
}
|
|
|
|
public void Resume()
|
|
{
|
|
play = true;
|
|
director.Resume();
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
play = false;
|
|
director.Stop();
|
|
}
|
|
|
|
public void Reset(double timePoint)
|
|
{
|
|
timePoint = timePoint >= 0 ? timePoint : 0;
|
|
timePoint = timePoint <= Duration ? timePoint : Duration;
|
|
director.time = timePoint;
|
|
play = false;
|
|
time = Duration - timePoint;
|
|
}
|
|
|
|
public void ResetAndPlay(double timePoint)
|
|
{
|
|
timePoint = timePoint >= 0 ? timePoint : 0;
|
|
timePoint = timePoint <= Duration ? timePoint : Duration;
|
|
director.time = timePoint;
|
|
play = true;
|
|
time = Duration - timePoint;
|
|
director.Play();
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
director.time = 0;
|
|
play = false;
|
|
time = Duration;
|
|
}
|
|
|
|
public void ResetAndPlay()
|
|
{
|
|
director.time = 0;
|
|
play = true;
|
|
time = Duration;
|
|
director.Play();
|
|
}
|
|
public UnityEngine.Object GetBindingObject(string trackName)
|
|
{
|
|
PlayableBinding playableBinding;
|
|
if (tracks.TryGetValue(trackName, out playableBinding))
|
|
{
|
|
return director.GetGenericBinding(playableBinding.sourceObject);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void Binding(string trackName, UnityEngine.Object obj)
|
|
{
|
|
PlayableBinding playableBinding;
|
|
if (tracks.TryGetValue(trackName, out playableBinding))
|
|
{
|
|
CheckRemoveCacheComponents(director.GetGenericBinding(playableBinding.sourceObject));
|
|
CheckBindingType(playableBinding.sourceObject, obj);
|
|
director.SetGenericBinding(playableBinding.sourceObject, obj);
|
|
}
|
|
}
|
|
|
|
public void UnBinding(string trackName)
|
|
{
|
|
PlayableBinding playableBinding;
|
|
if (tracks.TryGetValue(trackName, out playableBinding))
|
|
{
|
|
CheckRemoveCacheComponents(director.GetGenericBinding(playableBinding.sourceObject));
|
|
director.SetGenericBinding(playableBinding.sourceObject, null);
|
|
}
|
|
}
|
|
|
|
public void ClearAllBinding()
|
|
{
|
|
foreach (var track in tracks)
|
|
{
|
|
CheckRemoveCacheComponents(director.GetGenericBinding(track.Value.sourceObject));
|
|
director.ClearGenericBinding(track.Value.sourceObject);
|
|
}
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
ClearAllBinding();
|
|
tracks.Clear();
|
|
ClearEvent();
|
|
}
|
|
}
|
|
}
|