namespace UIWidgets { using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.UI; /// /// Modal helper for UI widgets. /// modalKey = ModalHelper.Open(this, modalSprite, modalColor); /// //... /// ModalHelper.Close(modalKey); /// [RequireComponent(typeof(RectTransform))] public class ModalHelper : MonoBehaviour, ITemplatable, IPointerClickHandler { static readonly Dictionary Used = new Dictionary(); static Templates Templates = new Templates(); static string key = "ModalTemplate"; #if UNITY_2019_3_OR_NEWER [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] static void StaticInit() { Templates = new Templates(); Used.Clear(); key = "ModalTemplate"; } #endif bool isTemplate = true; /// /// Gets a value indicating whether this instance is template. /// /// true if this instance is template; otherwise, false. public bool IsTemplate { get { return isTemplate; } set { isTemplate = value; } } /// /// Gets the name of the template. /// /// The name of the template. public string TemplateName { get; set; } readonly UnityEvent OnClick = new UnityEvent(); /// /// Create modal helper with the specified parent, sprite and color. /// /// Parent game object. /// Sprite. /// Color. /// onClick callback /// Parent. /// Modal helper index public static int Open(Component parentGameObject, Sprite sprite = null, Color? color = null, UnityAction onClick = null, RectTransform parent = null) { // check if in cache if (!Templates.Exists(key)) { Templates.FindTemplates(); CreateTemplate(); } var modal = Templates.Instance(key); if (parent == null) { parent = UtilitiesUI.FindTopmostCanvas(parentGameObject.transform); } modal.gameObject.SetActive(true); var rt = modal.transform as RectTransform; rt.SetParent(parent, false); rt.SetAsLastSibling(); rt.localPosition = Vector3.zero; rt.sizeDelta = new Vector2(0, 0); rt.anchorMin = new Vector2(0, 0); rt.anchorMax = new Vector2(1, 1); rt.anchoredPosition = new Vector2(0, 0); var img = modal.GetComponent(); if (sprite != null) { img.sprite = sprite; } if (color != null) { img.color = (Color)color; } modal.OnClick.RemoveAllListeners(); if (onClick != null) { modal.OnClick.AddListener(onClick); } Used.Add(modal.GetInstanceID(), modal); return modal.GetInstanceID(); } /// /// Creates the template. /// static void CreateTemplate() { var template = new GameObject(key); var modal = template.AddComponent(); template.AddComponent(); var le = template.AddComponent(); le.ignoreLayout = true; Templates.Add(key, modal); template.gameObject.SetActive(false); } /// /// Gets the modal instance. /// /// The instance. /// Index. public static GameObject GetInstance(int index) { return ((Used != null) && Used.ContainsKey(index)) ? Used[index].gameObject : null; } /// /// Set instance as last sibling. /// /// Instance index. /// true if instance exists; otherwise false. public static bool SetAsLastSibling(int? index) { if (index.HasValue) { return SetAsLastSibling(index.Value); } return false; } /// /// Set instance as last sibling. /// /// Instance index. /// true if instance exists; otherwise false. public static bool SetAsLastSibling(int index) { var instance = GetInstance(index); if (instance != null) { instance.transform.SetAsLastSibling(); return true; } return false; } /// /// Close modal helper with the specified index. /// /// Index. public static void Close(int index) { if ((Used != null) && Used.ContainsKey(index)) { Used[index].OnClick.RemoveAllListeners(); Templates.ToCache(Used[index]); Used.Remove(index); } } /// /// Remove template. /// protected virtual void OnDestroy() { Templates.Delete(key); } /// /// Process the pointer click event. /// /// Event data. public void OnPointerClick(PointerEventData eventData) { if (eventData.button != PointerEventData.InputButton.Left) { return; } OnClick.Invoke(); } } }