147 lines
4.4 KiB
C#
147 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using AibisDream.Framework;
|
|
using AibisDream.Kit;
|
|
using AibisDream.Utility;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
|
|
namespace AibisDream
|
|
{
|
|
public class BubbleGroup : MonoBehaviour, ILineView
|
|
{
|
|
[SerializeField] private TMP_Text widthEstimation;
|
|
|
|
private Dictionary<ActorRole, Bubble[]> _bubbleDict = new();
|
|
private BubbleFactory _bubbleFactory;
|
|
private CancellationTokenSource _autoHideToken;
|
|
|
|
#region 生命周期
|
|
|
|
private void Start()
|
|
{
|
|
_bubbleFactory = new BubbleFactory(this);
|
|
EnumEventSystem.Global.Register(DialogEventEnum.OptionShow, OnOptionShow);
|
|
DialogUIManager.Instance.RegisterScreenView(DialogViewType.StandardBubble, this);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
EnumEventSystem.Global.UnRegister(DialogEventEnum.OptionShow, OnOptionShow);
|
|
DialogUIManager.Instance.UnRegisterScreenView(DialogViewType.StandardBubble);
|
|
}
|
|
|
|
private void OnOptionShow()
|
|
{
|
|
_autoHideToken?.Cancel();
|
|
_autoHideToken = null;
|
|
|
|
HideDialog();
|
|
}
|
|
|
|
public void LoadBubbles(BubbleSlotGroupData groupData)
|
|
{
|
|
// 回收旧泡泡
|
|
foreach (var oldBubble in _bubbleDict.Values.SelectMany(item => item))
|
|
{
|
|
oldBubble.Dispose();
|
|
}
|
|
|
|
// 加载新泡泡
|
|
_bubbleDict = groupData.bubbleSlots
|
|
.Select(item => _bubbleFactory.Create(item))
|
|
.GroupBy(item => item.Role)
|
|
.ToDictionary(group => group.Key, group => group.ToArray());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 新对话框功能实现
|
|
|
|
public void RunLine(LineSyncToken syncToken)
|
|
{
|
|
// 先中断原来的事件
|
|
_autoHideToken?.Cancel();
|
|
_autoHideToken = null;
|
|
|
|
var character = syncToken.lineInfo.character;
|
|
|
|
if (TryGetBubble(character.role, character.bubbleIdx, out var bubble))
|
|
{
|
|
// 注册事件
|
|
bubble.OnLineShown += syncToken.TextShown;
|
|
syncToken.SkipTextAnima += () => bubble.SkipLine();
|
|
syncToken.OnAdvance += AfterAdvance;
|
|
// 播放文字
|
|
bubble.ShowActorName(character);
|
|
bubble.ShowLine(syncToken.lineInfo.lineText);
|
|
syncToken.TextStart();
|
|
// 将非选定的Bubble隐藏
|
|
HideDialog(bubble);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"{character.GetActorName()}的Role {character.role}没有对应Bubble");
|
|
HideDialog();
|
|
}
|
|
}
|
|
|
|
public float EstimateTextWidth(string text, float fontSize)
|
|
{
|
|
widthEstimation.fontSize = fontSize;
|
|
widthEstimation.text = text;
|
|
widthEstimation.ForceMeshUpdate();
|
|
return widthEstimation.preferredWidth;
|
|
}
|
|
|
|
private async void AfterAdvance()
|
|
{
|
|
_autoHideToken = new CancellationTokenSource();
|
|
try
|
|
{
|
|
await Task.Delay(ConstRef.AutoHideDelay, _autoHideToken.Token);
|
|
HideDialog();
|
|
}
|
|
catch (TaskCanceledException)
|
|
{
|
|
// 忽略取消
|
|
}
|
|
}
|
|
|
|
public void HideDialog()
|
|
{
|
|
foreach (var textBubble in _bubbleDict.Values.SelectMany(inner => inner))
|
|
{
|
|
textBubble.Hide();
|
|
}
|
|
}
|
|
|
|
private void HideDialog(IBubble activeBubble)
|
|
{
|
|
foreach (var textBubble in _bubbleDict.Values.SelectMany(inner => inner))
|
|
{
|
|
if (activeBubble != (IBubble)textBubble)
|
|
{
|
|
textBubble.Hide();
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool TryGetBubble(ActorRole role, int idx, out IBubble bubble)
|
|
{
|
|
if (_bubbleDict.TryGetValue(role, out var bubbles))
|
|
{
|
|
bubble = bubbles.FirstOrDefault(item => item.Idx == idx);
|
|
return bubble != null;
|
|
}
|
|
|
|
bubble = null;
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |