using LitJson; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace SC.XR.Unity.Module_Keyboard { public class SCKeyboard2DMono : SCKeyboardMono { #region Initialize public override void Initialize(SCKeyboardType keyboardType = SCKeyboardType.Default) { base.Initialize(keyboardType); InitializePromptWords(); Keyboard2DPrompt.isOpen = false; } protected override void DefaultKeyboardInitialize() { switch (SCKeyboard.currentSystemLanguage) { case KeyboardSystemLanguage.Chinese: ActiveKeyboard(KeyboardEnum.ABC, KeyboardState.Cn); break; default: ActiveKeyboard(KeyboardEnum.ABC, KeyboardState.En); break; } ActiveKeyboard(KeyboardEnum.Delete); ActiveKeyboard(KeyboardEnum.Number); } protected override void ASCIICapableKeyboardInitialize() { ActiveKeyboard(KeyboardEnum.ABC, KeyboardState.En); ActiveKeyboard(KeyboardEnum.Delete); ActiveKeyboard(KeyboardEnum.Number); } protected override void URLKeyboardInitialize() { switch (SCKeyboard.currentSystemLanguage) { case KeyboardSystemLanguage.Chinese: ActiveKeyboard(KeyboardEnum.ABC, KeyboardState.Cn); break; default: ActiveKeyboard(KeyboardEnum.ABC, KeyboardState.En); break; } ActiveKeyboard(KeyboardEnum.Delete); ActiveKeyboard(KeyboardEnum.Number); ActiveKeyboard(KeyboardEnum.Prompt); } protected override void SearchKeyboardInitialize() { switch (SCKeyboard.currentSystemLanguage) { case KeyboardSystemLanguage.Chinese: ActiveKeyboard(KeyboardEnum.ABC, KeyboardState.Cn); break; default: ActiveKeyboard(KeyboardEnum.ABC, KeyboardState.En); break; } ActiveKeyboard(KeyboardEnum.Delete); ActiveKeyboard(KeyboardEnum.Number); } #endregion #region Keyboards protected SCKeyboard2DPrompt Keyboard2DPrompt { get { return keyboard_prompt as SCKeyboard2DPrompt; } } public GameObject keyboard_symbol; public GameObject keyboard_meme; public GameObject keyboard_morePrompt; public GameObject keyboard_language; public GameObject keyboard_delete; public GameObject keyboard_num; #endregion #region Key Clicks public override void OnNumberKeyClick(string value) { if (preInputStringBuilder.Length != 0) { OnPinyinKeyClick(value); } else { base.OnNumberKeyClick(value); } } public override void OnPinyinKeyClick(string value) { chinesePagesDic = new Dictionary>>(); preInputStringBuilder.Append(value); ActiveKeyboard(KeyboardEnum.Prompt); Keyboard2DPrompt.SetEnteredText(preInputStringBuilder.ToString()); PinyinKeyHandler(preInputStringBuilder.ToString()); } public override void OnPromptKeyClick(string value) { base.OnPromptKeyClick(value); InitializePromptWords(); } #endregion #region Special Key Click Events public override void OnDeleteClick() { if (keyboard_prompt.isActiveAndEnabled) { if (preInputStringBuilder.Length == 0) { OnWebKeyClick?.Invoke("Backspace"); OnDeleteKeyClick?.Invoke(); return; } preInputStringBuilder.Remove(preInputStringBuilder.Length - 1, 1); Keyboard2DPrompt.SetEnteredText(preInputStringBuilder.ToString()); if (preInputStringBuilder.Length == 0) { InitializePromptWords(); return; } PinyinKeyHandler(preInputStringBuilder.ToString()); } else { OnWebKeyClick?.Invoke("Backspace"); OnDeleteKeyClick?.Invoke(); } } public override void OnEnterClick() { OnKeyClick?.Invoke(preInputStringBuilder.ToString()); for (int i = 0; i < preInputStringBuilder.Length; i++) { OnWebKeyClick?.Invoke(preInputStringBuilder[i].ToString()); } base.OnEnterClick(); OnEnterKeyClick?.Invoke(); } public override void OnLanguageClick() { base.OnLanguageClick(); InitializePromptWords(); } public override void OnCnClick() { base.OnCnClick(); InitializePromptWords(); //HideKeyboardPrompt(); } public override void OnEnClick() { base.OnEnClick(); InitializePromptWords(); // HideKeyboardPrompt(); } private int currentPage = 1; private int minPage = 1; private int maxPage = 10000; public override void OnPromptPageDownClick() { currentPage++; if (currentPage > maxPage) { currentPage = maxPage; } GenerateChinesePages(currentPage); } public override void OnPromptPageUpClick() { currentPage--; if (currentPage < minPage) { currentPage = minPage; } GenerateChinesePages(currentPage); } #endregion #region UGUI Key Click Events protected override void OnOpenMoreClick() { if (!Keyboard2DPrompt.isOpen) { if (preInputStringBuilder.Length != 0) { Keyboard2DPrompt.isOpen = true; ActiveKeyboard(KeyboardEnum.MorePrompt); GenerateChinesePages(1); } //GenerateMorePromptKeys(1); LayoutRebuilder.ForceRebuildLayoutImmediate(keyboard_morePrompt.transform.GetChild(0).GetChild(0).transform as RectTransform); } else { Keyboard2DPrompt.isOpen = false; ActiveKeyboard(KeyboardEnum.ABC, KeyboardState.Cn); } } #endregion #region Key Handlers private Text m_font; private RectTransform m_PromptPage; private RectTransform m_MorePromptPage; public Text Font { get { if (m_font == null) { m_font = Resources.Load(keyPath).GetComponentInChildren(); } return m_font; } } public RectTransform PromptPage { get { if (m_PromptPage == null) { m_PromptPage = Keyboard2DPrompt.promptInput; } return m_PromptPage; } } public RectTransform MorePromptPage { get { if (m_MorePromptPage == null) { m_MorePromptPage = keyboard_morePrompt.transform.GetChild(0).GetChild(0).GetComponent(); } return m_MorePromptPage; } } private int maxChineseWordCount; private static int currentChineseWordIndex = 0; public virtual void GenerateURLPages(int page = 0) { Keyboard2DPrompt.alreadyInput.gameObject.transform.parent.parent.gameObject.SetActive(false); //隐藏AlreadyInput Keyboard2DPrompt.promptInput.sizeDelta = new Vector2(484.88f, Keyboard2DPrompt.promptInput.sizeDelta.y); //拉长promptRow长度 GenerateURLKeys(); } public virtual void GenerateChinesePages(int page) { Keyboard2DPrompt.alreadyInput.gameObject.transform.parent.parent.gameObject.SetActive(true); //显示AlreadyInput Keyboard2DPrompt.promptInput.sizeDelta = new Vector2(268.88f, Keyboard2DPrompt.promptInput.sizeDelta.y); //缩短promptRow长度 if (chinesePagesDic.ContainsKey(page)) { if (page == 0) { HideAllPromptPages(); foreach (int row in chinesePagesDic[page].Keys) { foreach (int word in chinesePagesDic[page][row].Keys) { SCKeyboardBaseKey key = promptPagesDic[0][row][word]; string text = chinesePagesDic[page][row][word]; key.Value = text; key.gameObject.SetActive(true); } } } else { HidePromptPage(1); foreach (int row in chinesePagesDic[page].Keys) { foreach (int word in chinesePagesDic[page][row].Keys) { SCKeyboardBaseKey key = promptPagesDic[1][row][word]; string text = chinesePagesDic[page][row][word]; key.Value = text; key.gameObject.SetActive(true); } } } StartCoroutine(RebuildLayout(PromptPage)); } else { // Prompte Keys if (page == 0) { GenerateChineseKeys(); } // More Prompt Keys else { GenerateMoreChineseKeys(page); } } } private void GenerateChineseKeys() { maxPage = 10000; HideAllPromptPages(); maxChineseWordCount = Keyboard2DPrompt.GetChinese(preInputStringBuilder.ToString()); currentChineseWordIndex = 0; GenerateChineseKeys(0, PromptPage, new List()); StartCoroutine(RebuildLayout(PromptPage)); } private void GenerateURLKeys() { HideAllPromptPages(); GenerateURLKeys(0, PromptPage, new List()); StartCoroutine(RebuildLayout(PromptPage)); } private void GenerateMoreChineseKeys(int pageIndex = 1) { HidePromptPage(1); if (pageIndex < 1) pageIndex = 1; GenerateMoreChineseKeys(0, 0, pageIndex, new List()); StartCoroutine(RebuildLayout(MorePromptPage)); } private void GenerateChineseKeys(int keyIndex, RectTransform promptRow, List messages) { if (currentChineseWordIndex > maxChineseWordCount - 1) { return; } if (!promptPagesDic.ContainsKey(0)) promptPagesDic[0] = new Dictionary>(); if (!promptPagesDic[0].ContainsKey(0)) promptPagesDic[0][0] = new Dictionary(); if (!chinesePagesDic.ContainsKey(0)) chinesePagesDic[0] = new Dictionary>(); if (!chinesePagesDic[0].ContainsKey(0)) chinesePagesDic[0][0] = new Dictionary(); SCKeyboard2DKey promptKey; string text = Keyboard2DPrompt.GetChinese(currentChineseWordIndex); if (promptPagesDic[0][0].ContainsKey(keyIndex)) { promptKey = promptPagesDic[0][0][keyIndex] as SCKeyboard2DKey; promptKey.Value = text; promptKey.GetComponentInChildren().enabled = true; //改回来 messages.Add(promptKey.Value); if (!WithinTheLimits(messages, promptRow.GetComponent(), promptRow.sizeDelta.x)) { promptKey.gameObject.SetActive(false); return; } promptKey.gameObject.SetActive(true); chinesePagesDic[0][0][keyIndex] = text; } else { promptKey = InstantiateKey(keyPath, promptRow, text); messages.Add(promptKey.Value); promptPagesDic[0][0][keyIndex] = promptKey; if (!WithinTheLimits(messages, promptRow.GetComponent(), promptRow.sizeDelta.x)) { promptKey.gameObject.SetActive(false); return; } promptKey.gameObject.SetActive(true); chinesePagesDic[0][0][keyIndex] = text; } //Debug.Log("promptKey [ " + promptKey.Value + " ] :" + currentChineseWordIndex); currentChineseWordIndex++; GenerateChineseKeys(keyIndex + 1, promptRow, messages); } private void GenerateURLKeys(int keyIndex, RectTransform promptRow, List messages) { if (!promptPagesDic.ContainsKey(0)) promptPagesDic[0] = new Dictionary>(); if (!promptPagesDic[0].ContainsKey(0)) promptPagesDic[0][0] = new Dictionary(); if (urlPagesDic[0][0].ContainsKey(keyIndex)) { SCKeyboard2DKey promptKey; string text = urlPagesDic[0][0][keyIndex]; if (promptPagesDic[0][0].ContainsKey(keyIndex)) { promptKey = promptPagesDic[0][0][keyIndex] as SCKeyboard2DKey; } else { promptKey = InstantiateKey(keyPath, promptRow, text); promptPagesDic[0][0][keyIndex] = promptKey; } promptKey.Value = text; promptKey.GetComponentInChildren().enabled = false; //更改promptKey promptKey.GetComponentInChildren().GetComponent().sizeDelta = new Vector2(1000f, 240f); //更改promptKey messages.Add(promptKey.Value); if (!WithinTheLimits(messages, promptRow.GetComponent(), promptRow.sizeDelta.x)) { promptKey.gameObject.SetActive(false); return; } promptKey.gameObject.SetActive(true); //Debug.Log("URLKey [ " + promptKey.Value + " ] :" + keyIndex); GenerateURLKeys(keyIndex + 1, promptRow, messages); } } private void GenerateMoreChineseKeys(int keyIndex, int rowIndex, int pageIndex, List messages) { if (currentChineseWordIndex > maxChineseWordCount - 1) { maxPage = currentPage; return; } if (rowIndex > 4) { return; } SCKeyboard2DKey promptKey; RectTransform promptRow; if (promptRowRectTransformsDic.ContainsKey(rowIndex)) promptRow = promptRowRectTransformsDic[rowIndex]; else promptRowRectTransformsDic.Add(rowIndex, promptRow = InstantiateRow(rowPath, MorePromptPage)); string text = Keyboard2DPrompt.GetChinese(currentChineseWordIndex); if (!promptPagesDic.ContainsKey(1)) promptPagesDic[1] = new Dictionary>(); if (!promptPagesDic[1].ContainsKey(rowIndex)) promptPagesDic[1][rowIndex] = new Dictionary(); if (!chinesePagesDic.ContainsKey(pageIndex)) chinesePagesDic[pageIndex] = new Dictionary>(); if (!chinesePagesDic[pageIndex].ContainsKey(rowIndex)) chinesePagesDic[pageIndex][rowIndex] = new Dictionary(); if (promptPagesDic[1][rowIndex].ContainsKey(keyIndex)) { promptKey = promptPagesDic[1][rowIndex][keyIndex] as SCKeyboard2DKey; promptKey.Value = text; messages.Add(promptKey.Value); if (!WithinTheLimits(messages, promptRow.GetComponent(), 443f)) { promptKey.gameObject.SetActive(false); GenerateMoreChineseKeys(0, rowIndex + 1, pageIndex, new List()); return; } promptKey.gameObject.SetActive(true); chinesePagesDic[pageIndex][rowIndex][keyIndex] = text; } else { promptKey = InstantiateKey(keyPath, promptRow, text); messages.Add(promptKey.Value); promptPagesDic[1][rowIndex].Add(keyIndex, promptKey); if (!WithinTheLimits(messages, promptRow.GetComponent(), 443f)) { promptKey.gameObject.SetActive(false); GenerateMoreChineseKeys(0, rowIndex + 1, pageIndex, new List()); return; } promptKey.gameObject.SetActive(true); chinesePagesDic[pageIndex][rowIndex][keyIndex] = text; } //Debug.Log("promptKey [ " + promptKey.Value + " ] :" + currentChineseWordIndex); currentChineseWordIndex++; GenerateMoreChineseKeys(keyIndex + 1, rowIndex, pageIndex, messages); } private void HidePromptPage(int page) { if (promptPagesDic.ContainsKey(page)) { foreach (var rowIndex in promptPagesDic[page].Keys) { foreach (var keyIndex in promptPagesDic[page][rowIndex].Keys) { promptPagesDic[page][rowIndex][keyIndex].gameObject.SetActive(false); } } } } private void HideAllPromptPages() { HidePromptPage(0); HidePromptPage(1); } IEnumerator RebuildLayout(RectTransform rect) { yield return new WaitForEndOfFrame(); LayoutRebuilder.ForceRebuildLayoutImmediate(rect); } public override void PinyinKeyHandler(string preInput) { chinesePagesDic = new Dictionary>>(); if (keyboard_morePrompt.activeSelf == false) { GenerateChinesePages(0); } else { GenerateChinesePages(0); GenerateChinesePages(1); } } private SCKeyboard2DKey InstantiateKey(string path, Transform parent, string value) { SCKeyboard2DKey prefab = Resources.Load(path); SCKeyboard2DKey promptKey = GameObject.Instantiate(prefab); promptKey.transform.SetParent(parent); promptKey.transform.localPosition = Vector3.zero; promptKey.transform.localRotation = Quaternion.identity; promptKey.transform.localScale = Vector3.one; promptKey.Value = value; return promptKey; } private RectTransform InstantiateRow(string path, Transform parent) { GameObject prefab = Resources.Load(path); GameObject promptRow = GameObject.Instantiate(prefab); promptRow.transform.SetParent(parent); promptRow.transform.localPosition = Vector3.zero; promptRow.transform.localRotation = Quaternion.identity; promptRow.transform.localScale = Vector3.one; return promptRow.GetComponent(); } private bool WithinTheLimits(List messages, HorizontalLayoutGroup group, float LimitWidth) { float rectWidth = LimitWidth; float totalWidth = 0; float left = group.padding.left; float right = group.padding.right; float space = group.spacing; float width = 0; int wordCount = messages.Count; string message = ""; for (int i = 0; i < messages.Count; i++) { message += messages[i]; width += 12; } width += KeyboardUtils.CaculateTextLength(message, Font) / 10; totalWidth = (wordCount - 1) * space + left + width; return totalWidth <= rectWidth; } #endregion #region ActiveKeyboards protected override void ActiveKeyboard(KeyboardEnum keyboardEnum, KeyboardState keyboardState = KeyboardState.Cn) { base.ActiveKeyboard(keyboardEnum, keyboardState); switch (keyboardEnum) { case KeyboardEnum.ABC: OnActiveABCKeyboard(keyboardState); switch (presentKeyboardType) { case SCKeyboardType.Default: case SCKeyboardType.ASCIICapable: case SCKeyboardType.Search: break; case SCKeyboardType.URL: ActiveKeyboard(KeyboardEnum.Prompt); break; } break; case KeyboardEnum.Symbol: OnActiveSymbolKeyboard(); break; case KeyboardEnum.Number: OnActiveNumberKeyboard(); break; case KeyboardEnum.Meme: OnActiveMemeKeyboard(); break; case KeyboardEnum.Prompt: OnActivePromptKeyboard(); break; case KeyboardEnum.MorePrompt: OnActiveMorePromptKeyboard(); break; case KeyboardEnum.Language: OnActiveLanguageKeyboard(); break; case KeyboardEnum.Delete: OnActiveDeleteKeyboard(); break; } } protected override void HideKeyboardPrompt(bool inputPreString = false) { if (keyboard_prompt.isActiveAndEnabled) { switch (presentKeyboardType) { case SCKeyboardType.URL: break; default: //if (inputPreString) OnNormalKeyClick(preInputStringBuilder.ToString()); preInputStringBuilder.Clear(); Keyboard2DPrompt.gameObject.SetActive(false); ChangePromptOpenBtnState(true); break; } } } protected void ChangePromptOpenBtnState(bool isOpen) { Keyboard2DPrompt.open.gameObject.SetActive(isOpen); Keyboard2DPrompt.close.gameObject.SetActive(!isOpen); } public void OnActiveABCKeyboard(KeyboardState keyboardState) { if (presentKeyboard != null) previousKeyboard = presentKeyboard; keyboard_abc.SetActive(true); presentKeyboard = keyboard_abc; if (previousKeyboard != null && previousKeyboard != presentKeyboard) previousKeyboard.SetActive(false); presentKeyboardState = keyboardState; OnKeyboardStateChange?.Invoke(keyboardState); } public void OnActiveSymbolKeyboard() { if (presentKeyboard != null) previousKeyboard = presentKeyboard; keyboard_symbol.SetActive(true); HideKeyboardPrompt(); presentKeyboard = keyboard_symbol; if (previousKeyboard != null && previousKeyboard != presentKeyboard) previousKeyboard.SetActive(false); } public void OnActiveNumberKeyboard() { keyboard_num.SetActive(true); } public void OnActiveMemeKeyboard() { keyboard_meme.SetActive(true); } public void OnActivePromptKeyboard() { keyboard_prompt.gameObject.SetActive(true); } public void OnActiveMorePromptKeyboard() { if (presentKeyboard != null) previousKeyboard = presentKeyboard; keyboard_morePrompt.gameObject.SetActive(true); presentKeyboard = keyboard_morePrompt; if (previousKeyboard != null && previousKeyboard != presentKeyboard) previousKeyboard.SetActive(false); } public void OnActiveLanguageKeyboard() { if (presentKeyboard != null) previousKeyboard = presentKeyboard; keyboard_language.SetActive(true); HideKeyboardPrompt(); presentKeyboard = keyboard_language; if (previousKeyboard != null && previousKeyboard != presentKeyboard) previousKeyboard.SetActive(false); } public void OnActiveDeleteKeyboard() { keyboard_delete.SetActive(true); } #endregion #region Methods private void InitializePromptWords() { HideAllPromptPages(); switch (presentKeyboardType) { case SCKeyboardType.Default: case SCKeyboardType.Search: case SCKeyboardType.ASCIICapable: preInputStringBuilder.Clear(); Keyboard2DPrompt.SetEnteredText(""); Keyboard2DPrompt.gameObject.SetActive(false); break; case SCKeyboardType.URL: preInputStringBuilder.Clear(); Keyboard2DPrompt.SetEnteredText(""); if (!urlPagesDic.ContainsKey(0)) urlPagesDic[0] = new Dictionary>(); if (!urlPagesDic[0].ContainsKey(0)) urlPagesDic[0][0] = new Dictionary(); for (int i = 0; i < Keyboard2DPrompt.URLWords.Count; i++) { urlPagesDic[0][0][i] = Keyboard2DPrompt.URLWords[i]; } //urlPagesDic[0][0][0] = "http://"; //urlPagesDic[0][0][1] = "www."; //urlPagesDic[0][0][2] = ".com"; //urlPagesDic[0][0][3] = "@"; GenerateURLPages(); break; } if (keyboard_morePrompt.gameObject.activeSelf) { keyboard_morePrompt.gameObject.SetActive(false); Keyboard2DPrompt.isOpen = false; ActiveKeyboard(KeyboardEnum.ABC, KeyboardState.Cn); } } #endregion #region Extend Methods #endregion } }