diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/IAwaitCaller.cs b/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/IAwaitCaller.cs index c97e4d0ce..877ae8ae0 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/IAwaitCaller.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/IAwaitCaller.cs @@ -31,5 +31,11 @@ namespace VRMShaders /// /// Task Run(Func action); + + /// + /// 指定した時間が経過している場合のみ、NextFrame() を使って1フレーム待つ + /// + /// タイムアウト時はNextFrame()を呼び出す。そうではない場合、Task.CompletedTaskを返す + Task NextFrameIfTimedOut(); } } diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/ImmediateCaller.cs b/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/ImmediateCaller.cs index f3e6d56a0..db71fe818 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/ImmediateCaller.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/ImmediateCaller.cs @@ -23,5 +23,7 @@ namespace VRMShaders { return Task.FromResult(action()); } + + public Task NextFrameIfTimedOut() => NextFrame(); } } \ No newline at end of file diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/RuntimeOnlyAwaitCaller.cs b/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/RuntimeOnlyAwaitCaller.cs index 83665d7a0..b583465ff 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/RuntimeOnlyAwaitCaller.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/RuntimeOnlyAwaitCaller.cs @@ -10,14 +10,23 @@ namespace VRMShaders public sealed class RuntimeOnlyAwaitCaller : IAwaitCaller { private readonly NextFrameTaskScheduler _scheduler; + private readonly float _timeOutInSeconds; + private float _lastTimeoutBaseTime; - public RuntimeOnlyAwaitCaller() + /// + /// タイムアウト指定可能なコンストラクタ + /// + /// NextFrameIfTimedOutがタイムアウトと見なす時間(秒単位) + public RuntimeOnlyAwaitCaller(float timeOutInSeconds = 1f / 1000f) { _scheduler = new NextFrameTaskScheduler(); + _timeOutInSeconds = timeOutInSeconds; + ResetLastTimeoutBaseTime(); } public Task NextFrame() { + ResetLastTimeoutBaseTime(); var tcs = new TaskCompletionSource(); _scheduler.Enqueue(() => tcs.SetResult(default)); return tcs.Task; @@ -33,50 +42,20 @@ namespace VRMShaders return Task.Run(action); } - /// - /// 指定した時間が経過している場合のみ、NextFrame() を使って1フレーム待つ - /// - /// タイムアウト時間(ミリ秒単位) - /// タイムアウト時はNextFrame()を呼び出す。そうではない場合、Task.CompletedTaskを返す - public Task NextFrameIfTimedOut_(float timeOutInMilliseconds = 1f) - { - if (!CheckTimeOut(timeOutInMilliseconds)) - { - return Task.CompletedTask; - } - _lastBaseTime = 0f; - return NextFrame(); - } + public Task NextFrameIfTimedOut() => CheckTimeout() ? NextFrame() : Task.CompletedTask; - private bool CheckTimeOut(float timeOutInMilliseconds) + private void ResetLastTimeoutBaseTime() => _lastTimeoutBaseTime = 0f; + + private bool LastTimeoutBaseTimeNeedsReset => _lastTimeoutBaseTime == 0f; + + private bool CheckTimeout() { float t = UnityEngine.Time.realtimeSinceStartup; - if (_lastBaseTime == 0f) + if (LastTimeoutBaseTimeNeedsReset) { - // Reset base time - _lastBaseTime = t; + _lastTimeoutBaseTime = t; } - return (t - _lastBaseTime) >= timeOutInMilliseconds * (1f / 1000f); - } - - private float _lastBaseTime; - } - - internal static class RuntimeOnlyAwaitCallerHelper - { - /// - /// 指定した時間が経過している場合のみ、NextFrame() を使って1フレーム待つ - /// - /// IAwaitCallerのインスタンス - /// タイムアウト時間(ミリ秒単位) - /// タイムアウト時はNextFrame()を呼び出す。そうではない場合、Task.CompletedTaskを返す - internal static Task NextFrameIfTimedOut(this IAwaitCaller iAwaitCaller, float timeOutInMilliseconds) - { - if (iAwaitCaller is RuntimeOnlyAwaitCaller runtimeOnlyAwaitCaller) - { - return runtimeOnlyAwaitCaller.NextFrameIfTimedOut_(timeOutInMilliseconds); - } - return Task.CompletedTask; + return (t - _lastTimeoutBaseTime) >= _timeOutInSeconds; } } } diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/RuntimeOnlyNoThreadAwaitCaller.cs b/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/RuntimeOnlyNoThreadAwaitCaller.cs index e3b53c9a8..97e8597fd 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/RuntimeOnlyNoThreadAwaitCaller.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/AwaitCaller/RuntimeOnlyNoThreadAwaitCaller.cs @@ -10,14 +10,23 @@ namespace VRMShaders public sealed class RuntimeOnlyNoThreadAwaitCaller : IAwaitCaller { private readonly NextFrameTaskScheduler _scheduler; + private readonly float _timeoutInSeconds; + private float _lastTimeoutBaseTime; - public RuntimeOnlyNoThreadAwaitCaller() + /// + /// タイムアウト指定可能なコンストラクタ + /// + /// NextFrameIfTimedOutがタイムアウトと見なす時間(秒単位) + public RuntimeOnlyNoThreadAwaitCaller(float timeoutInSeconds = 1f / 1000f) { _scheduler = new NextFrameTaskScheduler(); + _timeoutInSeconds = timeoutInSeconds; + ResetLastTimeoutBaseTime(); } public Task NextFrame() { + ResetLastTimeoutBaseTime(); var tcs = new TaskCompletionSource(); _scheduler.Enqueue(() => tcs.SetResult(default)); return tcs.Task; @@ -47,5 +56,21 @@ namespace VRMShaders return Task.FromException(ex); } } + + public Task NextFrameIfTimedOut() => CheckTimeout() ? NextFrame() : Task.CompletedTask; + + private void ResetLastTimeoutBaseTime() => _lastTimeoutBaseTime = 0f; + + private bool LastTimeoutBaseTimeNeedsReset => _lastTimeoutBaseTime == 0f; + + private bool CheckTimeout() + { + float t = UnityEngine.Time.realtimeSinceStartup; + if (LastTimeoutBaseTimeNeedsReset) + { + _lastTimeoutBaseTime = t; + } + return (t - _lastTimeoutBaseTime) >= _timeoutInSeconds; + } } } \ No newline at end of file