144 lines
4.0 KiB
C#
144 lines
4.0 KiB
C#
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<RectTransform>();
|
|
_layoutElement = _text.GetComponent<LayoutElement>();
|
|
|
|
if (_layoutElement == null)
|
|
_layoutElement = _text.gameObject.AddComponent<LayoutElement>();
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
} |