/// /// User interface rich text4 chat. /// add by chenbin /// 2016-03-22 /// using UnityEngine; using System.Collections; using System.Collections.Generic; /// /// User interface rich text4 chat. /// public class UIRichText4Chat : MonoBehaviour { public UILabel _label; public UILabel label { get { if (_label == null) { _label = GetComponent(); } return _label; } set { _label = value; } } [HideInInspector] public UIAtlas faceAtlas; //表情所在的图集 public string atlasName; public int faceSize = 30; public float faceScaleOffset = 1; //表情图片的大小(最好是font大小的整数倍,当与字体是一样大小时为最宜) // public static List faceList = new List (); public string faceHead = ""; public bool isFullSpace = true; //用一个全角空格来占表情的位置,***因次使用的font中需要包含全角空格*** // [HideInInspector] public float spaceSize = -1; public static string _FaceChar_ = " "; [HideInInspector] public int spaceNumber = -1; [HideInInspector] public string faceStr = ""; public static SpritePool pool = new SpritePool(); public List spList = new List(); [ContextMenu("init")] public void init() { if (isFullSpace) { _FaceChar_ = " "; //用一个全角空格来占表情的位置,***因次使用的font中需要包含全角空格*** } else { _FaceChar_ = "."; //用半角空格来占位不知道为何有问题,因此用一个“.“来占位 } calculateSpaceSize(); } public void calculateSpaceSize() { string oldStr = label.text; mTempVerts.Clear(); mTempIndices.Clear(); label.text = _FaceChar_; string text = label.processedText; label.UpdateNGUIText(); NGUIText.PrintExactCharacterPositions(text, mTempVerts, mTempIndices); if (mTempVerts.size > 1) { spaceSize = mTempVerts[mTempVerts.size - 1].x - mTempVerts[0].x; spaceNumber = Mathf.CeilToInt(faceSize / spaceSize); } mTempVerts.Clear(); mTempIndices.Clear(); label.text = oldStr; faceStr = ""; for (int i = 0; i < spaceNumber; i++) { faceStr += _FaceChar_; } } string mText = ""; public string value { get { return mText; } set { if (mText != value) { mText = value; onTextChanged(gameObject); } } } public string wrapFaceName(string faceName) { return string.IsNullOrEmpty(faceHead) ? faceName : faceHead + faceName; } public void onInputChanged(GameObject go) { if (go == null) return; UIInput input = go.GetComponent(); if (input == null) return; value = input.value; } static BetterList mTempVerts = new BetterList(); static BetterList mTempIndices = new BetterList(); bool isFinishInit = false; [ContextMenu("Execute Text Changed")] public void onTextChanged(GameObject go) { if (!isFinishInit) { isFinishInit = true; init(); } clean(); mTempVerts.Clear(); mTempIndices.Clear(); string str = findFace(); label.text = str; string text = label.processedText; label.UpdateNGUIText(); NGUIText.PrintExactCharacterPositions(label.text, mTempVerts, mTempIndices); // for (int i=0; i < mTempVerts.size; i++) { // Debug.Log (mTempVerts [i]); // } ArrayList keyList = new ArrayList(); keyList.AddRange(facesMap.Keys); int count = keyList.Count; int index = 0; string faceName = ""; Vector3 pos = Vector3.zero; for (int i = 0; i < count; i++) { index = (int)(keyList[i]); if (index * 2 + 1 < mTempVerts.size) { faceName = facesMap[index].ToString(); // Debug.Log ("index==" + index); // Debug.Log("faceName==" + faceName); pos = calculatePos(mTempVerts[index * 2], mTempVerts[index * 2 + 1]); showFace(faceName, pos); } } keyList.Clear(); mTempVerts.Clear(); mTempIndices.Clear(); } /// /// Calculates the position. search for #xx# /// /// The position. /// Pos1. /// Pos2. public Vector3 calculatePos(Vector3 pos1, Vector3 pos2) { float offsetX = label.printedSize.x; if (label.overflowMethod == UILabel.Overflow.ResizeHeight) { offsetX = label.localSize.x; } Vector3 pos = pos1; Vector3 diff = pos2 - pos; switch (label.pivot) { case UIWidget.Pivot.Center: pos.x -= offsetX / 2.0f; pos.y += label.printedSize.y / 2.0f; pos.y += diff.y / 2.0f; break; case UIWidget.Pivot.TopLeft: pos.y += diff.y / 2.0f; break; case UIWidget.Pivot.BottomLeft: pos.y += label.printedSize.y; pos.y += diff.y / 2.0f; break; case UIWidget.Pivot.Left: pos.y += label.printedSize.y / 2.0f; pos.y += diff.y / 2.0f; break; case UIWidget.Pivot.Right: pos.x -= offsetX; pos.y += label.printedSize.y / 2.0f; pos.y += diff.y / 2.0f; break; case UIWidget.Pivot.TopRight: pos.x -= offsetX; pos.y += diff.y / 2.0f; break; case UIWidget.Pivot.BottomRight: pos.x -= offsetX; pos.y += label.printedSize.y; pos.y += diff.y / 2.0f; break; case UIWidget.Pivot.Top: pos.x -= offsetX / 2.0f; pos.y += diff.y / 2.0f; break; case UIWidget.Pivot.Bottom: pos.x -= offsetX / 2.0f; pos.y += label.printedSize.y; pos.y += diff.y / 2.0f; break; } return pos; } public void showFace(string faceName, Vector3 pos) { UISprite sp = pool.getSprite(); spList.Add(sp); NGUITools.SetLayer(sp.gameObject, gameObject.layer); sp.pivot = UIWidget.Pivot.Left; sp.atlas = faceAtlas; sp.spriteName = wrapFaceName(faceName); sp.SetDimensions(faceSize, faceSize); sp.transform.parent = transform; sp.transform.localScale = Vector3.one * faceScaleOffset; if (sp.transform.parent == label.transform) { sp.transform.localPosition = pos; } else { sp.transform.localPosition = pos + label.transform.localPosition; } sp.depth = label.depth + 1; NGUITools.SetActive(sp.gameObject, true); } Hashtable facesMap = new Hashtable(); public string findFace() { facesMap.Clear(); if (string.IsNullOrEmpty(value)) return ""; int len = value.Length; string str = ""; int offset = 0; string faceName = ""; for (int i = 0; i < len; i++) { // Debug.Log("val==[" + value[i] + "]"); if (value[i] == '\n') { offset += 1; } else if (value[i] == '\\' && (i + 1 < len) && value[i + 1] == 'n') { offset += 2; } else if (value[i] == '[' && i + 7 < len && value[i + 7] == ']') { offset += 8; } else if (value[i] == '[' && i + 2 < len && value[i + 1] == '-' && value[i + 2] == ']') { offset += 3; } // Debug.Log ("val==[" + value [i] + "]==" + offset); if (value[i] == '#') { faceName = ""; for (int j = i + 1; j < len; j++) { if (value[j] == '\n') { offset += 1; } else if (value[j] == '\\' && (j + 1 < len) && value[j + 1] == 'n') { offset += 2; } else if (value[i] == '[' && i + 7 < len && value[i + 7] == ']') { offset += 8; } else if (value[i] == '[' && i + 2 < len && value[i + 1] == '-' && value[i + 2] == ']') { offset += 3; } // Debug.Log ("val==[" + value [j] + "]==" + offset); if (value[j] == '#') { if (faceAtlas.spriteMap.Contains(wrapFaceName(faceName))) { facesMap[str.Length - offset] = faceName; str += faceStr; faceName = ""; i = j; } else { str += ("#" + faceName); faceName = ""; i = j - 1; } break; } else { faceName += value[j]; if (j == len - 1) { i = j; } } } } else { str += value[i]; } } if (!string.IsNullOrEmpty(faceName)) { str += "#" + faceName; } return str; } [ContextMenu("Clean")] public void clean() { int count = spList.Count; for (int i = 0; i < count; i++) { pool.retSprite(spList[i]); // spList [i].transform.parent = null; // NGUITools.SetActive (spList [i].gameObject, false); } spList.Clear(); } public void OnDestroy() { clean(); UISprite[] sps = label.GetComponentsInChildren(true); int count = sps.Length; for (int i = 0; i < count; i++) { if (sps[i].name == "__Sprite__") { sps[i].transform.parent = null; } } } public void OnDisable() { clean(); } public void OnEnable() { onTextChanged(gameObject); } //图表对像池 public class SpritePool { Queue queue = new Queue(); public void clean() { queue.Clear(); } public UISprite getSprite() { if (queue.Count <= 0) { return newSprite(); } else { UISprite sp = queue.Dequeue(); try { if (sp == null && sp.gameObject == null) { return getSprite(); } else { return sp; } } catch (System.Exception e) { // Debug.LogError (e); return getSprite(); } } } public void retSprite(UISprite sp) { try { queue.Enqueue(sp); NGUITools.SetActive(sp.gameObject, false); //sp.gameObject.transform.parent = null; } catch (System.Exception e) { Debug.LogWarning(e); } } public UISprite newSprite() { GameObject go = new GameObject("__Sprite__"); go.transform.parent = null; UISprite sp = go.AddComponent(); NGUITools.SetActive(go, false); return sp; } } }