using UnityEngine; #if NETFX_CORE || BUILD_FOR_WP8 using System.Threading.Tasks; #endif namespace BestHTTP { /// /// Will route some U3D calls to the HTTPManager. /// [ExecuteInEditMode] public sealed class HTTPUpdateDelegator : MonoBehaviour { #region Public Properties /// /// The singleton instance of the HTTPUpdateDelegator /// public static HTTPUpdateDelegator Instance { get; private set; } /// /// True, if the Instance property should hold a valid value. /// public static bool IsCreated { get; private set; } /// /// Set it true before any CheckInstance() call, or before any request sent to dispatch callbacks on another thread. /// public static bool IsThreaded { get; set; } /// /// It's true if the dispatch thread running. /// public static bool IsThreadRunning { get; private set; } /// /// How much time the plugin should wait between two update call. Its default value 100 ms. /// public static int ThreadFrequencyInMS { get; set; } /// /// Called in the OnApplicationQuit function. If this function returns False, the plugin will not start to /// shut down itself. /// public static System.Func OnBeforeApplicationQuit; public static System.Action OnApplicationForegroundStateChanged; #endregion private static bool IsSetupCalled; static HTTPUpdateDelegator() { ThreadFrequencyInMS = 100; } /// /// Will create the HTTPUpdateDelegator instance and set it up. /// public static void CheckInstance() { try { if (!IsCreated) { GameObject go = GameObject.Find("HTTP Update Delegator"); if (go != null) Instance = go.GetComponent(); if (Instance == null) { go = new GameObject("HTTP Update Delegator"); go.hideFlags = HideFlags.DontSave; Instance = go.AddComponent(); } IsCreated = true; #if UNITY_EDITOR if (!UnityEditor.EditorApplication.isPlaying) { UnityEditor.EditorApplication.update -= Instance.Update; UnityEditor.EditorApplication.update += Instance.Update; } #if UNITY_2017_2_OR_NEWER UnityEditor.EditorApplication.playModeStateChanged -= Instance.OnPlayModeStateChanged; UnityEditor.EditorApplication.playModeStateChanged += Instance.OnPlayModeStateChanged; #else UnityEditor.EditorApplication.playmodeStateChanged -= Instance.OnPlayModeStateChanged; UnityEditor.EditorApplication.playmodeStateChanged += Instance.OnPlayModeStateChanged; #endif #endif HTTPManager.Logger.Information("HTTPUpdateDelegator", "Instance Created!"); } } catch { HTTPManager.Logger.Error("HTTPUpdateDelegator", "Please call the BestHTTP.HTTPManager.Setup() from one of Unity's event(eg. awake, start) before you send any request!"); } } private void Setup() { #if !BESTHTTP_DISABLE_CACHING && (!UNITY_WEBGL || UNITY_EDITOR) Caching.HTTPCacheService.SetupCacheFolder(); #endif #if !BESTHTTP_DISABLE_COOKIES && (!UNITY_WEBGL || UNITY_EDITOR) Cookies.CookieJar.SetupFolder(); Cookies.CookieJar.Load(); #endif #if UNITY_WEBGL && !UNITY_EDITOR // Threads are not implemented in WEBGL builds, disable it for now. IsThreaded = false; #endif if (IsThreaded) { #if NETFX_CORE #pragma warning disable 4014 Windows.System.Threading.ThreadPool.RunAsync(ThreadFunc); #pragma warning restore 4014 #else System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ThreadFunc)); #endif } IsSetupCalled = true; // Unity doesn't tolerate well if the DontDestroyOnLoad called when purely in editor mode. So, we will set the flag // only when we are playing, or not in the editor. if (!Application.isEditor || Application.isPlaying) GameObject.DontDestroyOnLoad(this.gameObject); HTTPManager.Logger.Information("HTTPUpdateDelegator", "Setup done!"); } #if NETFX_CORE async #endif void ThreadFunc(object obj) { HTTPManager.Logger.Information ("HTTPUpdateDelegator", "Update Thread Started"); try { IsThreadRunning = true; while (IsThreadRunning) { HTTPManager.OnUpdate(); #if NETFX_CORE await Task.Delay(ThreadFrequencyInMS); #else System.Threading.Thread.Sleep(ThreadFrequencyInMS); #endif } } finally { HTTPManager.Logger.Information("HTTPUpdateDelegator", "Update Thread Ended"); } } void Update() { if (!IsSetupCalled) { IsSetupCalled = true; Setup(); } if (!IsThreaded) HTTPManager.OnUpdate(); } #if UNITY_EDITOR #if UNITY_2017_2_OR_NEWER void OnPlayModeStateChanged(UnityEditor.PlayModeStateChange playMode) { if (playMode == UnityEditor.PlayModeStateChange.EnteredPlayMode) UnityEditor.EditorApplication.update -= Update; else if (playMode == UnityEditor.PlayModeStateChange.ExitingPlayMode) UnityEditor.EditorApplication.update += Update; } #else void OnPlayModeStateChanged() { if (UnityEditor.EditorApplication.isPlaying) UnityEditor.EditorApplication.update -= Update; else if (!UnityEditor.EditorApplication.isPlaying) UnityEditor.EditorApplication.update += Update; } #endif #endif void OnDisable() { HTTPManager.Logger.Information("HTTPUpdateDelegator", "OnDisable Called!"); #if UNITY_EDITOR if (UnityEditor.EditorApplication.isPlaying) #endif OnApplicationQuit(); } void OnApplicationPause(bool isPaused) { if (HTTPUpdateDelegator.OnApplicationForegroundStateChanged != null) HTTPUpdateDelegator.OnApplicationForegroundStateChanged(isPaused); } void OnApplicationQuit() { HTTPManager.Logger.Information("HTTPUpdateDelegator", "OnApplicationQuit Called!"); if (OnBeforeApplicationQuit != null) { try { if (!OnBeforeApplicationQuit()) { HTTPManager.Logger.Information("HTTPUpdateDelegator", "OnBeforeApplicationQuit call returned false, postponing plugin shutdown."); return; } } catch(System.Exception ex) { HTTPManager.Logger.Exception("HTTPUpdateDelegator", string.Empty, ex); } } IsThreadRunning = false; if (!IsCreated) return; IsCreated = false; HTTPManager.OnQuit(); #if UNITY_EDITOR UnityEditor.EditorApplication.update -= Update; #if UNITY_2017_2_OR_NEWER UnityEditor.EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; #else UnityEditor.EditorApplication.playmodeStateChanged -= OnPlayModeStateChanged; #endif #endif } } }