Add DoTween Extension

master
neuecc 2020-05-23 01:10:04 +09:00
parent ec0123eec7
commit 896eef1ee4
7 changed files with 297 additions and 34 deletions

View File

@ -0,0 +1,241 @@
// asmdef Version Defines, enabled when com.demigiant.dotween is imported.
#if UNITASK_DOTWEEN_SUPPORT
using Cysharp.Threading.Tasks.Internal;
using DG.Tweening;
using System;
using System.Runtime.CompilerServices;
using System.Threading;
namespace Cysharp.Threading.Tasks
{
// The idea of TweenCancelBehaviour is borrowed from https://www.shibuya24.info/entry/dotween_async_await
public enum TweenCancelBehaviour
{
Kill,
KillWithCompleteCallback,
Complete,
CompleteWithSeqeunceCallback,
CancelAwait,
// AndCancelAwait
KillAndCancelAwait,
KillWithCompleteCallbackAndCancelAwait,
CompleteAndCancelAwait,
CompleteWithSeqeunceCallbackAndCancelAwait
}
public static class DoTweenAsyncExtensions
{
public static TweenAwaiter GetAwaiter(this Tween tween)
{
return new TweenAwaiter(tween);
}
public static UniTask WithCancellation(this Tween tween, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(tween, nameof(tween));
return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, out var token), token);
}
public static UniTask ToUniTask(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(tween, nameof(tween));
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, out var token), token);
}
public struct TweenAwaiter : ICriticalNotifyCompletion
{
readonly Tween tween;
// killed(non active) as completed.
public bool IsCompleted => !tween.IsActive();
public TweenAwaiter(Tween tween)
{
this.tween = tween;
}
public TweenAwaiter GetAwaiter()
{
return this;
}
public void GetResult()
{
}
public void OnCompleted(System.Action continuation)
{
UnsafeOnCompleted(continuation);
}
public void UnsafeOnCompleted(System.Action continuation)
{
// convert Action -> TweenCallback allocation.
// onKill is called after OnCompleted, both Complete(false/true) and Kill(false/true).
tween.onKill = new TweenCallback(continuation);
}
}
class TweenConfiguredSource : IUniTaskSource, IPromisePoolItem
{
static readonly PromisePool<TweenConfiguredSource> pool = new PromisePool<TweenConfiguredSource>();
static Action<object> CancellationCallbackDelegate = CancellationCallback;
Tween tween;
TweenCancelBehaviour cancelBehaviour;
CancellationToken cancellationToken;
bool canceled;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<AsyncUnit> core;
TweenConfiguredSource()
{
}
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
}
var result = pool.TryRent() ?? new TweenConfiguredSource();
result.tween = tween;
result.cancelBehaviour = cancelBehaviour;
result.cancellationToken = cancellationToken;
TaskTracker.TrackActiveTask(result, 3);
result.RegisterEvent();
token = result.core.Version;
return result;
}
void RegisterEvent()
{
if (cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(CancellationCallbackDelegate, this);
}
// allocate delegate.
tween.OnKill(new TweenCallback(OnKill));
}
void OnKill()
{
cancellationTokenRegistration.Dispose();
if (canceled)
{
if (cancelBehaviour == TweenCancelBehaviour.CancelAwait)
{
// already called TrySetCanceled, do nothing.
}
else
{
core.TrySetCanceled(cancellationToken);
}
}
else
{
core.TrySetResult(AsyncUnit.Default);
}
}
static void CancellationCallback(object state)
{
var self = (TweenConfiguredSource)state;
switch (self.cancelBehaviour)
{
case TweenCancelBehaviour.Kill:
default:
self.tween.Kill(false);
break;
case TweenCancelBehaviour.KillAndCancelAwait:
self.canceled = true;
self.tween.Kill(false);
break;
case TweenCancelBehaviour.KillWithCompleteCallback:
self.tween.Kill(true);
break;
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
self.canceled = true;
self.tween.Kill(true);
break;
case TweenCancelBehaviour.Complete:
self.tween.Complete(false);
break;
case TweenCancelBehaviour.CompleteAndCancelAwait:
self.canceled = true;
self.tween.Complete(false);
break;
case TweenCancelBehaviour.CompleteWithSeqeunceCallback:
self.tween.Complete(true);
break;
case TweenCancelBehaviour.CompleteWithSeqeunceCallbackAndCancelAwait:
self.canceled = true;
self.tween.Complete(true);
break;
case TweenCancelBehaviour.CancelAwait:
self.canceled = true;
self.core.TrySetCanceled(self.cancellationToken);
break;
}
}
public void GetResult(short token)
{
try
{
TaskTracker.RemoveTracking(this);
core.GetResult(token);
}
finally
{
pool.TryReturn(this);
}
}
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public void Reset()
{
core.Reset();
tween = default;
cancellationToken = default;
}
~TweenConfiguredSource()
{
if (pool.TryReturn(this))
{
GC.ReRegisterForFinalize(this);
}
}
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f448d5bc5b232e4f98d89d5d1832e8e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -2,7 +2,8 @@
"name": "UniTask", "name": "UniTask",
"references": [ "references": [
"Unity.ResourceManager", "Unity.ResourceManager",
"Unity.TextMeshPro" "Unity.TextMeshPro",
"DOTween.Modules"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],
@ -21,6 +22,11 @@
"name": "com.unity.textmeshpro", "name": "com.unity.textmeshpro",
"expression": "", "expression": "",
"define": "UNITASK_TEXTMESHPRO_SUPPORT" "define": "UNITASK_TEXTMESHPRO_SUPPORT"
},
{
"name": "com.demigiant.dotween",
"expression": "",
"define": "UNITASK_DOTWEEN_SUPPORT"
} }
], ],
"noEngineReferences": false "noEngineReferences": false

