using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UWE;
namespace NitroxClient.MonoBehaviours.Gui.Modals;
///
/// Base class for Modal components, which are dialog boxes that appear in the middle of the screen
///
public abstract class Modal
{
///
/// Get a Modal by its type at any time (static)
///
public static Dictionary Modals = new();
///
/// Current modal that is visible on the screen
///
public static Modal CurrentModal;
private GameObject modalSubWindow;
private TextMeshProUGUI text;
// All the properties that will be overriden by new instances that inherit this class
public string SubWindowName { get; init; }
public string ModalText { get; set; }
///
/// Makes it possible to dismiss the modal by clicking outside of the modal or pressing escape (default false).
///
public bool IsAvoidable { get; init; }
public bool HideNoButton { get; init; }
public string YesButtonText { get; init; }
public string NoButtonText { get; init; }
public bool FreezeGame { get; init; }
public float Transparency { get; init; }
public float Height { get; init; }
// Is useful for calling IngameMenu::OnDeselect() from a modal class (in Hide() for example)
public bool IsAvoidableBypass = false;
public Modal(string yesButtonText = "YES", bool hideNoButton = true, string noButtonText = "NO", string modalText = "", bool isAvoidable = false, bool freezeGame = false, float transparency = 0.392f, float height = 195f)
{
Type type = GetType();
if (Modals.ContainsKey(type))
{
throw new NotSupportedException($"You cannot set two modals to have the same Type");
}
SubWindowName = GetType().Name;
YesButtonText = yesButtonText;
HideNoButton = hideNoButton;
NoButtonText = noButtonText;
ModalText = modalText;
IsAvoidable = isAvoidable;
FreezeGame = freezeGame;
Transparency = transparency; // 0.392 is the default transparency for Subnautica's modal
Height = height;
Log.Debug($"Registered Modal {SubWindowName} of type {type}");
Modals.Add(type, this);
}
///
/// Adds the Modal to the screen
///
public void Show()
{
CoroutineHost.StartCoroutine(ShowAsync());
}
public IEnumerator ShowAsync()
{
CurrentModal?.Hide();
CurrentModal = this;
yield return ShowImplementation();
}
///
/// Removes the Modal from the screen
///
public void Hide()
{
CurrentModal = null;
if (FreezeGame)
{
FreezeTime.End(FreezeTime.Id.Quit);
}
if (IsAvoidable)
{
IngameMenu.main.OnDeselect();
}
else
{
IsAvoidableBypass = true;
IngameMenu.main.OnDeselect();
IsAvoidableBypass = false;
}
}
///
/// Called when this modal is deselected (only when pressing outside of the modal)
///
public virtual void OnDeselect() { }
///
/// This creates the modal when showing it for the first time, you can't modify it afterwards
///
private void InitSubWindow()
{
if (!IngameMenu.main)
{
throw new NotSupportedException($"Cannot show ingame subwindow {SubWindowName} because the ingame window does not exist.");
}
if (!modalSubWindow)
{
GameObject derivedSubWindow = IngameMenu.main.transform.Find("QuitConfirmation").gameObject;
modalSubWindow = UnityEngine.Object.Instantiate(derivedSubWindow, IngameMenu.main.transform, false);
modalSubWindow.name = SubWindowName;
// Styling.
RectTransform main = modalSubWindow.GetComponent();
main.sizeDelta = new Vector2(700, Height);
RectTransform messageTransform = modalSubWindow.FindChild("Header").GetComponent();
messageTransform.sizeDelta = new Vector2(700, Height);
messageTransform.anchoredPosition = new Vector2(0, 50 - Height / 2);
}
modalSubWindow.GetComponent().color = Color.white.WithAlpha(Transparency);
// Will happen either it's initialized or not
UpdateModal();
}
///
/// Update the modal with informations that may change from one Show() to another
///
private void UpdateModal()
{
text = modalSubWindow.FindChild("Header").GetComponent();
text.text = ModalText;
GameObject buttonYesObject = modalSubWindow.FindChild("ButtonYes");
GameObject buttonNoObject = modalSubWindow.FindChild("ButtonNo");
Button yesButton = buttonYesObject.GetComponent