using System; using System.Collections.Generic; using System.Text; using AibisDream.Framework; using AibisDream.Kit; using TMPro; using UnityEngine; namespace AibisDream { public class DialogCanvasManager : Singleton, IDialogView { #region 引用 private readonly Dictionary _dialogViewDict = new(); private IDialogView _defaultView; private IDialogView _showingView; private IActionController _autoNext; private IActionController _block; private IActionController _hideDialog; public TMP_Text widthEstimation; #endregion #region 参数 [SerializeField] private float blockDuration; [SerializeField] private float autoSkipDelay; [SerializeField] private float autoHideDuration; private bool _isNextAutoSkip; private bool _isNextBlocked; private bool _isProcessingOptions; // 标记是否正在处理选项 #endregion private readonly List _rmvList = new(); public override void OnSingletonInit() { InitEvent(); } private void Start() { // 默认对话框直接加载 // var box = transform.Find("Dialog Box").GetComponent(); // RegisterDialogView(DialogViewType.OldBox, box); var centerText = transform.Find("Center Text").GetComponent(); RegisterDialogView(DialogViewType.CenterText, centerText); var centerOption = transform.Find("Center Option").GetComponent(); RegisterDialogView(DialogViewType.CenterOption, centerOption); var bubbleGroup = transform.Find("Bubble Group").GetComponent(); RegisterDialogView(DialogViewType.StandardBubble, bubbleGroup); // 注册Screen类型对话框 var screenSystem = FindObjectOfType(); if (screenSystem != null) { RegisterDialogView(DialogViewType.Screen, screenSystem); // 注册Task类型对话框 if (screenSystem.TaskScreen != null) { RegisterDialogView(DialogViewType.Task, screenSystem.TaskScreen); } } // 注册Bubble类型对话框 var textBubbleGroup = FindObjectOfType(); if (textBubbleGroup != null) { RegisterDialogView(DialogViewType.Bubble, textBubbleGroup); } _defaultView = _dialogViewDict[DialogViewType.StandardBubble]; } private void InitEvent() { // 记录相关 _rmvList.Add( EnumEventSystem.Global.Register(DialogEventEnum.LineStart, AddDialogueLine)); _rmvList.Add( EnumEventSystem.Global.Register(DialogEventEnum.OptionSelected, OnOptionSelected)); _rmvList.Add(EnumEventSystem.Global.Register(EventEnum.NextYarn, CleanDialogHistory)); // 文本显示事件 _rmvList.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineShown, OnTextShown)); _rmvList.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineEnd, OnTextEnd)); } private void OnTextShown() { // 阻塞部分 _isNextBlocked = true; _block = ActionKit.Delay(blockDuration, () => { _isNextBlocked = false; _block = null; } ).Start(this); // 自动跳过部分 if (DialogController.Instance.quickRunMode) return; // 检查当前显示的角色是否为Aside,如果是则延迟自动跳过 bool isAsideRole = false; if (_showingView is BubbleGroup bubbleGroup) { // 通过反射或其他方式检查当前bubble的角色 var curBubbleField = typeof(BubbleGroup).GetField("_curBubble", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (curBubbleField != null) { var curBubble = curBubbleField.GetValue(bubbleGroup) as Bubble; isAsideRole = curBubble != null && curBubble.role == ActorRole.Aside; } } if (DialogController.Instance.autoRunMode || _isNextAutoSkip) { float skipDelay = isAsideRole ? autoSkipDelay * 2f : autoSkipDelay; // Aside角色延迟更长时间 _autoNext = ActionKit.Delay(skipDelay, () => { _autoNext = null; NextStep(); }).Start(this); _isNextAutoSkip = false; } } private void OnTextEnd() { _block?.Deinit(); _block = null; _isNextBlocked = false; _autoNext?.Deinit(); _autoNext = null; } private void OnOptionSelected(DialogText dialogText) { _isProcessingOptions = false; // 清除处理选项的标志 AddDialogueLine(dialogText); // 记录选项 } public override void OnSingletonDestroy() { // 销毁前处理事件 _rmvList.ForEach(item => item.UnRegister()); } #region 对话结束后隐藏 private void OnEnable() { DialogController.OnDialogueComplete += HideDialog; } private void OnDisable() { DialogController.OnDialogueComplete -= HideDialog; } #endregion #region 对话框相关处理 /// /// 注册对话框 /// /// /// public void RegisterDialogView(DialogViewType viewType, IDialogView dialogView) { _dialogViewDict.Add(viewType, dialogView); } /// /// 注销对话框 /// /// public void UnregisterDialogView(DialogViewType viewType) { _dialogViewDict.Remove(viewType); } #endregion #region 对话框接口 public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false) { _isNextAutoSkip = isAutoSkip; // 根据DialogViewType确定在哪个对话框显示 if (character.dialogViewType == DialogViewType.Default) { if (_showingView != _defaultView) { _showingView?.HideDialog(); } else { _hideDialog?.Deinit(); _hideDialog = null; } _showingView = _defaultView; _showingView.ShowLine(dialogLine, character, nextStep, lineId, isAutoSkip); } else if (_dialogViewDict.TryGetValue(character.dialogViewType, out var view)) { if (_showingView != view) { _showingView?.HideDialog(); } else { _hideDialog?.Deinit(); _hideDialog = null; } _showingView = view; // 对于指定了对话框的,就在指定对话框显示 view.ShowLine(dialogLine, character, nextStep, lineId, isAutoSkip); } else { Debug.Log($"{character.dialogViewType.ToString()}类型对话框不存在"); } } public void ShowOptions(DialogOption[] dialogueOptions) { _isProcessingOptions = true; // 设置正在处理选项的标志 var viewType = dialogueOptions[0].Character.dialogViewType; // 根据状况选择不同的选择框 if (viewType == DialogViewType.Default) { if (_showingView != _defaultView) { _showingView?.HideDialog(); } else { _hideDialog?.Deinit(); _hideDialog = null; } _showingView = _defaultView; _showingView.ShowOptions(dialogueOptions); } else if(_dialogViewDict.TryGetValue(viewType, out var view)) { if (_showingView != view) { _showingView?.HideDialog(); } else { _hideDialog?.Deinit(); _hideDialog = null; } _showingView = view; _showingView.ShowOptions(dialogueOptions); } } public void HideDialog() { _isProcessingOptions = false; // 清除处理选项的标志 _showingView?.HideDialog(); } public bool TrySkipLine(bool isForceSkip = false) { if (_isNextBlocked) { return true; } return _showingView != null && _showingView.TrySkipLine(isForceSkip); } public void NextStep() { _isProcessingOptions = false; // 清除处理选项的标志 var view = _showingView; _hideDialog = ActionKit.Delay(autoHideDuration, () => { _hideDialog = null; view.HideDialog(); }).Start(this); _showingView?.NextStep(); } public void OnLocalizationChanged(string value) { } /// /// 检查当前是否有活动的选项显示 /// /// 是否有活动选项 public bool HasActiveOptions() { // 如果正在处理选项,返回true if (_isProcessingOptions) { return true; } // 检查当前显示的对话框是否有选项 if (_showingView != null) { // 通过反射检查当前对话框是否有选项显示 var hasOptionsMethod = _showingView.GetType().GetMethod("HasActiveOptions", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); if (hasOptionsMethod != null) { return (bool)hasOptionsMethod.Invoke(_showingView, null); } } return false; } public void SwitchDialogView(DialogViewType dialogViewType) { if (_dialogViewDict.TryGetValue(dialogViewType, out var view)) { _defaultView?.HideDialog(); _showingView?.HideDialog(); _defaultView = view; } else { Debug.Log($"{dialogViewType.ToString()}类型对话框不存在"); } } #endregion #region 对话回顾 private StringBuilder DialogRecord => UIManager.Instance.GetPanel().recordStr; /// /// 记录对话 /// /// 对话 private void AddDialogueLine(DialogText line) { DialogRecord.Append(line.GetDialogText()); } private void CleanDialogHistory() { DialogRecord.Clear(); } public void CloseCanvas() { gameObject.SetActive(false); } public void OpenCanvas() { gameObject.SetActive(true); } #endregion public float EstimateTextWidth(string text, float fontSize) { widthEstimation.fontSize = fontSize; widthEstimation.text = text; widthEstimation.ForceMeshUpdate(); return widthEstimation.preferredWidth; } } public enum DialogViewType { Default, Bubble, OldBox, Screen, CenterText, CenterOption, Task, StandardBubble } }