micromissiles-unity/Assets/Scripts/UI/UIDialog.cs

214 lines
7.0 KiB
C#
Raw Permalink Normal View History

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using System;
using UnityEngine.UI;
public class UIDialog : MonoBehaviour
{
[SerializeField]
private string dialogTitle;
[SerializeField]
private TextMeshProUGUI dialogTitleHandle;
[SerializeField]
private RectTransform contentHandle;
/// TABS
[SerializeField]
private float tabWidth = 50f;
[SerializeField]
private float tabHeight = 16f;
// List of dialog tabs
private List<GameObject> dialogTabs;
/// ENTRIES
private List<UISelectableEntry> entries;
private float entryHeight = 20f;
private float entryIndentWidth= 10f;
private List<UISelectableEntry> cleanupPool;
private bool isOpen;
// Start is called before the first frame update
public virtual void Start()
{
dialogTitleHandle.text = dialogTitle;
dialogTitleHandle.font = UIManager.Instance.Font;
isOpen = gameObject.activeSelf;
dialogTabs = new List<GameObject>();
entries = new List<UISelectableEntry>();
cleanupPool = new List<UISelectableEntry>();
}
internal RectTransform GetContentHandle()
{
return contentHandle;
}
public bool IsOpen()
{
return isOpen;
}
protected virtual void OnEnable() { isOpen = true; }
protected virtual void OnDisable() { isOpen = false; }
public float GetTabWidth() { return tabWidth; }
public float GetTabHeight() { return tabHeight; }
/// <summary>
/// Returns the height of the dialog title bar
/// </summary>
public float GetTitleBarHeight() { return dialogTitleHandle.rectTransform.sizeDelta.y; }
/// <summary>
/// Adds a new tab to the dialog, when clicked it will call the given callback
/// </summary>
public void AddDialogTab(string tabName, Action onClick)
{
dialogTabs.Add(AddTabButton(tabName, onClick));
}
/// <summary>
/// Add the tab button to the right of the existing tabs
/// </summary>
private GameObject AddTabButton(string tabName, Action onClick)
{
GameObject tabButton = new GameObject("TabButton", typeof(RectTransform));
tabButton.transform.SetParent(transform); // worldPositionStays ?
// RectTransform anchors to the right of the content handle
RectTransform rTransform = tabButton.GetComponent<RectTransform>();
rTransform.anchorMin = new Vector2(0, 1);
rTransform.anchorMax = new Vector2(0, 1);
rTransform.pivot = new Vector2(0, 1);
rTransform.sizeDelta = new Vector2(tabWidth, tabHeight);
// Count tabs * tabSize to get the position from the left
rTransform.anchoredPosition = new Vector2(tabWidth * dialogTabs.Count, -(GetTitleBarHeight()));
// Add the onClick callback to the button
Button button = tabButton.AddComponent<Button>();
button.onClick.AddListener(() => onClick());
// Add the image to the button and link it to the tab
button.targetGraphic = tabButton.AddComponent<Image>();
AddTabText(tabName, tabButton);
return tabButton;
}
/// <summary>
/// Add text as a child of the tab's button object
/// </summary>
private void AddTabText(string tabName, GameObject tabButton)
{
GameObject tabText = new GameObject("TabText", typeof(RectTransform));
tabText.transform.SetParent(tabButton.transform);
// RectTransform anchors to the center of the button
RectTransform textRectTransform = tabText.GetComponent<RectTransform>();
textRectTransform.anchorMin = new Vector2(0.5f, 0.5f);
textRectTransform.anchorMax = new Vector2(0.5f, 0.5f);
textRectTransform.pivot = new Vector2(0.5f, 0.5f);
textRectTransform.sizeDelta = new Vector2(tabWidth, tabHeight);
// Text position
textRectTransform.anchoredPosition = new Vector2(0, 0);
TextMeshProUGUI buttonText = tabText.AddComponent<TextMeshProUGUI>();
buttonText.text = tabName;
buttonText.font = UIManager.Instance.Font;
buttonText.fontSize = 12;
buttonText.color = Color.black;
buttonText.alignment = TextAlignmentOptions.Center;
buttonText.verticalAlignment = VerticalAlignmentOptions.Middle;
}
public virtual UISelectableEntry CreateSelectableEntry()
{
// Create a new entry object with content handle as parent
GameObject go = Instantiate(Resources.Load<GameObject>("Prefabs/EmptyObject"), contentHandle);
go.name = "UISelectableEntry";
UISelectableEntry entry = go.AddComponent<UISelectableEntry>();
entry.SetParent(this);
// add to cleanup pool so we can clear later in clear dialog entries
cleanupPool.Add(entry);
return entry;
}
public void ClearDialogEntries()
{
if (cleanupPool == null)
return;
foreach (UISelectableEntry entry in cleanupPool)
{
GameObject.Destroy(entry.gameObject);
}
cleanupPool.Clear();
if (entries != null)
entries.Clear();
}
/// <summary>
/// Clears, sets, and prints the dialog entries in the order they were added
/// </summary>
public virtual void SetDialogEntries(List<UISelectableEntry> entries)
{
this.entries = entries;
// calculate total height of the content
float heightHead = -1*GetTabHeight();
int count = 0;
foreach (UISelectableEntry entry in this.entries)
{
(heightHead, count) = RecursiveContentPrint(entry, 1, heightHead, count);
}
contentHandle.sizeDelta = new Vector2(contentHandle.sizeDelta.x, count * entryHeight + Mathf.Abs(heightHead));
}
public virtual void SetDialogEntries(UISelectableEntry entry)
{
SetDialogEntries(new List<UISelectableEntry>() { entry });
}
private (float, int) RecursiveContentPrint(UISelectableEntry entry, int depth, float heightHead, int count)
{
RectTransform rTransform = entry.GetComponent<RectTransform>();
rTransform.anchorMin = new Vector2(0, 1);
rTransform.anchorMax = new Vector2(1, 1);
rTransform.pivot = new Vector2(0.5f, 1f);
rTransform.anchoredPosition = new Vector2(0, heightHead); // positioning from top
rTransform.sizeDelta = new Vector2(0, entryHeight);
float padding = 5f;
rTransform.SetRight(padding);
rTransform.SetLeft(padding);
// actually indent the text
entry.GetTextTransform().anchoredPosition = new Vector2(entryIndentWidth * depth, 0);
heightHead -= entryHeight;
count++;
// Print the children
if (entry.GetChildEntries() != null)
{
foreach (UISelectableEntry child in entry.GetChildEntries())
{
(heightHead, count) = RecursiveContentPrint(child, depth + 1, heightHead, count);
}
}
return (heightHead, count);
}
// Update is called once per frame
void Update()
{
}
}