Files
QuestAppLauncher/Assets/Scripts/IEnumeratorAwaitExtensions.cs
tverona1 6bca1d0c07 Support for renaming apps
- Adds support for renaming apps: By pressing A or X on the controller, you can choose an alternate app name / icon. You can reset these changes back to default in Settings.
2019-09-08 14:28:45 -07:00

148 lines
4.0 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading;
using UnityEngine;
namespace QuestAppLauncher
{
public class AsyncCoroutineRunner : MonoBehaviour
{
static AsyncCoroutineRunner _instance;
public static AsyncCoroutineRunner Instance
{
get
{
if (_instance == null)
{
_instance = new GameObject("AsyncCoroutineRunner")
.AddComponent<AsyncCoroutineRunner>();
}
return _instance;
}
}
void Awake()
{
// Don't show in scene hierarchy
gameObject.hideFlags = HideFlags.HideAndDontSave;
DontDestroyOnLoad(gameObject);
}
}
public static class IEnumeratorAwaitExtensions
{
public static SimpleCoroutineAwaiter<AsyncOperation> GetAwaiter(this AsyncOperation instruction)
{
return GetAwaiterReturnSelf(instruction);
}
static SimpleCoroutineAwaiter<T> GetAwaiterReturnSelf<T>(T instruction)
{
var awaiter = new SimpleCoroutineAwaiter<T>();
RunOnUnityScheduler(() => AsyncCoroutineRunner.Instance.StartCoroutine(
InstructionWrappers.ReturnSelf(awaiter, instruction)));
return awaiter;
}
static void RunOnUnityScheduler(Action action)
{
if (SynchronizationContext.Current == SyncContextUtil.UnitySynchronizationContext)
{
action();
}
else
{
SyncContextUtil.UnitySynchronizationContext.Post(_ => action(), null);
}
}
public class SimpleCoroutineAwaiter<T> : INotifyCompletion
{
bool _isDone;
Exception _exception;
Action _continuation;
T _result;
public bool IsCompleted
{
get { return _isDone; }
}
public T GetResult()
{
Debug.Assert(_isDone);
if (_exception != null)
{
ExceptionDispatchInfo.Capture(_exception).Throw();
}
return _result;
}
public void Complete(T result, Exception e)
{
Debug.Assert(!_isDone);
_isDone = true;
_exception = e;
_result = result;
// Always trigger the continuation on the unity thread when awaiting on unity yield
// instructions
if (_continuation != null)
{
RunOnUnityScheduler(_continuation);
}
}
void INotifyCompletion.OnCompleted(Action continuation)
{
Debug.Assert(_continuation == null);
Debug.Assert(!_isDone);
_continuation = continuation;
}
}
static class InstructionWrappers
{
public static IEnumerator ReturnSelf<T>(
SimpleCoroutineAwaiter<T> awaiter, T instruction)
{
yield return instruction;
awaiter.Complete(instruction, null);
}
}
public static class SyncContextUtil
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void Install()
{
UnitySynchronizationContext = SynchronizationContext.Current;
UnityThreadId = Thread.CurrentThread.ManagedThreadId;
}
public static int UnityThreadId
{
get; private set;
}
public static SynchronizationContext UnitySynchronizationContext
{
get; private set;
}
}
}
}