using System; using System.Threading; using System.Threading.Tasks; using Febucci.UI.Core; using TMPro; using UnityEngine; using UnityEngine.UI; using AibisDream.Framework; using AibisDream.Utility; namespace AibisDream { public class OnelineBox : MonoBehaviour, ILineView { [SerializeField] private TypewriterCore content; [SerializeField] private GameObject box; [Header("排版参数")] [SerializeField] private int maxWidth = 800; [SerializeField] private int minWidth = 10; private LayoutElement _contentLayoutElement; private TMP_Text _contentText; private RectTransform _rectTransform; private CancellationTokenSource _autoHideToken; private event Action OnTextShowed; private bool _isInitialized; // ---------------------------- 显示逻辑 ---------------------------- public void RunLine(LineSyncToken syncToken) { // 先中断结束事件 _autoHideToken?.Cancel(); _autoHideToken = null; // 注册事件 OnTextShowed += syncToken.TextShown; syncToken.SkipTextAnima += () => content.SkipTypewriter(); syncToken.OnAdvance += AfterAdvance; // 播放文字 content.TextAnimator.SetText(string.Empty); var lineText = GetOneLineText(syncToken.lineInfo); box.SetActive(true); HandleLayout(lineText); content.ShowText(lineText); syncToken.TextStart(); } private string GetOneLineText(LineInfo lineInfo) { if (string.IsNullOrEmpty(lineInfo.character.GetActorName())) { return lineInfo.lineText; } return $"{lineInfo.character.GetActorName()}: {lineInfo.lineText}"; } private void HandleLayout(string line) { if (!_isInitialized) { InitRefs(); } // 去除富文本标签后计算宽度 var width = DialogUIManager.Instance.EstimateTextWidth(line.RemoveRichTextTags(), _contentText.fontSize); if (width > maxWidth) { _contentLayoutElement.preferredWidth = maxWidth; } else { _contentLayoutElement.preferredWidth = -1; // 自适应 } _contentLayoutElement.minWidth = minWidth; LayoutRebuilder.ForceRebuildLayoutImmediate(_rectTransform); } private async void AfterAdvance() { _autoHideToken = new CancellationTokenSource(); try { await Task.Delay(ConstRef.AutoHideDelay, _autoHideToken.Token); HideDialog(); } catch (TaskCanceledException) { // 忽略取消 } } public void HideDialog() { box.SetActive(false); } // ---------------------------- 生命周期 ---------------------------- private void Awake() { box.SetActive(false); InitRefs(); } private void InitRefs() { if (_isInitialized) return; _rectTransform = box.GetComponent(); _contentText = content.GetComponent(); _contentLayoutElement = content.GetComponent(); _isInitialized = true; } private void Start() { DialogUIManager.Instance.RegisterScreenView(DialogViewType.OnelineBox, this); RegisterEvents(); } private void OnDestroy() { DialogUIManager.Instance.UnRegisterScreenView(DialogViewType.OnelineBox); UnregisterEvents(); OnTextShowed = null; } private void RegisterEvents() { // 全局事件 EnumEventSystem.Global.Register(DialogEventEnum.OptionShow, OnOptionShow); // 文本事件 content.onTextShowed.AddListener(TextShowed); } private void UnregisterEvents() { // 全局事件 EnumEventSystem.Global.UnRegister(DialogEventEnum.OptionShow, OnOptionShow); // 文本事件 content.onTextShowed.RemoveListener(TextShowed); } private void TextShowed() { OnTextShowed?.Invoke(); OnTextShowed = null; } private void OnOptionShow() { _autoHideToken?.Cancel(); _autoHideToken = null; HideDialog(); } } }