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 UnityEngine; namespace AibisDream { public class BubbleGroup : MonoBehaviour, ILineView { private Dictionary _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()); #if UNITY_EDITOR var roleSummary = string.Join(", ", _bubbleDict.Select(kv => $"{kv.Key}({kv.Value.Length})")); Debug.Log($"[BubbleGroup] 已加载 {groupData.dialogViewType}: {roleSummary}", this); #endif } #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(); } } 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 } }