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 : Singleton, ILineView { [SerializeField] private TMP_Text widthEstimation; [SerializeField] private CenterBubble centerBubble; private Dictionary _bubbleDict = new(); private BubbleFactory _bubbleFactory; private CancellationTokenSource _autoHideToken; #region 生命周期 public override void OnSingletonInit() { // 工厂 _bubbleFactory = new BubbleFactory(transform); } 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(); } centerBubble.Hide(); } private void HideDialog(IBubble activeBubble) { foreach (var textBubble in _bubbleDict.Values.SelectMany(inner => inner)) { if (activeBubble != (IBubble)textBubble) { textBubble.Hide(); } } if (activeBubble != (IBubble)centerBubble) { centerBubble.Hide(); } } private bool TryGetBubble(ActorRole role, int idx, out IBubble bubble) { if (role == ActorRole.Center) { bubble = centerBubble; return true; } if (_bubbleDict.TryGetValue(role, out var bubbles)) { bubble = bubbles.FirstOrDefault(item => item.Idx == idx); return bubble != null; } bubble = null; return false; } #endregion } }