View File

@ -24,7 +24,6 @@ namespace Cysharp.Threading.Tasks
public static UniTask ToUniTask(this AsyncOperation asyncOperation) public static UniTask ToUniTask(this AsyncOperation asyncOperation)
{ {
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation)); Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, CancellationToken.None, out var token), token); return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, CancellationToken.None, out var token), token);
} }
@ -125,7 +124,6 @@ namespace Cysharp.Threading.Tasks
} }
} }
public UniTaskStatus GetStatus(short token) public UniTaskStatus GetStatus(short token)
{ {
return core.GetStatus(token); return core.GetStatus(token);

View File

@ -12,6 +12,9 @@ using Unity.Jobs;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
// using DG.Tweening;
public struct MyJob : IJob public struct MyJob : IJob
{ {
public int loopCount; public int loopCount;
@ -240,16 +243,9 @@ public class SandboxMain : MonoBehaviour
public int MyProperty { get; set; } public int MyProperty { get; set; }
} }
MyClass mcc;
void Start() async UniTaskVoid Start()
{ {
this.mcc = new MyClass();
this.MyProperty = 999;
CheckDest().Forget();
//UniTaskAsyncEnumerable.EveryValueChanged(mcc, x => x.MyProperty) //UniTaskAsyncEnumerable.EveryValueChanged(mcc, x => x.MyProperty)
// .Do(_ => { }, () => Debug.Log("COMPLETED")) // .Do(_ => { }, () => Debug.Log("COMPLETED"))
// .ForEachAsync(x => // .ForEachAsync(x =>
@ -260,22 +256,43 @@ public class SandboxMain : MonoBehaviour
// DG.Tweening.Core.TweenerCore<int>
//okButton.GetComponent<RectTransform>().DOMoveX(10.2f, 30);
// DOTween.To(
var cts = new CancellationTokenSource();
//var tween = okButton.GetComponent<RectTransform>().DOLocalMoveX(100, 5.0f);
cancelButton.OnClickAsAsyncEnumerable().ForEachAsync(_ =>
{
cts.Cancel();
}).Forget();
// await tween.ToUniTask(TweenCancelBehaviour.KillAndCancelAwait, cts.Token);
//tween.SetRecyclable(true);
Debug.Log("END");
// tween.Play();
// DOTween.
// DOVirtual.Float(0, 1, 1, x => { }).ToUniTask();
okButton.OnClickAsAsyncEnumerable().ForEachAsync(_ => okButton.OnClickAsAsyncEnumerable().ForEachAsync(_ =>
{ {
mcc.MyProperty += 10;
}).Forget(); }).Forget();
cancelButton.OnClickAsAsyncEnumerable().ForEachAsync(_ =>
{
this.mcc = null;
});
okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield())); okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield()));
@ -286,20 +303,6 @@ public class SandboxMain : MonoBehaviour
await UniTask.Yield(); await UniTask.Yield();
} }
async UniTaskVoid CheckDest()
{
try
{
Debug.Log("WAIT");
await UniTask.WaitUntilValueChanged(mcc, x => x.MyProperty);
Debug.Log("CHANGED?");
}
finally
{
Debug.Log("END");
}
}
async UniTaskVoid Running(CancellationToken ct) async UniTaskVoid Running(CancellationToken ct)
{ {
Debug.Log("BEGIN"); Debug.Log("BEGIN");

View File

@ -5,7 +5,8 @@
"UnityEditor.TestRunner", "UnityEditor.TestRunner",
"UniTask.Tests", "UniTask.Tests",
"UniTask", "UniTask",
"Unity.ResourceManager" "Unity.ResourceManager",
"DOTween.Modules"
], ],
"includePlatforms": [ "includePlatforms": [
"Editor" "Editor"
@ -14,7 +15,8 @@
"allowUnsafeCode": false, "allowUnsafeCode": false,
"overrideReferences": true, "overrideReferences": true,
"precompiledReferences": [ "precompiledReferences": [
"nunit.framework.dll" "nunit.framework.dll",
"DOTween.dll"
], ],
"autoReferenced": false, "autoReferenced": false,
"defineConstraints": [ "defineConstraints": [

View File

@ -4,14 +4,16 @@
"UnityEngine.TestRunner", "UnityEngine.TestRunner",
"UnityEditor.TestRunner", "UnityEditor.TestRunner",
"UniTask", "UniTask",
"Unity.ResourceManager" "Unity.ResourceManager",
"DOTween.Modules"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],
"allowUnsafeCode": false, "allowUnsafeCode": false,
"overrideReferences": true, "overrideReferences": true,
"precompiledReferences": [ "precompiledReferences": [
"nunit.framework.dll" "nunit.framework.dll",
"DOTween.dll"
], ],
"autoReferenced": false, "autoReferenced": false,
"defineConstraints": [ "defineConstraints": [