#nullable enable using System; using System.Collections.Generic; using System.Threading.Tasks; using AibisDream.Framework; using AibisDream.Utility; using UnityEngine; using Yarn.Unity; namespace AibisDream { public class OptionView : DialoguePresenterBase { [SerializeField] private DefaultOptions defaultOptions; [SerializeField] private CenterOptions centerOptions; [SerializeField] private OnelineOptions onelineOptions; [SerializeField] private DialogViewType defaultViewType = DialogViewType.StandardBubble; private OptionExploreTracker? _tracker; private LineInfo? _pendingOptionPrompt; private void Awake() { _tracker = new OptionExploreTracker(); _tracker.Bind(); } private void OnDestroy() { _tracker?.Unbind(); _tracker = null; } public override YarnTask OnDialogueStartedAsync() { ClearPendingOptionPrompt(); return YarnTask.CompletedTask; } public override YarnTask OnDialogueCompleteAsync() { ClearPendingOptionPrompt(); HideDialog(); return YarnTask.CompletedTask; } public override YarnTask RunLineAsync(LocalizedLine line, LineCancellationToken token) { if (line.IsOptionPromptLine()) { _pendingOptionPrompt = LineInfo.Generate(line); } else { ClearPendingOptionPrompt(); } 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 (nodeName, tags) = DialogController.Instance != null ? DialogController.Instance.GetCurrentNodeContext() : (null, (IReadOnlyList)Array.Empty()); var options = DialogOption.GeneOptions( dialogueOptions, _tracker, nodeName, tags, optionId => optionSelectedSource.TrySetResult(optionId)); var viewType = GetCurrentViewType(options); var optionPrompt = _pendingOptionPrompt; ClearPendingOptionPrompt(); switch (viewType) { case DialogViewType.Default: case DialogViewType.StandardBubble: defaultOptions.ShowOptions(options); break; case DialogViewType.OnelineBox: onelineOptions.ShowOptions(options, optionPrompt?.lineText); if (optionPrompt.HasValue) { EnumEventSystem.Global.Send( DialogEventEnum.LineHistoryAppend, optionPrompt.Value); } 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) { HideDialog(); return null; } } private void ClearPendingOptionPrompt() { _pendingOptionPrompt = null; } private DialogViewType GetCurrentViewType(DialogOption[] options) { var optionViewType = options[0].Character.dialogViewType; if (optionViewType == DialogViewType.Default) { return defaultViewType; } return optionViewType; } public void HideDialog() { defaultOptions.HideOptions(); onelineOptions.HideOptions(); centerOptions.HideOptions(); } } }