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; #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() { // 阻塞部分 _isNextBlocked = true; _block = ActionKit.Delay(blockDuration, () => { _isNextBlocked = false; _block = null; } ).Start(this); // 自动跳过部分 if (DialogController.Instance.quickRunMode) return; if (DialogController.Instance.autoRunMode || _isNextAutoSkip) { _autoNext = ActionKit.Delay(autoSkipDelay, () => { _autoNext = null; NextStep(); }).Start(this); _isNextAutoSkip = false; } } private void OnTextEnd() { _block?.Deinit(); _block = null; _isNextBlocked = false; _autoNext?.Deinit(); _autoNext = null; } 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) { 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) { if (_isNextBlocked) { return true; } return _showingView != null && _showingView.TrySkipLine(isForceSkip); } public void NextStep() { var view = _showingView; _hideDialog = ActionKit.Delay(autoHideDuration, () => { _hideDialog = null; view.HideDialog(); }).Start(this); _showingView?.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 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 } }