Files
ft/Client/Assets/Scripts/Common/Timeline/LeviathanVideo/LeviathanVideoTrack.cs
2026-06-29 21:18:33 +08:00

98 lines
3.1 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
#if UNITY_EDITOR
using System.Reflection;
using UnityEditor;
#endif
namespace FT.Timeline
{
[Serializable]
public class LeviathanVideoTrackMixerBehaviour : PlayableBehaviour
{
}
[Serializable]
[TrackColor(0.82f, 0.42f, 0.62f)]
[TrackClipType(typeof(LeviathanVideoPlayableAsset))]
[TrackBindingType(typeof(LeviathanVideoDecoderBase))]
[ExcludeFromPreset]
public class LeviathanVideoTrack : TrackAsset
{
public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
{
return ScriptPlayable<LeviathanVideoTrackMixerBehaviour>.Create(graph, inputCount);
}
protected override void OnCreateClip(TimelineClip clip)
{
clip.displayName = "Leviathan Video";
if (clip.asset is LeviathanVideoPlayableAsset asset)
{
#if UNITY_EDITOR
ApplyNewClipFromBoundDecoder(clip, asset);
#endif
clip.duration = asset.clipDurationSeconds;
}
base.OnCreateClip(clip);
}
#if UNITY_EDITOR
/// <summary>
/// 新建 Clip 时:从当前 Timeline 窗口正在编辑的 Director 上读取本轨绑定解码器,同步 Video Override 与片段时长。
/// </summary>
private void ApplyNewClipFromBoundDecoder(TimelineClip clip, LeviathanVideoPlayableAsset asset)
{
var director = TryGetTimelineInspectedDirector();
if (director == null)
return;
var decoder = director.GetGenericBinding(this) as LeviathanVideoDecoderBase;
if (decoder == null)
return;
if (decoder.bytesFile != null)
asset.videoOverride = decoder.bytesFile;
if (LeviathanVideoPlayableAsset.TryGetClipDurationSecondsFromDecoder(decoder, out var seconds) &&
seconds > 0.0001)
asset.clipDurationSeconds = seconds;
EditorUtility.SetDirty(asset);
if (timelineAsset != null)
EditorUtility.SetDirty(timelineAsset);
}
private static PlayableDirector TryGetTimelineInspectedDirector()
{
foreach (var asm in System.AppDomain.CurrentDomain.GetAssemblies())
{
var t = asm.GetType("UnityEditor.Timeline.TimelineEditor");
if (t == null)
continue;
var p = t.GetProperty("inspectedDirector", BindingFlags.Public | BindingFlags.Static);
return p?.GetValue(null) as PlayableDirector;
}
return null;
}
#endif
#if UNITY_EDITOR
public override void GatherProperties(PlayableDirector director, IPropertyCollector driver)
{
var bound = director.GetGenericBinding(this) as LeviathanVideoDecoderBase;
if (bound != null)
{
driver.AddFromComponent(bound.gameObject, bound);
}
base.GatherProperties(director, driver);
}
#endif
}
}