#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR) using System; using System.Collections; using System.Threading.Tasks; using UnityEngine; using UnityEngine.EventSystems; namespace SingularityGroup.HotReload { internal class Prompts : MonoBehaviour { public GameObject retryPrompt; public GameObject connectedPrompt; public GameObject questionPrompt; [Header("Other")] [Tooltip("Used when project does not create an EventSystem early enough")] public GameObject fallbackEventSystem; #region Singleton private static Prompts _I; /// /// All usages must check that is true before accessing this singleton. /// /// /// This getter can throw on unsupported platforms (HotReloadSettingsObject resource doesn't exist on unsupported platforms). /// public static Prompts I { get { if (_I == null) { // allow showing prompts in editor (for testing) if (!Application.isEditor && !PlayerEntrypoint.IsPlayerWithHotReload()) { throw new NotSupportedException("IsPlayerWithHotReload() is false"); } var go = Instantiate(HotReloadSettingsObject.I.PromptsPrefab, new Vector3(0, 0, 0), Quaternion.identity); go.name = nameof(Prompts) + "_singleton"; if (Application.isPlaying) { DontDestroyOnLoad(go); } _I = go.GetComponentInChildren(); } return _I; } } #endregion /// public static void SetConnectionState(string state, bool log = true) { var connectionDialog = I.connectedPrompt.GetComponentInChildren(); if (log) Log.Debug($"SetConnectionState( {state} )"); if (connectionDialog) { connectionDialog.SetSummary(state); } } /// public static void ShowConnectionDialog() { I.retryPrompt.SetActive(false); I.connectedPrompt.SetActive(true); } public static async Task ShowQuestionDialog(QuestionDialog.Config config) { var tcs = new TaskCompletionSource(); var holder = I.questionPrompt; var dialog = holder.GetComponentInChildren(); dialog.completion = tcs; dialog.UpdateView(config); holder.SetActive(true); return await tcs.Task; } public static void ShowRetryDialog( PatchServerInfo patchServerInfo, ServerHandshake.Result handshakeResults = ServerHandshake.Result.None, bool auto = true ) { var retryDialog = I.retryPrompt.GetComponentInChildren(); RetryDialog.TargetServer = patchServerInfo; RetryDialog.HandshakeResults = handshakeResults; if (patchServerInfo == null) { retryDialog.DebugInfo = $"patchServerInfo == null {handshakeResults}"; } else { retryDialog.DebugInfo = $"{RequestHelper.CreateUrl(patchServerInfo)} {handshakeResults}"; } retryDialog.autoConnect = auto; I.connectedPrompt.SetActive(false); I.retryPrompt.SetActive(true); } #region fallback event system private void Start() { StartCoroutine(DelayedEnsureEventSystem()); } private bool userTriedToInteract = false; private void Update() { if (!userTriedToInteract) { // when user interacts with the screen, make sure overlay can handle taps if (Input.touchCount > 0 || Input.GetMouseButtonDown(0)) { userTriedToInteract = true; DoEnsureEventSystem(); } } } private IEnumerator DelayedEnsureEventSystem() { // allow some delay in-case the project loads the EventSystem asynchronously (perhaps in a second scene) if (EventSystem.current == null) { yield return new WaitForSeconds(1f); DoEnsureEventSystem(); } } /// Scene must contain an EventSystem and StandaloneInputModule, otherwise clicking/tapping on the overlay does nothing. private void DoEnsureEventSystem() { if (EventSystem.current == null) { Log.Info($"No EventSystem is active, enabling an EventSystem inside Hot Reload {name} prefab." + " A Unity EventSystem and an Input module is required for tapping buttons on the Unity UI."); fallbackEventSystem.SetActive(true); } } #endregion } } #endif