Add more DoTween support - `AwaitForComplete`, `AwaitForPause`, `AwaitForPlay`, `AwaitForRewind`, `AwaitForStepComplete`.

master
neuecc 2020-08-25 07:10:39 +09:00
parent 1494ea6717
commit 727c7102d3
2 changed files with 134 additions and 10 deletions

View File

@ -489,6 +489,8 @@ await UniTask.WhenAll(
transform.DOScale(10, 3).WithCancellation(ct)); transform.DOScale(10, 3).WithCancellation(ct));
``` ```
DOTween support's default behaviour(`await`, `WithCancellation`, `ToUniTask`) awaits tween is killed. It works both Complete(true/false) and Kill(true/false). But if you want to tween reuse(`SetAutoKill(false)`), it does not work you expected. Or, if you want to await for another timing, the following extension methods exist in Tween, `AwaitForComplete`, `AwaitForPause`, `AwaitForPlay`, `AwaitForRewind`, `AwaitForStepComplete`.
AsyncEnumerable and Async LINQ AsyncEnumerable and Async LINQ
--- ---
Unity 2020.2.0a12 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in async era. Unity 2020.2.0a12 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in async era.

View File

@ -11,7 +11,6 @@ using System.Threading;
namespace Cysharp.Threading.Tasks namespace Cysharp.Threading.Tasks
{ {
// The idea of TweenCancelBehaviour is borrowed from https://www.shibuya24.info/entry/dotween_async_await
public enum TweenCancelBehaviour public enum TweenCancelBehaviour
{ {
Kill, Kill,
@ -29,6 +28,16 @@ namespace Cysharp.Threading.Tasks
public static class DOTweenAsyncExtensions public static class DOTweenAsyncExtensions
{ {
enum CallbackType
{
Kill,
Complete,
Pause,
Play,
Rewind,
StepComplete
}
public static TweenAwaiter GetAwaiter(this Tween tween) public static TweenAwaiter GetAwaiter(this Tween tween)
{ {
return new TweenAwaiter(tween); return new TweenAwaiter(tween);
@ -39,7 +48,7 @@ namespace Cysharp.Threading.Tasks
Error.ThrowArgumentNullException(tween, nameof(tween)); Error.ThrowArgumentNullException(tween, nameof(tween));
if (!tween.IsActive()) return UniTask.CompletedTask; if (!tween.IsActive()) return UniTask.CompletedTask;
return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, out var token), token); return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, CallbackType.Kill, out var token), token);
} }
public static UniTask ToUniTask(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default) public static UniTask ToUniTask(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
@ -47,7 +56,47 @@ namespace Cysharp.Threading.Tasks
Error.ThrowArgumentNullException(tween, nameof(tween)); Error.ThrowArgumentNullException(tween, nameof(tween));
if (!tween.IsActive()) return UniTask.CompletedTask; if (!tween.IsActive()) return UniTask.CompletedTask;
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, out var token), token); return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Kill, out var token), token);
}
public static UniTask AwaitForComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(tween, nameof(tween));
if (!tween.IsActive()) return UniTask.CompletedTask;
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Complete, out var token), token);
}
public static UniTask AwaitForPause(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(tween, nameof(tween));
if (!tween.IsActive()) return UniTask.CompletedTask;
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Pause, out var token), token);
}
public static UniTask AwaitForPlay(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(tween, nameof(tween));
if (!tween.IsActive()) return UniTask.CompletedTask;
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Play, out var token), token);
}
public static UniTask AwaitForRewind(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(tween, nameof(tween));
if (!tween.IsActive()) return UniTask.CompletedTask;
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Rewind, out var token), token);
}
public static UniTask AwaitForStepComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(tween, nameof(tween));
if (!tween.IsActive()) return UniTask.CompletedTask;
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.StepComplete, out var token), token);
} }
public struct TweenAwaiter : ICriticalNotifyCompletion public struct TweenAwaiter : ICriticalNotifyCompletion
@ -95,12 +144,13 @@ namespace Cysharp.Threading.Tasks
static readonly TweenCallback EmptyTweenCallback = () => { }; static readonly TweenCallback EmptyTweenCallback = () => { };
readonly TweenCallback onKillDelegate; readonly TweenCallback onCompleteCallbackDelegate;
readonly TweenCallback onUpdateDelegate; readonly TweenCallback onUpdateDelegate;
Tween tween; Tween tween;
TweenCancelBehaviour cancelBehaviour; TweenCancelBehaviour cancelBehaviour;
CancellationToken cancellationToken; CancellationToken cancellationToken;
CallbackType callbackType;
bool canceled; bool canceled;
TweenCallback originalUpdateAction; TweenCallback originalUpdateAction;
@ -108,11 +158,11 @@ namespace Cysharp.Threading.Tasks
TweenConfiguredSource() TweenConfiguredSource()
{ {
onKillDelegate = OnKill; onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
onUpdateDelegate = OnUpdate; onUpdateDelegate = OnUpdate;
} }
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, out short token) public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
@ -128,6 +178,7 @@ namespace Cysharp.Threading.Tasks
result.tween = tween; result.tween = tween;
result.cancelBehaviour = cancelBehaviour; result.cancelBehaviour = cancelBehaviour;
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
result.callbackType = callbackType;
result.originalUpdateAction = tween.onUpdate; result.originalUpdateAction = tween.onUpdate;
result.canceled = false; result.canceled = false;
@ -138,7 +189,30 @@ namespace Cysharp.Threading.Tasks
} }
tween.onUpdate = result.onUpdateDelegate; tween.onUpdate = result.onUpdateDelegate;
tween.onKill = result.onKillDelegate;
switch (callbackType)
{
case CallbackType.Kill:
tween.onKill = result.onCompleteCallbackDelegate;
break;
case CallbackType.Complete:
tween.onComplete = result.onCompleteCallbackDelegate;
break;
case CallbackType.Pause:
tween.onPause = result.onCompleteCallbackDelegate;
break;
case CallbackType.Play:
tween.onPlay = result.onCompleteCallbackDelegate;
break;
case CallbackType.Rewind:
tween.onRewind = result.onCompleteCallbackDelegate;
break;
case CallbackType.StepComplete:
tween.onStepComplete = result.onCompleteCallbackDelegate;
break;
default:
break;
}
TaskTracker.TrackActiveTask(result, 3); TaskTracker.TrackActiveTask(result, 3);
@ -146,7 +220,7 @@ namespace Cysharp.Threading.Tasks
return result; return result;
} }
void OnKill() void OnCompleteCallbackDelegate()
{ {
if (canceled) if (canceled)
{ {
@ -199,7 +273,31 @@ namespace Cysharp.Threading.Tasks
this.tween.Complete(true); this.tween.Complete(true);
break; break;
case TweenCancelBehaviour.CancelAwait: case TweenCancelBehaviour.CancelAwait:
this.tween.onKill = EmptyTweenCallback; // replace to empty(avoid callback after Canceled(instance is returned to pool.) // replace to empty(avoid callback after Canceled(instance is returned to pool.)
switch (callbackType)
{
case CallbackType.Kill:
tween.onKill = EmptyTweenCallback;
break;
case CallbackType.Complete:
tween.onComplete = EmptyTweenCallback;
break;
case CallbackType.Pause:
tween.onPause = EmptyTweenCallback;
break;
case CallbackType.Play:
tween.onPlay = EmptyTweenCallback;
break;
case CallbackType.Rewind:
tween.onRewind = EmptyTweenCallback;
break;
case CallbackType.StepComplete:
tween.onStepComplete = EmptyTweenCallback;
break;
default:
break;
}
this.core.TrySetCanceled(this.cancellationToken); this.core.TrySetCanceled(this.cancellationToken);
break; break;
} }
@ -272,7 +370,31 @@ namespace Cysharp.Threading.Tasks
TaskTracker.RemoveTracking(this); TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
tween.onUpdate = originalUpdateAction; tween.onUpdate = originalUpdateAction;
switch (callbackType)
{
case CallbackType.Kill:
tween.onKill = null; tween.onKill = null;
break;
case CallbackType.Complete:
tween.onComplete = null;
break;
case CallbackType.Pause:
tween.onPause = null;
break;
case CallbackType.Play:
tween.onPlay = null;
break;
case CallbackType.Rewind:
tween.onRewind = null;
break;
case CallbackType.StepComplete:
tween.onStepComplete = null;
break;
default:
break;
}
tween = default; tween = default;
cancellationToken = default; cancellationToken = default;
originalUpdateAction = default; originalUpdateAction = default;