454 lines
14 KiB
C#
454 lines
14 KiB
C#
using DG.Tweening;
|
|
using SuperScrollView.AI;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Text.RegularExpressions;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
public class ChatUI : MonoBehaviour
|
|
{
|
|
public LoopListView2 mLoopListView;
|
|
|
|
/// <summary>
|
|
/// 发送信息按钮
|
|
/// </summary>
|
|
[SerializeField] private Button m_SendBtn;
|
|
|
|
/// <summary>
|
|
/// 输入的信息
|
|
/// </summary>
|
|
[SerializeField] public InputField m_InputWord;
|
|
|
|
[SerializeField] private Button hideDialogue;
|
|
[SerializeField] public Transform p1;
|
|
[SerializeField] public Transform p2;
|
|
[SerializeField] private GameObject chatuiObj;
|
|
[SerializeField] private AudioSource audioSource;
|
|
public AudioClip welcomeAudioCilp;
|
|
public Animator IP_Animator;
|
|
public static ChatUI Instance { get; private set; }
|
|
public GameObject prefab_h;
|
|
public GameObject prefab_v;
|
|
public GameObject prefab_h_next;
|
|
public GameObject prefab_v_next;
|
|
private float recordingSendCountdownTime = 1f;
|
|
private float recordingSendCurrentTime;
|
|
private float wakeUpCountdownTime = 5f;
|
|
private float wakeUpCurrentTime;
|
|
private Coroutine coroutine;
|
|
public XunFeiWakeup xunFeiWakeup;//语音唤醒
|
|
private bool chatUIOpen;
|
|
private string speakTxt;
|
|
public string SpeakTxt
|
|
{
|
|
get
|
|
{
|
|
return speakTxt;
|
|
}
|
|
set
|
|
{
|
|
recordingSendCurrentTime = recordingSendCountdownTime;
|
|
wakeUpCurrentTime = wakeUpCountdownTime;
|
|
speakTxt = value;
|
|
}
|
|
}
|
|
private bool thinking;
|
|
public bool Thinking
|
|
{
|
|
get { return thinking; }
|
|
set
|
|
{
|
|
if (value)
|
|
{
|
|
GenChatTxt("思考中...");
|
|
}
|
|
thinking = value;
|
|
}
|
|
}
|
|
//private bool typing;
|
|
//public bool Typing
|
|
//{
|
|
// get { return typing; }
|
|
// set
|
|
// {
|
|
// typing = value;
|
|
// }
|
|
//}
|
|
private bool closed;
|
|
Action action;
|
|
private void Awake()
|
|
{
|
|
Instance = this;
|
|
DontDestroyOnLoad(this);
|
|
hideDialogue.onClick.AddListener(HideDialogue);
|
|
xunFeiWakeup.callBack = Listener;
|
|
|
|
}
|
|
void Start()
|
|
{
|
|
mLoopListView.InitListView(ChatMsgDataSourceMgr.Get.TotalItemCount, OnGetItemByIndex);
|
|
|
|
m_SendBtn.onClick.AddListener(SendData);
|
|
#if UNITY_WEBGL
|
|
m_InputWord.gameObject.AddComponent<WebGLSupport.WebGLInput>();
|
|
#endif
|
|
}
|
|
|
|
#region 语音合成
|
|
private void Update()
|
|
{
|
|
//回车发送
|
|
if (
|
|
(Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
|
|
&& !m_InputWord.text.Equals("")
|
|
&& m_SendBtn.interactable
|
|
&& gameObject.activeSelf
|
|
&& chatUIOpen
|
|
)
|
|
{
|
|
SendData();
|
|
}
|
|
//准备进入唤醒
|
|
if (wakeUpCurrentTime > 0 && !Thinking /*&& !Typing*/)
|
|
{
|
|
wakeUpCurrentTime -= Time.deltaTime;
|
|
}
|
|
//准备发送
|
|
if (recordingSendCurrentTime >= 0 && !Thinking /*&& !Typing*/)
|
|
{
|
|
recordingSendCurrentTime -= Time.deltaTime;
|
|
}
|
|
else
|
|
{
|
|
if (!string.IsNullOrEmpty(SpeakTxt))
|
|
{
|
|
Thinking = true;
|
|
OnAppendMsg(1, MsgTypeEnum.Str, SpeakTxt);
|
|
ChatAI.Instance.SendData(Regex.Replace(SpeakTxt, @"[\p{P}\p{S}]", ""), str =>
|
|
{
|
|
Thinking = false;
|
|
wakeUpCurrentTime = 0;
|
|
if (closed) return;
|
|
if (string.IsNullOrEmpty(str)) return;
|
|
if (str == "error")
|
|
{
|
|
GenChatTxt(str);
|
|
OnAppendMsg(0, MsgTypeEnum.Str, str);
|
|
}
|
|
else
|
|
{
|
|
//coroutine = StartCoroutine(TypeText(0.2f * str.Length, str, str => GenChatTxt(str), () => Typing = false));
|
|
GenChatTxt(str);
|
|
//Typing = false;
|
|
OnAppendMsg(0, MsgTypeEnum.Str, str);
|
|
//Typing = true;
|
|
ChatAI.Instance.PlayVoice(str, clip => {
|
|
audioSource.clip = clip;
|
|
audioSource.Play();
|
|
});
|
|
}
|
|
});
|
|
ChatAI.Instance.StopRecording();
|
|
SpeakTxt = "";
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
public void SendAI(string str,Action action)
|
|
{
|
|
this.action = action;
|
|
CloseChatTxt();
|
|
if (!string.IsNullOrEmpty(str))
|
|
{
|
|
Thinking = true;
|
|
ChatAI.Instance.SendData(/*Regex.Replace(str, @"[\p{P}\p{S}]", "")*/str, str =>
|
|
{
|
|
Thinking = false;
|
|
wakeUpCurrentTime = 0;
|
|
if (string.IsNullOrEmpty(str)) return;
|
|
if (str == "error")
|
|
{
|
|
GenChatTxt(str);
|
|
OnAppendMsg(0, MsgTypeEnum.Str, str);
|
|
}
|
|
else
|
|
{
|
|
//coroutine = StartCoroutine(TypeText(0.18f * str.Length, str, str => GenChatTxt(str), () => Typing = false));
|
|
GenChatTxt(str);
|
|
//Typing = false;
|
|
OnAppendMsg(0, MsgTypeEnum.Str, str);
|
|
//Typing = true;
|
|
ChatAI.Instance.PlayVoice(str, clip => {
|
|
audioSource.clip = clip;
|
|
audioSource.Play();
|
|
});
|
|
}
|
|
});
|
|
ChatAI.Instance.StopRecording();
|
|
SpeakTxt = "";
|
|
}
|
|
}
|
|
public void SendAINext(string str, Action action)
|
|
{
|
|
this.action = action;
|
|
CloseChatTxt();
|
|
if (!string.IsNullOrEmpty(str))
|
|
{
|
|
Thinking = true;
|
|
ChatAI.Instance.SendData(/*Regex.Replace(str, @"[\p{P}\p{S}]", "")*/str, str =>
|
|
{
|
|
Thinking = false;
|
|
wakeUpCurrentTime = 0;
|
|
if (string.IsNullOrEmpty(str)) return;
|
|
if (str == "error")
|
|
{
|
|
GenChatTxtNext(str);
|
|
OnAppendMsg(0, MsgTypeEnum.Str, str);
|
|
}
|
|
else
|
|
{
|
|
//coroutine = StartCoroutine(TypeText(0.18f * str.Length, str, str => GenChatTxt(str), () => Typing = false));
|
|
GenChatTxtNext(str);
|
|
//Typing = false;
|
|
OnAppendMsg(0, MsgTypeEnum.Str, str);
|
|
//Typing = true;
|
|
ChatAI.Instance.PlayVoice(str, clip => {
|
|
audioSource.clip = clip;
|
|
audioSource.Play();
|
|
});
|
|
}
|
|
});
|
|
ChatAI.Instance.StopRecording();
|
|
SpeakTxt = "";
|
|
}
|
|
}
|
|
private void SendData()
|
|
{
|
|
//空字符退出
|
|
if (string.IsNullOrEmpty(m_InputWord.text)) return;
|
|
//提示词
|
|
OnAppendMsg(1, MsgTypeEnum.Str, m_InputWord.text);
|
|
//发送数据
|
|
ChatAI.Instance.SendData("用户消息:" + m_InputWord.text, ResponseCallBack);
|
|
//恢复
|
|
m_InputWord.text = "";
|
|
m_SendBtn.interactable = false;
|
|
}
|
|
/// <summary>
|
|
/// AI回复的信息的回调
|
|
/// </summary>
|
|
/// <param name="_response"></param>
|
|
private void ResponseCallBack(string _response)
|
|
{
|
|
_response = _response.Trim();
|
|
//VoiceBtnEnable();
|
|
m_SendBtn.interactable = true;
|
|
if (!string.IsNullOrEmpty(_response))
|
|
{
|
|
OnAppendMsg(0, MsgTypeEnum.Str, _response);
|
|
if(_response != "error")
|
|
{
|
|
ChatAI.Instance.PlayVoice(_response, clip => {
|
|
audioSource.clip = clip;
|
|
audioSource.Play();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
LoopListViewItem2 OnGetItemByIndex(LoopListView2 listView, int index)
|
|
{
|
|
if (index < 0 || index >= ChatMsgDataSourceMgr.Get.TotalItemCount)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
ChatMsg itemData = ChatMsgDataSourceMgr.Get.GetChatMsgByIndex(index);
|
|
if (itemData == null)
|
|
{
|
|
return null;
|
|
}
|
|
LoopListViewItem2 item = null;
|
|
if (itemData.mPersonId == 0)
|
|
{
|
|
if (System.Text.Encoding.UTF8.GetByteCount(itemData.mSrtMsg) >= 48)
|
|
{
|
|
item = listView.NewListViewItem("ItemPrefab1");
|
|
}
|
|
else
|
|
{
|
|
item = listView.NewListViewItem("ItemPrefab3");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (System.Text.Encoding.UTF8.GetByteCount(itemData.mSrtMsg) >= 48)
|
|
{
|
|
item = listView.NewListViewItem("ItemPrefab2");
|
|
}
|
|
else
|
|
{
|
|
item = listView.NewListViewItem("ItemPrefab4");
|
|
}
|
|
}
|
|
ChatViewItem itemScript = item.GetComponent<ChatViewItem>();
|
|
if (item.IsInitHandlerCalled == false)
|
|
{
|
|
item.IsInitHandlerCalled = true;
|
|
itemScript.Init();
|
|
}
|
|
itemScript.SetItemData(itemData, index);
|
|
return item;
|
|
}
|
|
|
|
public void OnAppendMsg(int id, MsgTypeEnum msgTypeEnum, string msg)
|
|
{
|
|
ChatMsgDataSourceMgr.Get.AppendOneMsg(id, msgTypeEnum, msg);
|
|
mLoopListView.SetListItemCount(ChatMsgDataSourceMgr.Get.TotalItemCount, false);
|
|
mLoopListView.MovePanelToItemIndex(ChatMsgDataSourceMgr.Get.TotalItemCount - 1, 0);
|
|
}
|
|
|
|
public void HideDialogue()
|
|
{
|
|
ChatAI.Instance.StopVoice();
|
|
HideDialogueEvent();
|
|
IP_Animator.SetBool("out", false);
|
|
chatUIOpen = false;
|
|
}
|
|
public void ShowDialogue()
|
|
{
|
|
IP_Animator.SetBool("out",true);
|
|
chatUIOpen = true;
|
|
CloseChatTxtWithAction();
|
|
}
|
|
public void HideDialogueEvent()
|
|
{
|
|
chatuiObj.transform.DOMove(p2.position, 0.5f);
|
|
audioSource.Stop();
|
|
}
|
|
public void ShowDialogueEvent()
|
|
{
|
|
chatuiObj.transform.DOMove(p1.position, 0.5f);
|
|
//audioSource.volume = 1;
|
|
}
|
|
void Listener()
|
|
{
|
|
if (wakeUpCurrentTime <= 0 && !Thinking && /*!Typing*/ /*&& !audioSource.isPlaying &&*/ !chatUIOpen && !prefab_v_next.activeSelf && !prefab_h_next.activeSelf)
|
|
{
|
|
closed = false;
|
|
wakeUpCurrentTime = 0;
|
|
ChatAI.Instance.StopVoice();
|
|
audioSource.Stop();
|
|
if (coroutine != null) StopCoroutine(coroutine);
|
|
GenChatTxt("你好,我在");
|
|
//Typing = true;
|
|
audioSource.clip = welcomeAudioCilp;
|
|
audioSource.Play();
|
|
coroutine = StartCoroutine(WaitExecute(welcomeAudioCilp.length, () => {
|
|
wakeUpCurrentTime = wakeUpCountdownTime;
|
|
//Typing = false;
|
|
ChatAI.Instance.StartRecording(str => {
|
|
SpeakTxt = str;
|
|
});
|
|
}));
|
|
}
|
|
}
|
|
//void Check(string txt)
|
|
//{
|
|
// if (wakeUpCurrentTime <= 0 && Regex.Replace(txt, @"[\p{P}\p{S}]", "").Contains("小智小智") && !Thinking && !Typing && !audioSource.isPlaying && !chatUIOpen)
|
|
// {
|
|
// closed = false;
|
|
// wakeUpCurrentTime = 0;
|
|
// ChatAI.Instance.StopVoice();
|
|
// audioSource.Stop();
|
|
// if (coroutine != null) StopCoroutine(coroutine);
|
|
// GenChatTxt("你好,我在");
|
|
// Typing = true;
|
|
// audioSource.clip = welcomeAudioCilp;
|
|
// audioSource.Play();
|
|
// coroutine = StartCoroutine(WaitExecute(welcomeAudioCilp.length + 1.5f, () => {
|
|
// wakeUpCurrentTime = wakeUpCountdownTime;
|
|
// Typing = false;
|
|
// }));
|
|
// }
|
|
// if (!audioSource.isPlaying && wakeUpCurrentTime > 0 && !Thinking && !Typing && !closed && !chatUIOpen)
|
|
// {
|
|
// Debug.Log("语音正在输入中: " + Regex.Replace(txt, @"[\p{P}\p{S}]", ""));
|
|
// SpeakTxt = txt;
|
|
// }
|
|
//}
|
|
void GenChatTxt(string txt)
|
|
{
|
|
int lineCount = Regex.Matches(txt, @"\r\n|\r|\n").Count + 1;
|
|
if (System.Text.Encoding.UTF8.GetByteCount(txt) >= 48 || lineCount > 1)
|
|
{
|
|
prefab_v.gameObject.SetActive(true);
|
|
prefab_h.gameObject.SetActive(false);
|
|
prefab_v.GetComponentInChildren<ReplyItem>().SetItemData(txt);
|
|
}
|
|
else
|
|
{
|
|
prefab_v.gameObject.SetActive(false);
|
|
prefab_h.gameObject.SetActive(true);
|
|
prefab_h.GetComponentInChildren<ReplyItem>().SetItemData(txt);
|
|
}
|
|
}
|
|
void GenChatTxtNext(string txt)
|
|
{
|
|
prefab_h.gameObject.SetActive(false);
|
|
prefab_v.gameObject.SetActive(false);
|
|
int lineCount = Regex.Matches(txt, @"\r\n|\r|\n").Count + 1;
|
|
if (System.Text.Encoding.UTF8.GetByteCount(txt) >= 48 || lineCount > 1)
|
|
{
|
|
prefab_v_next.gameObject.SetActive(true);
|
|
prefab_h_next.gameObject.SetActive(false);
|
|
prefab_v_next.GetComponentInChildren<ReplyItem>().SetItemData(txt);
|
|
}
|
|
else
|
|
{
|
|
prefab_v_next.gameObject.SetActive(false);
|
|
prefab_h_next.gameObject.SetActive(true);
|
|
prefab_h_next.GetComponentInChildren<ReplyItem>().SetItemData(txt);
|
|
}
|
|
}
|
|
public void CloseChatTxt()
|
|
{
|
|
closed = true;
|
|
SpeakTxt = "";
|
|
wakeUpCurrentTime = 0;
|
|
ChatAI.Instance.StopRecording();
|
|
Thinking = false;
|
|
//Typing = false;
|
|
ChatAI.Instance.StopVoice();
|
|
ChatAI.Instance.StopSend();
|
|
audioSource.Stop();
|
|
prefab_h.gameObject.SetActive(false);
|
|
prefab_v.gameObject.SetActive(false);
|
|
prefab_h_next.gameObject.SetActive(false);
|
|
prefab_v_next.gameObject.SetActive(false);
|
|
if (coroutine != null) StopCoroutine(coroutine);
|
|
}
|
|
|
|
public void CloseChatTxtWithAction()
|
|
{
|
|
CloseChatTxt();
|
|
action?.Invoke();
|
|
}
|
|
|
|
IEnumerator WaitExecute(float t, Action callBack)
|
|
{
|
|
yield return new WaitForSeconds(t);
|
|
callBack?.Invoke();
|
|
}
|
|
//IEnumerator TypeText(float totalTime, string fullText, Action<string> callBack, Action action)
|
|
//{
|
|
// float timePerCharacter = totalTime / fullText.Length;
|
|
// for (int i = 0; i <= fullText.Length; i++)
|
|
// {
|
|
// callBack?.Invoke(fullText.Substring(0, i));
|
|
// yield return new WaitForSeconds(timePerCharacter);
|
|
// }
|
|
// action?.Invoke();
|
|
//}
|
|
}
|