BITFALL/Assets/Artists/Scripts/UX/UXDialogue.cs

139 lines
3.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using BITKit;
using BITKit.Entities;
using BITKit.Entities.Player;
using Cysharp.Threading.Tasks;
using JetBrains.Annotations;
using NodeCanvas.DialogueTrees;
using UnityEngine;
using UnityEngine.InputSystem;
namespace BITFALL.UX
{
/// <summary>
/// 对话组件,基于NodeCanvas.DialogueTrees
/// </summary>
public class UXDialogue : MonoBehaviour
{
[SerializeReference,SubclassSelector] private IPlayerService playerService;
[SerializeField] private UXBuilder dialogueBuilder;
[SerializeField] private InputActionReference[] choosesActions;
private readonly ValidHandle allowBackground = new();
private readonly List<int> _dialogueIds = new();
[Inject] private InputActionGroup _inputActionGroup;
[CanBeNull] private MultipleChoiceRequestInfo _multipleChoiceRequestInfo;
private void Start()
{
allowBackground.AddListener(dialogueBuilder.VisualElement.SetActive);
allowBackground.Invoke();
playerService.OnPlayerInitialized += OnPlayerInitialized;
playerService.OnPlayerDisposed += OnPlayerDisposed;
DialogueTree.OnSubtitlesRequest += OnSubtitlesRequest;
DialogueTree.OnMultipleChoiceRequest += OnMultipleChoiceRequest;
destroyCancellationToken.Register(() =>
{
playerService.OnPlayerInitialized -= OnPlayerInitialized;
DialogueTree.OnSubtitlesRequest -= OnSubtitlesRequest;
DialogueTree.OnMultipleChoiceRequest -= OnMultipleChoiceRequest;
playerService.OnPlayerDisposed -= OnPlayerDisposed;
});
}
private void OnPlayerDisposed(Entity obj)
{
foreach (var action in choosesActions)
{
UXOnScreenPrompts.Release(action.GetKeyMap());
}
}
private void OnPlayerInitialized(Entity obj)
{
obj.Inject(this);
for (var i = 0; i < choosesActions.Length; i++)
{
var action = choosesActions[i];
var index = i;
_inputActionGroup.RegisterCallback(action, OnAction);
continue;
void OnAction(InputAction.CallbackContext context)
{
if (_multipleChoiceRequestInfo is null) return;
_multipleChoiceRequestInfo.SelectOption?.Invoke(index);
_multipleChoiceRequestInfo = null;
}
}
}
private void OnMultipleChoiceRequest(MultipleChoiceRequestInfo obj)
{
_multipleChoiceRequestInfo = obj;
foreach (var (statement,index) in obj.options)
{
UXOnScreenPrompts.Get(choosesActions[index].GetKeyMap(),statement.text);
obj.SelectOption+=i =>
{
UXOnScreenPrompts.Release(choosesActions[index].GetKeyMap());
};
}
}
private async void OnSubtitlesRequest(SubtitlesRequestInfo obj)
{
var id = obj.GetHashCode();
_dialogueIds.Add(id);
dialogueBuilder.VisualElement.SetActive(true);
var container = dialogueBuilder.BuildAsContainer();
container.contextLabel.text = $"{obj.actor.name}:{obj.statement}";
try
{
if (double.TryParse( obj.statement.meta,out var duration))
{
await Task.Delay(TimeSpan.FromSeconds(duration), destroyCancellationToken);
}
else
{
await Task.Delay(5000, destroyCancellationToken);
}
obj.Continue.Invoke();
await Task.Delay(5000, destroyCancellationToken);
container.visualElement.AddToClassList("dispose");
await Task.Delay(1000, destroyCancellationToken);
container.visualElement.RemoveFromHierarchy();
}
catch (OperationCanceledException)
{
obj.Continue.Invoke();
}
_dialogueIds.Remove(id);
}
private void Update()
{
allowBackground.SetElements(this, _dialogueIds.Count is not 0);
}
}
}