CapersProject/Packages/com.singularitygroup.hotreload/Runtime/MonoBehaviours/Prompts.cs

135 lines
5.1 KiB
C#

#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;
/// <summary>
/// All usages must check that <see cref="PlayerEntrypoint.RuntimeSupportsHotReload"/> is true before accessing this singleton.
/// </summary>
/// <remarks>
/// This getter can throw on unsupported platforms (HotReloadSettingsObject resource doesn't exist on unsupported platforms).
/// </remarks>
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<Prompts>();
}
return _I;
}
}
#endregion
/// <seealso cref="ShowConnectionDialog"/>
public static void SetConnectionState(string state, bool log = true) {
var connectionDialog = I.connectedPrompt.GetComponentInChildren<ConnectionDialog>();
if (log) Log.Debug($"SetConnectionState( {state} )");
if (connectionDialog) {
connectionDialog.SetSummary(state);
}
}
/// <seealso cref="SetConnectionState"/>
public static void ShowConnectionDialog() {
I.retryPrompt.SetActive(false);
I.connectedPrompt.SetActive(true);
}
public static async Task<bool> ShowQuestionDialog(QuestionDialog.Config config) {
var tcs = new TaskCompletionSource<bool>();
var holder = I.questionPrompt;
var dialog = holder.GetComponentInChildren<QuestionDialog>();
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>();
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