using System; using System.Collections.Generic; using AibisDream.Framework; using AibisDream.Kit; using AibisDream.UI; 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; #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); _defaultView = _dialogViewDict[DialogViewType.StandardBubble]; } private void InitEvent() { // 记录相关 _rmvList.Add( EnumEventSystem.Global.Register(DialogEventEnum.LineStart, AddDialogueLine)); _rmvList.Add( EnumEventSystem.Global.Register(DialogEventEnum.OptionSelected, AddDialogueLine)); _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() { Debug.Log("[事件处理] OnTextShown - 文本显示完成事件"); // 在快速模式下,不设置阻塞,因为快速模式会立即处理 if (DialogController.Instance.quickRunMode) { Debug.Log("[事件处理] OnTextShown - 快速模式,跳过阻塞设置"); return; } // 阻塞部分 - 只在非快速模式下阻塞,确保文本能够显示 _isNextBlocked = true; _block = ActionKit.Delay(blockDuration, () => { Debug.Log("[事件处理] OnTextShown - 阻塞时间结束"); _isNextBlocked = false; _block = null; } ).Start(this); // 自动跳过部分 - 只在非快速模式下执行 if (DialogController.Instance.autoRunMode || _isNextAutoSkip) { Debug.Log("[事件处理] OnTextShown - 设置自动跳过定时器"); _autoNext = ActionKit.Delay(autoSkipDelay, () => { Debug.Log("[事件处理] OnTextShown - 自动跳过定时器触发"); _autoNext = null; NextStep(); }).Start(this); _isNextAutoSkip = false; } } private void OnTextEnd() { Debug.Log("[事件处理] OnTextEnd - 文本结束事件"); // 清理阻塞定时器 if (_block != null) { Debug.Log("[事件处理] OnTextEnd - 清理阻塞定时器"); _block.Deinit(); _block = null; } _isNextBlocked = false; // 清理自动跳过定时器 if (_autoNext != null) { Debug.Log("[事件处理] OnTextEnd - 清理自动跳过定时器"); _autoNext.Deinit(); _autoNext = null; } Debug.Log("[事件处理] OnTextEnd - 清理完成"); } 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) { Debug.Log($"[DialogCanvasManager] ShowLine - 角色对话框类型: {character.dialogViewType}"); Debug.Log($"[DialogCanvasManager] ShowLine - nextStep是否为null: {nextStep == null}"); _isNextAutoSkip = isAutoSkip; // 根据DialogViewType确定在哪个对话框显示 if (character.dialogViewType == DialogViewType.Default) { Debug.Log("[DialogCanvasManager] ShowLine - 使用默认对话框"); 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)) { Debug.Log($"[DialogCanvasManager] ShowLine - 使用指定对话框: {view.GetType().Name}"); 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()}类型对话框不存在"); } Debug.Log($"[DialogCanvasManager] ShowLine - 当前_showingView类型: {_showingView?.GetType().Name}"); } public void ShowOptions(DialogOption[] dialogueOptions) { 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() { _showingView?.HideDialog(); } public bool TrySkipLine(bool isForceSkip = false) { string skipType = isForceSkip ? "强制跳过" : "用户跳过"; Debug.Log($"[跳过操作] {skipType} - 阻塞状态: {_isNextBlocked}"); if (_isNextBlocked) { Debug.Log("[跳过操作] ❌ 被阻塞,返回true"); return true; } bool result = _showingView != null && _showingView.TrySkipLine(isForceSkip); Debug.Log($"[跳过操作] {skipType} - 结果: {(result ? "✅ 成功" : "❌ 失败")}"); return result; } public void NextStep() { Debug.Log("[对话继续] ===== NextStep开始 ====="); Debug.Log($"[对话继续] 当前显示的对话框类型: {_showingView?.GetType().Name}"); // 在快速模式下,不设置延迟隐藏,避免定时器冲突 if (!DialogController.Instance.quickRunMode) { var view = _showingView; _hideDialog = ActionKit.Delay(autoHideDuration, () => { Debug.Log("[对话继续] 延迟隐藏对话框"); _hideDialog = null; view?.HideDialog(); }).Start(this); } else { Debug.Log("[对话继续] 快速模式,跳过延迟隐藏设置"); // 清理可能存在的延迟隐藏定时器 if (_hideDialog != null) { _hideDialog.Deinit(); _hideDialog = null; } } Debug.Log("[对话继续] 调用对话框NextStep"); _showingView?.NextStep(); Debug.Log("[对话继续] ===== NextStep完成 ====="); } public void OnLocalizationChanged(string value) { } 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 RecordPanel RecordPanel => UIManager.Instance.GetPanel(); /// /// 记录对话 /// /// 对话 private void AddDialogueLine(DialogText line) { if (line.actor.dialogViewType == DialogViewType.Task) { return; } RecordPanel.AppendDialogLine(line); } private void CleanDialogHistory() { RecordPanel.ClearDialog(); } 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 } }