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; /// /// 发送信息按钮 /// [SerializeField] private Button m_SendBtn; /// /// 输入的信息 /// [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(); #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; } /// /// AI回复的信息的回调 /// /// 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(); 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().SetItemData(txt); } else { prefab_v.gameObject.SetActive(false); prefab_h.gameObject.SetActive(true); prefab_h.GetComponentInChildren().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().SetItemData(txt); } else { prefab_v_next.gameObject.SetActive(false); prefab_h_next.gameObject.SetActive(true); prefab_h_next.GetComponentInChildren().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 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(); //} }