/**************************************************************************** * Copyright 2019 Nreal Techonology Limited. All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ namespace NRKernal { using System; using System.Collections.Generic; using System.Threading; using UnityEngine; /// A main thread dispather. [ExecuteInEditMode] public class MainThreadDispather : MonoBehaviour { /// A delayed queue item. public class DelayedQueueItem { /// The time. public float time; /// The action. public Action action; } /// The current. private static MainThreadDispather m_Current; /// Number of. private int m_Count; /// Current time. private static float m_CurrentTime; /// True once initialization is complete. private static bool m_Initialized; /// Identifier for the thread. private static int m_ThreadId = -1; /// The actions. private List m_Actions = new List(); /// The delayed. private List m_Delayed = new List(); /// Gets the current. /// The current. public static MainThreadDispather Current { get { if (!MainThreadDispather.m_Initialized) { MainThreadDispather.Initialize(); } return MainThreadDispather.m_Current; } } /// Initializes this object. public static void Initialize() { bool flag = !MainThreadDispather.m_Initialized; if (flag && MainThreadDispather.m_ThreadId != -1 && MainThreadDispather.m_ThreadId != Thread.CurrentThread.ManagedThreadId) { return; } if (flag) { GameObject gameObject = new GameObject("MainThreadDispather"); gameObject.hideFlags = HideFlags.DontSave; UnityEngine.Object.DontDestroyOnLoad(gameObject); if (MainThreadDispather.m_Current) { if (Application.isPlaying) { UnityEngine.Object.Destroy(MainThreadDispather.m_Current.gameObject); } else { UnityEngine.Object.DestroyImmediate(MainThreadDispather.m_Current.gameObject); } } MainThreadDispather.m_Current = gameObject.AddComponent(); UnityEngine.Object.DontDestroyOnLoad(MainThreadDispather.m_Current); MainThreadDispather.m_Initialized = true; MainThreadDispather.m_ThreadId = Thread.CurrentThread.ManagedThreadId; MainThreadDispather.m_CurrentTime = Time.time; } } /// Executes the 'destroy' action. private void OnDestroy() { MainThreadDispather.m_Initialized = false; } /// Queue on main thread. /// The action. public static void QueueOnMainThread(Action action) { MainThreadDispather.QueueOnMainThread(action, 0f); } /// Queue on main thread. /// The action. /// The time. public static void QueueOnMainThread(Action action, float time) { if (time != 0f) { List delayed = MainThreadDispather.Current.m_Delayed; lock (delayed) { MainThreadDispather.Current.m_Delayed.Add(new MainThreadDispather.DelayedQueueItem { time = m_CurrentTime + time, action = action }); } } else { List actions = MainThreadDispather.Current.m_Actions; lock (actions) { MainThreadDispather.Current.m_Actions.Add(action); } } } /// Executes the 'asynchronous' operation. /// The action. public static void RunAsync(Action action) { new Thread(new ParameterizedThreadStart(MainThreadDispather.RunAction)) { Priority = System.Threading.ThreadPriority.Normal }.Start(action); } /// Executes the action. /// The action. private static void RunAction(object action) { ((Action)action)?.Invoke(); } /// Updates this object. private void Update() { MainThreadDispather.m_CurrentTime = Time.time; List actions = this.m_Actions; if (actions.Count > 0) { lock (actions) { for (int i = 0; i < this.m_Actions.Count; i++) { this.m_Actions[i](); } this.m_Actions.Clear(); } } List delayed = this.m_Delayed; if (delayed.Count > 0) { lock (delayed) { for (int j = 0; j < this.m_Delayed.Count; j++) { MainThreadDispather.DelayedQueueItem delayedQueueItem = this.m_Delayed[j]; if (delayedQueueItem.time <= MainThreadDispather.m_CurrentTime) { delayedQueueItem.action(); this.m_Delayed.RemoveAt(j); j--; } } } } } } }