using System; using System.Collections.Generic; using System.Threading; using TMPro; using UnityEngine; namespace Cryville.Crtr.UI { public class Dialog : MonoBehaviour { static Dialog _instance; [SerializeField] CanvasGroup m_group; [SerializeField] AnimationCurve m_fadeCurve; [SerializeField] TextMeshProUGUI m_msgText; [SerializeField] TextMeshProUGUI m_button0Text; [SerializeField] TextMeshProUGUI m_button1Text; [SerializeField] GameObject m_button1; float _fadeDuration; static readonly Queue _queue = new(); struct DialogEntry { public Action callback; public string message; public string action0; public string action1; } void Awake() { _instance = this; _fadeDuration = m_fadeCurve[m_fadeCurve.length - 1].time; } float _timer; DialogEntry? _cur; static bool _suppressed; void Update() { if (_cur == null) { if (_timer > 0) { _timer -= Time.deltaTime; if (_timer < 0) { _timer = 0; m_group.gameObject.SetActive(false); } m_group.alpha = m_fadeCurve.Evaluate(_timer); } if (_queue.Count > 0 && !_suppressed) { m_group.gameObject.SetActive(true); _cur = _queue.Dequeue(); m_msgText.text = _cur.Value.message; m_button0Text.text = _cur.Value.action0; m_button1Text.text = _cur.Value.action1; m_button1.SetActive(_cur.Value.action1 != null); } } else { if (_timer < _fadeDuration) { _timer += Time.deltaTime; if (_timer > _fadeDuration) _timer = _fadeDuration; m_group.alpha = m_fadeCurve.Evaluate(_timer); } } } public void OnButton(int id) { if (_cur == null) return; _cur.Value.callback?.Invoke(id); _cur = null; } public static void Suppress() { _suppressed = true; if (_instance._cur != null) { _queue.Enqueue(_instance._cur.Value); _instance._cur = null; } } public static void Release() { _suppressed = false; } public static void Show(Action callback, string message, string action0 = "OK", string action1 = null) { _queue.Enqueue(new DialogEntry { callback = callback, message = message, action0 = action0, action1 = action1 }); } public static int ShowAndWait(string message, string action0 = "OK", string action1 = null) { using var ev = new AutoResetEvent(false); int result = 0; _queue.Enqueue(new DialogEntry { callback = r => { result = r; ev.Set(); }, message = message, action0 = action0, action1 = action1, }); ev.WaitOne(); return result; } } }