77 lines
2.4 KiB
C#
77 lines
2.4 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using UnityEngine;
|
|
using UnityEngine.Playables;
|
|
using UnityEngine.Timeline;
|
|
|
|
namespace AibisDream.FrameAnimation.Timeline
|
|
{
|
|
[Serializable]
|
|
[DisplayName("Frame Animation Clip")]
|
|
public sealed class FrameAnimationTimelineClip : PlayableAsset, ITimelineClipAsset
|
|
{
|
|
private const double FallbackDurationSeconds = 1d;
|
|
|
|
[SerializeField, Tooltip("要由 Timeline 播放的独立 FrameClip 资产。")]
|
|
private FrameClip frameClip;
|
|
[SerializeField, HideInInspector] private FrameClip synchronizedDurationSource;
|
|
[SerializeField, HideInInspector] private bool hasSynchronizedDuration;
|
|
|
|
public FrameClip FrameClip => frameClip;
|
|
|
|
public override double duration => GetEffectiveDuration(frameClip);
|
|
|
|
public ClipCaps clipCaps
|
|
{
|
|
get
|
|
{
|
|
var caps = ClipCaps.ClipIn | ClipCaps.SpeedMultiplier;
|
|
if (frameClip != null && frameClip.DefaultEndBehavior == FrameClipEndBehavior.Loop)
|
|
{
|
|
caps |= ClipCaps.Looping;
|
|
}
|
|
return caps;
|
|
}
|
|
}
|
|
|
|
public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
|
|
{
|
|
var playable = ScriptPlayable<FrameAnimationTimelineBehaviour>.Create(graph);
|
|
playable.GetBehaviour().FrameClip = frameClip;
|
|
return playable;
|
|
}
|
|
|
|
internal void SetFrameClipForTests(FrameClip value)
|
|
{
|
|
frameClip = value;
|
|
}
|
|
|
|
internal bool TrySynchronizeSourceDuration(out double sourceDuration)
|
|
{
|
|
sourceDuration = duration;
|
|
if (hasSynchronizedDuration && synchronizedDurationSource == frameClip)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
synchronizedDurationSource = frameClip;
|
|
hasSynchronizedDuration = true;
|
|
return true;
|
|
}
|
|
|
|
internal static double GetEffectiveDuration(FrameClip value)
|
|
{
|
|
if (value == null || value.TotalDurationMs <= 0 || value.Speed <= 0f)
|
|
{
|
|
return FallbackDurationSeconds;
|
|
}
|
|
return value.TotalDurationMs / 1000d / value.Speed;
|
|
}
|
|
}
|
|
|
|
internal sealed class FrameAnimationTimelineBehaviour : PlayableBehaviour
|
|
{
|
|
internal FrameClip FrameClip { get; set; }
|
|
}
|
|
}
|