233 lines
7.1 KiB
C#
233 lines
7.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Net.Http;
|
|
using BITKit;
|
|
using BITKit.UX;
|
|
using Cysharp.Threading.Tasks;
|
|
using Microsoft.Extensions.Logging;
|
|
using Net.BITKit;
|
|
using Net.BITKit.Chat;
|
|
using Net.Project.B.UX;
|
|
using Newtonsoft.Json;
|
|
using Project.B.Player;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.UIElements;
|
|
using Object = System.Object;
|
|
|
|
namespace Net.Project.B.Chat
|
|
{
|
|
public class UXChat<TPanel> : UIToolkitSubPanel<TPanel>,IDisposable, IUXChat where TPanel : IUXPanel
|
|
{
|
|
private readonly IChatService _chatService;
|
|
private readonly IUXKeyMap<InputAction> _uxKeyMap;
|
|
private readonly ILogger<UXChat<TPanel>> _logger;
|
|
|
|
|
|
[UXBindPath("chat-field-container")]
|
|
private VisualElement _chatFieldContainer;
|
|
[UXBindPath("chat-container")]
|
|
private VisualElement _chatContainer;
|
|
[UXBindPath("chat-field")]
|
|
private TextField _chatField;
|
|
[UXBindPath("chat-scroll")]
|
|
private ScrollView _chatScroll;
|
|
[UXBindPath("voice-button")]
|
|
private Button _voiceButton;
|
|
|
|
private readonly ValidHandle _isEnabled = new();
|
|
|
|
private string _currentDevice;
|
|
private AudioClip _recordClip;
|
|
|
|
private UniTaskCompletionSource _waitVoice;
|
|
|
|
|
|
public UXChat(IServiceProvider serviceProvider, IChatService chatService, IUXKeyMap<InputAction> uxKeyMap, ILogger<UXChat<TPanel>> logger) : base(serviceProvider)
|
|
{
|
|
_chatService = chatService;
|
|
_uxKeyMap = uxKeyMap;
|
|
_logger = logger;
|
|
|
|
_chatService.OnMessageReceived += OnMessageReceived;
|
|
|
|
}
|
|
|
|
private async void OnVoice()
|
|
{
|
|
_chatField.SetEnabled(false);
|
|
|
|
_currentDevice = Microphone.devices[0];
|
|
|
|
_logger.LogInformation("开始录音");
|
|
|
|
_recordClip = Microphone.Start(_currentDevice, false, 10, 16000);
|
|
|
|
try
|
|
{
|
|
await _waitVoice.Task;
|
|
|
|
_logger.LogInformation("录音完成");
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
_logger.LogInformation("录音取消");
|
|
return;
|
|
}
|
|
finally
|
|
{
|
|
Microphone.End(_currentDevice);
|
|
|
|
_waitVoice = null;
|
|
}
|
|
|
|
|
|
var newGo = new GameObject();
|
|
var audioSource =
|
|
newGo.AddComponent<AudioSource>();
|
|
|
|
audioSource.clip = _recordClip;
|
|
|
|
audioSource.Play();
|
|
|
|
var wav = AudioClipUtils.AudioClipToWavBytes(_recordClip);
|
|
|
|
await UniTask.Delay(TimeSpan.FromSeconds(_recordClip.length));
|
|
if (audioSource)
|
|
{
|
|
UnityEngine.Object.Destroy(newGo);
|
|
}
|
|
|
|
using var httpClient = new HttpClient();
|
|
var responseMessage = await httpClient.PostAsync(@"http://localhost:5062/api/vosk/gettext?modelName=vosk-model-en-us-0.42-gigaspeech", new ByteArrayContent(wav));
|
|
var message = await responseMessage.Content.ReadAsStringAsync();
|
|
|
|
_chatField.SetEnabled(true);
|
|
|
|
var data = JsonConvert.DeserializeObject<dynamic>(message);
|
|
|
|
Debug.Log(message);
|
|
|
|
_chatField.value = data.text;
|
|
}
|
|
|
|
protected override void OnInitiated()
|
|
{
|
|
base.OnInitiated();
|
|
_chatContainer.Clear();
|
|
|
|
if (Panel is UIToolKitPanel panel)
|
|
{
|
|
panel.InputActionGroup.RegisterCallback(_uxKeyMap.ChatKey, OnChat);
|
|
panel.OnExit+=()=>
|
|
{
|
|
_isEnabled.SetElements(this,false);
|
|
|
|
};
|
|
}
|
|
|
|
_isEnabled.AddListener(enabled =>
|
|
{
|
|
_chatFieldContainer.SetActive(enabled);
|
|
_voiceButton.SetActive(enabled);
|
|
if (enabled)
|
|
{
|
|
BITInputSystem.AllowInput.AddDisableElements(this);
|
|
BITAppForUnity.AllowCursor.AddElement(this);
|
|
_chatField.SetActive(true);
|
|
_chatField.focusable = true;
|
|
|
|
_chatField.schedule.Execute(_chatField.Focus).ExecuteLater(1);
|
|
_chatScroll.ScrollToBottom();
|
|
|
|
_chatScroll.focusable = true;
|
|
|
|
}
|
|
else
|
|
{
|
|
_waitVoice?.TrySetCanceled();
|
|
|
|
BITAppForUnity.AllowCursor.RemoveElement(this);
|
|
BITInputSystem.AllowInput.RemoveDisableElements(this);
|
|
|
|
_chatField.focusable = false;
|
|
_chatField.schedule.Execute(()=>
|
|
{
|
|
_chatScroll.ScrollToBottom();
|
|
_chatField.SetActive(false);
|
|
_chatField.SetValueWithoutNotify(string.Empty);
|
|
_chatField.Blur();
|
|
}).ExecuteLater(1);
|
|
|
|
_chatScroll.focusable = false;
|
|
}
|
|
_chatScroll.Blur();
|
|
});
|
|
_isEnabled.Invoke();
|
|
|
|
_chatField.RegisterCallback<KeyDownEvent>(OnKeyDown);
|
|
_chatField.BlinkingCursor();
|
|
|
|
_voiceButton.clicked += ToggleVoice;
|
|
}
|
|
|
|
private void ToggleVoice()
|
|
{
|
|
if (_waitVoice is not null)
|
|
{
|
|
_waitVoice.TrySetResult();
|
|
}
|
|
else
|
|
{
|
|
_waitVoice = new();
|
|
|
|
OnVoice();
|
|
}
|
|
}
|
|
|
|
private void OnKeyDown(KeyDownEvent keyDownEvent)
|
|
{
|
|
switch (keyDownEvent.keyCode)
|
|
{
|
|
case KeyCode.Return:
|
|
if (string.IsNullOrEmpty(_chatField.value) is false)
|
|
{
|
|
_chatService.SendMessage(new ChatMessage()
|
|
{
|
|
FromUserId = Environment.UserName,
|
|
ToUserId = "World",
|
|
Content = _chatField.value
|
|
});
|
|
_chatField.value = string.Empty;
|
|
|
|
keyDownEvent.StopPropagation();
|
|
keyDownEvent.PreventDefault();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void OnChat(InputAction.CallbackContext obj)
|
|
{
|
|
if (obj.JustPressed() is false)return;
|
|
|
|
_isEnabled.SetElements(this,!_isEnabled.Allow);
|
|
}
|
|
|
|
private void OnMessageReceived(ChatMessage obj)
|
|
{
|
|
var label = _chatContainer.Create<Label>();
|
|
label.text = $"<color=yellow>{obj.FromUserId}:</color>{obj.Content}";
|
|
|
|
_chatScroll.ScrollToBottomAutomatic();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
}
|