using System; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; namespace AibisDream.FrameAnimation { public sealed class FrameAnimationPlaybackHandle : CustomYieldInstruction { private readonly TaskCompletionSource completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); private readonly List> callbacks = new List>(); private bool isCompleted; private FrameAnimationPlaybackResult result; public long RequestId { get; } public bool IsCompleted => isCompleted; public override bool keepWaiting => !isCompleted; public FrameAnimationPlaybackResult Result { get { if (!isCompleted) { throw new InvalidOperationException("播放请求尚未完成,不能读取 Result。"); } return result; } } internal FrameAnimationPlaybackHandle(long requestId) { RequestId = requestId; } public Task WaitAsync() { return completionSource.Task; } public void RegisterCompleted(Action callback) { if (callback == null) { throw new ArgumentNullException(nameof(callback)); } if (isCompleted) { InvokeCallback(callback, result); return; } callbacks.Add(callback); } internal bool TryComplete(FrameAnimationPlaybackResult completionResult) { if (isCompleted) { return false; } isCompleted = true; result = completionResult; completionSource.TrySetResult(completionResult); var callbacksToInvoke = callbacks.ToArray(); callbacks.Clear(); foreach (var callback in callbacksToInvoke) { InvokeCallback(callback, completionResult); } return true; } private static void InvokeCallback( Action callback, FrameAnimationPlaybackResult completionResult) { try { callback(completionResult); } catch (Exception exception) { Debug.LogException(exception); } } } }