mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-04-25 15:47:26 -05:00
RuntimeOnlyAwaitCaller を実装
This commit is contained in:
parent
4743ad7c57
commit
cb1e30a195
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace VRMShaders
|
||||
{
|
||||
public sealed class NextFrameTaskScheduler
|
||||
{
|
||||
public bool IsSupported => Application.isPlaying;
|
||||
|
||||
public NextFrameTaskScheduler()
|
||||
{
|
||||
if (!IsSupported)
|
||||
{
|
||||
throw new NotSupportedException($"{nameof(NextFrameTaskScheduler)} is supported at runtime only.");
|
||||
}
|
||||
}
|
||||
|
||||
public bool Enqueue(Action action)
|
||||
{
|
||||
var currentFrame = Time.frameCount;
|
||||
|
||||
UnityLoopTaskScheduler.Instance.Scheduler.Enqueue(action, () => Time.frameCount != currentFrame);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private sealed class UnityLoopTaskScheduler : MonoBehaviour
|
||||
{
|
||||
private static UnityLoopTaskScheduler _instance;
|
||||
|
||||
public static UnityLoopTaskScheduler Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
var go = new GameObject("UniGLTF UnityThreadScheduler");
|
||||
Object.DontDestroyOnLoad(go);
|
||||
_instance = go.AddComponent<UnityLoopTaskScheduler>();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public TinyManagedTaskScheduler Scheduler { get; } = new TinyManagedTaskScheduler();
|
||||
|
||||
private void Update()
|
||||
{
|
||||
Scheduler.ManagedUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3ce7defdc7144878a058274ae561d0be
|
||||
timeCreated: 1634203513
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VRMShaders
|
||||
{
|
||||
public sealed class RuntimeOnlyAwaitCaller : IAwaitCaller
|
||||
{
|
||||
private readonly NextFrameTaskScheduler _scheduler;
|
||||
|
||||
public RuntimeOnlyAwaitCaller()
|
||||
{
|
||||
_scheduler = new NextFrameTaskScheduler();
|
||||
}
|
||||
|
||||
public Task NextFrame()
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
_scheduler.Enqueue(() => tcs.SetResult(default));
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public Task Run(Action action)
|
||||
{
|
||||
return Task.Run(action);
|
||||
}
|
||||
|
||||
public Task<T> Run<T>(Func<T> action)
|
||||
{
|
||||
return Task.Run(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e4e64b1835ca4cd2b682a6bda572b8fb
|
||||
timeCreated: 1634203216
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRMShaders
|
||||
{
|
||||
internal sealed class TinyManagedTaskScheduler
|
||||
{
|
||||
private readonly ConcurrentQueue<(Action, Func<bool>)> _continuationQueue =
|
||||
new ConcurrentQueue<(Action, Func<bool>)>();
|
||||
|
||||
public void ManagedUpdate()
|
||||
{
|
||||
while (_continuationQueue.TryDequeue(out var tuple))
|
||||
{
|
||||
var (continuation, canExecute) = tuple;
|
||||
|
||||
if (canExecute())
|
||||
{
|
||||
continuation();
|
||||
}
|
||||
else
|
||||
{
|
||||
_continuationQueue.Enqueue(tuple);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Enqueue(Action continuation, Func<bool> canExecute)
|
||||
{
|
||||
_continuationQueue.Enqueue((continuation, canExecute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9c52ff07a0834bdc8f4c8d6c7f9a634f
|
||||
timeCreated: 1634203919
|
||||
Loading…
Reference in New Issue
Block a user