214 lines
7.0 KiB
C#
214 lines
7.0 KiB
C#
|
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()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
}
|