Files
aibis-dream/Assets/Scripts/UI/DialogUI/DialogCanvasManager.cs
T
2025-09-16 17:13:21 +08:00

390 lines
13 KiB
C#

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<DialogCanvasManager>, IDialogView
{
#region 引用
private readonly Dictionary<DialogViewType, IDialogView> _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<IUnRegister> _rmvList = new();
public override void OnSingletonInit()
{
InitEvent();
}
private void Start()
{
// 默认对话框直接加载
// var box = transform.Find("Dialog Box").GetComponent<IDialogView>();
// RegisterDialogView(DialogViewType.OldBox, box);
var centerText = transform.Find("Center Text").GetComponent<IDialogView>();
RegisterDialogView(DialogViewType.CenterText, centerText);
var centerOption = transform.Find("Center Option").GetComponent<IDialogView>();
RegisterDialogView(DialogViewType.CenterOption, centerOption);
var bubbleGroup = transform.Find("Bubble Group").GetComponent<IDialogView>();
RegisterDialogView(DialogViewType.StandardBubble, bubbleGroup);
_defaultView = _dialogViewDict[DialogViewType.StandardBubble];
}
private void InitEvent()
{
// 记录相关
_rmvList.Add(
EnumEventSystem.Global.Register<DialogEventEnum, DialogText>(DialogEventEnum.LineStart,
AddDialogueLine));
_rmvList.Add(
EnumEventSystem.Global.Register<DialogEventEnum, DialogText>(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 对话框相关处理
/// <summary>
/// 注册对话框
/// </summary>
/// <param name="viewType"></param>
/// <param name="dialogView"></param>
public void RegisterDialogView(DialogViewType viewType, IDialogView dialogView)
{
_dialogViewDict.Add(viewType, dialogView);
}
/// <summary>
/// 注销对话框
/// </summary>
/// <param name="viewType"></param>
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<RecordPanel>();
/// <summary>
/// 记录对话
/// </summary>
/// <param name="line">对话</param>
private void AddDialogueLine(DialogText line)
{
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
}
}