using TMPro; using UnityEngine; using UnityEngine.UI; namespace BriarQueen.UI.Components { [ExecuteAlways] public class ScrollableTextBox : MonoBehaviour { [SerializeField] private TextMeshProUGUI _text; [SerializeField] private RectTransform _content; [SerializeField] private BriarQueen.UI.Menus.VerticalScrollbar _scrollbar; private RectTransform _textRect; private LayoutElement _layoutElement; private void Awake() { Init(); } private void OnValidate() { #if UNITY_EDITOR UnityEditor.EditorApplication.delayCall += () => { if (this == null) return; Init(); if (_text != null && !string.IsNullOrEmpty(_text.text)) ApplyTextHeight(); }; #endif } private void Init() { if (_text != null) { _textRect = _text.GetComponent(); _layoutElement = _text.GetComponent(); if (_layoutElement == null) _layoutElement = _text.gameObject.AddComponent(); } } private void ApplyTextHeight() { _text.ForceMeshUpdate(); var height = _text.preferredHeight; if (_layoutElement != null) _layoutElement.preferredHeight = height; if (_textRect != null) { var delta = _textRect.sizeDelta; delta.y = height; _textRect.sizeDelta = delta; } if (_content != null) { Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate(_content); } } public void SetText(string content) { if (_text == null) return; _text.text = content; _text.ForceMeshUpdate(); var height = _text.preferredHeight; if (_layoutElement != null) _layoutElement.preferredHeight = height; if (_textRect != null) { var delta = _textRect.sizeDelta; delta.y = height; _textRect.sizeDelta = delta; } // Also resize Content to match so scrollbar measures correctly if (_content != null) { var delta = _content.sizeDelta; delta.y = height; _content.sizeDelta = delta; var pos = _content.anchoredPosition; pos.y = 0f; _content.anchoredPosition = pos; } if (Application.isPlaying) StartCoroutine(RebuildNextFrame()); else _scrollbar?.Rebuild(); } private System.Collections.IEnumerator RebuildNextFrame() { yield return null; Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate(_content); yield return null; _scrollbar?.Rebuild(); _scrollbar?.SetNormalized(1f); } public void Clear() { if (_text == null) return; _text.text = string.Empty; if (_layoutElement != null) _layoutElement.preferredHeight = 0f; if (_textRect != null) { var sd = _textRect.sizeDelta; sd.y = 0f; _textRect.sizeDelta = sd; } if (_content != null) { var pos = _content.anchoredPosition; pos.y = 0f; _content.anchoredPosition = pos; } _scrollbar?.Rebuild(); } public void ScrollToTop() => _scrollbar?.SetNormalized(1f); public void ScrollToBottom() => _scrollbar?.SetNormalized(0f); } }