#nullable enable using System.Collections.Generic; using System.Threading.Tasks; using AibisDream.Framework; using UnityEngine; using Yarn.Unity; namespace AibisDream { public class OptionView : DialoguePresenterBase { private HashSet _selectedIds = new(); [SerializeField] private DefaultOptions defaultOptions; [SerializeField] private CenterOptions centerOptions; [SerializeField] private OnelineOptions onelineOptions; [SerializeField] private DialogViewType defaultViewType = DialogViewType.StandardBubble; public override YarnTask OnDialogueStartedAsync() { return YarnTask.CompletedTask; } public override YarnTask OnDialogueCompleteAsync() { HideDialog(); return YarnTask.CompletedTask; } public override YarnTask RunLineAsync(LocalizedLine line, LineCancellationToken token) { return YarnTask.CompletedTask; } public void LoadBubbles(BubbleSlotGroupData data) { defaultViewType = data.dialogViewType; } public override async YarnTask RunOptionsAsync(DialogueOption[] dialogueOptions, LineCancellationToken cancellationToken) { EnumEventSystem.Global.Send(DialogEventEnum.OptionShow); var optionSelectedSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var options = DialogOption.GeneOptions(dialogueOptions, optionId => { optionSelectedSource.TrySetResult(optionId); }, _selectedIds); var viewType = GetCurrentViewType(options); switch (viewType) { case DialogViewType.Default: case DialogViewType.StandardBubble: defaultOptions.ShowOptions(options); break; case DialogViewType.OnelineBox: onelineOptions.ShowOptions(options); break; case DialogViewType.CenterOption: centerOptions.ShowOptions(options); break; default: Debug.Log($"选项{options[0].Character.key}没有找到选项框{viewType}"); break; } using var cancellationReg = cancellationToken.NextContentToken.Register(() => { optionSelectedSource.TrySetCanceled(cancellationToken.NextContentToken); }); try { var selectedOptionId = await optionSelectedSource.Task; foreach (var dialogueOption in dialogueOptions) { if (dialogueOption.DialogueOptionID == selectedOptionId) { return dialogueOption; } } return null; } catch (TaskCanceledException) { return null; } } private DialogViewType GetCurrentViewType(DialogOption[] options) { var optionViewType = options[0].Character.dialogViewType; if (optionViewType == DialogViewType.Default) { return defaultViewType; } return optionViewType; } // --------------------------- 生命周期方法 --------------------------- private void OnEnable() { RegisterEvent(); } private void OnDisable() { UnRegisterEvent(); } private void RegisterEvent() { // 进入游戏或者进入下一个Yarn的时候清空 EnumEventSystem.Global.Register(GameLoopEnum.GameStart, ClearSelectedIds); EnumEventSystem.Global.Register(EventEnum.NextYarn, ClearSelectedIds); // 选择选项的时候记录 EnumEventSystem.Global.Register(DialogEventEnum.OptionSelected, RecordSelectedId); } private void UnRegisterEvent() { EnumEventSystem.Global.UnRegister(GameLoopEnum.GameStart, ClearSelectedIds); EnumEventSystem.Global.UnRegister(EventEnum.NextYarn, ClearSelectedIds); EnumEventSystem.Global.UnRegister(DialogEventEnum.OptionSelected, RecordSelectedId); } private void ClearSelectedIds() { _selectedIds.Clear(); } private void RecordSelectedId(LineInfo lineInfo) { _selectedIds.Add(lineInfo.lineId); } public void HideDialog() { defaultOptions.HideOptions(); onelineOptions.HideOptions(); centerOptions.HideOptions(); } } }