116 lines
3.3 KiB
C#
116 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
|
|
namespace AibisDream.FrameAnimation
|
|
{
|
|
public sealed class FrameAnimationPlaybackAwaitable : CustomYieldInstruction
|
|
{
|
|
private readonly FrameAnimationPlayer player;
|
|
|
|
public FrameAnimationPlaybackHandle PlaybackHandle { get; }
|
|
|
|
internal FrameAnimationPlaybackAwaitable(
|
|
FrameAnimationPlayer player,
|
|
FrameAnimationPlaybackHandle playbackHandle)
|
|
{
|
|
this.player = player;
|
|
PlaybackHandle = playbackHandle ??
|
|
throw new ArgumentNullException(nameof(playbackHandle));
|
|
}
|
|
|
|
public override bool keepWaiting =>
|
|
player != null && player.ShouldWaitForAsyncCompletion(PlaybackHandle);
|
|
}
|
|
|
|
public sealed class FrameAnimationPlaybackHandle : CustomYieldInstruction
|
|
{
|
|
private readonly TaskCompletionSource<FrameAnimationPlaybackResult> completionSource =
|
|
new TaskCompletionSource<FrameAnimationPlaybackResult>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
private readonly List<Action<FrameAnimationPlaybackResult>> callbacks =
|
|
new List<Action<FrameAnimationPlaybackResult>>();
|
|
|
|
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<FrameAnimationPlaybackResult> WaitAsync()
|
|
{
|
|
return completionSource.Task;
|
|
}
|
|
|
|
public void RegisterCompleted(Action<FrameAnimationPlaybackResult> 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<FrameAnimationPlaybackResult> callback,
|
|
FrameAnimationPlaybackResult completionResult)
|
|
{
|
|
try
|
|
{
|
|
callback(completionResult);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.LogException(exception);
|
|
}
|
|
}
|
|
}
|
|
}
|