protected override void OnPopulateMesh(VertexHelper toFill) { if (font == null) { return; } if (EmojiIndex == null) { EmojiIndex = EmojiUtil.EmojiIndex; } if (EmojiIndex == null || EmojiIndex.Count == 0) { base.OnPopulateMesh(toFill); return; } Dictionary <int, EmojiInfo> emojiDic = new Dictionary <int, EmojiInfo> (); string resultText = string.Empty; if (supportRichText) { List <EmojiElement> emojiList = EmojiUtil.getEmojiList(text, out resultText); //Debug.Log("resultText:"+ resultText+",len:"+ resultText.Length); //Debug.Log("emojiList:"+ emojiList.Count); for (int i = 0, length = emojiList.Count; i < length; i++) { EmojiElement element = emojiList[i]; if (element.isEmoji) { EmojiInfo info; string unicodeValue = element.unicode; //Debug.Log("unicodeValue:" + unicodeValue + ",i:" + i); if (EmojiIndex.TryGetValue(unicodeValue, out info)) { //Debug.Log("1 unicodeValue:" + unicodeValue); info.len = 1; emojiDic.Add(i, info); } } } } // We don't care if we the font Texture changes while we are doing our Update. // The end result of cachedTextGenerator will be valid for this instance. // Otherwise we can get issues like Case 619238. m_DisableFontTextureRebuiltCallback = true; Vector2 extents = rectTransform.rect.size; var settings = GetGenerationSettings(extents); if (supportRichText && !string.IsNullOrEmpty(resultText)) { cachedTextGenerator.Populate(resultText, settings); } else { cachedTextGenerator.Populate(text, settings); } Rect inputRect = rectTransform.rect; // get the text alignment anchor point for the text in local space Vector2 textAnchorPivot = GetTextAnchorPivot(alignment); Vector2 refPoint = Vector2.zero; refPoint.x = Mathf.Lerp(inputRect.xMin, inputRect.xMax, textAnchorPivot.x); refPoint.y = Mathf.Lerp(inputRect.yMin, inputRect.yMax, textAnchorPivot.y); // Determine fraction of pixel to offset text mesh. Vector2 roundingOffset = PixelAdjustPoint(refPoint) - refPoint; // Apply the offset to the vertices IList <UIVertex> verts = cachedTextGenerator.verts; float unitsPerPixel = 1 / pixelsPerUnit; //Last 4 verts are always a new line... int vertCount = verts.Count - 4; //Debug.Log("verts:" + verts.Count); toFill.Clear(); if (roundingOffset != Vector2.zero) { for (int i = 0; i < vertCount; ++i) { int tempVertsIndex = i & 3; m_TempVerts[tempVertsIndex] = verts[i]; m_TempVerts[tempVertsIndex].position *= unitsPerPixel; m_TempVerts[tempVertsIndex].position.x += roundingOffset.x; m_TempVerts[tempVertsIndex].position.y += roundingOffset.y; if (tempVertsIndex == 3) { toFill.AddUIVertexQuad(m_TempVerts); } } } else { float repairDistance = 0; float repairDistanceHalf = 0; float repairY = 0; if (vertCount > 0) { repairY = verts [3].position.y; } for (int i = 0; i < vertCount; ++i) { EmojiInfo info; int index = i / 4; if (emojiDic.TryGetValue(index, out info)) { //compute the distance of '[' and get the distance of emoji float charDis = (verts [i + 1].position.x - verts [i].position.x) * 3; m_TempVerts [3] = verts [i]; //1 m_TempVerts [2] = verts [i + 1]; //2 m_TempVerts [1] = verts [i + 2]; //3 m_TempVerts [0] = verts [i + 3]; //4 //the real distance of an emoji m_TempVerts [2].position += new Vector3(charDis, 0, 0); m_TempVerts [1].position += new Vector3(charDis, 0, 0); //make emoji has equal width and height float fixValue = (m_TempVerts [2].position.x - m_TempVerts [3].position.x - (m_TempVerts [2].position.y - m_TempVerts [1].position.y)); m_TempVerts [2].position -= new Vector3(fixValue, 0, 0); m_TempVerts [1].position -= new Vector3(fixValue, 0, 0); float curRepairDis = 0; if (verts [i].position.y < repairY) // to judge current char in the same line or not { repairDistance = repairDistanceHalf; repairDistanceHalf = 0; repairY = verts [i + 3].position.y; } curRepairDis = repairDistance; int dot = 0; //repair next line distance for (int j = info.len - 1; j > 0; j--) { if (verts [i + j * 4 + 3].position.y >= verts [i + 3].position.y) { repairDistance += verts [i + j * 4 + 1].position.x - m_TempVerts [2].position.x; break; } else { dot = i + 4 * j; } } if (dot > 0) { int nextChar = i + info.len * 4; if (nextChar < verts.Count) { repairDistanceHalf = verts [nextChar].position.x - verts [dot].position.x; } } //repair its distance for (int j = 0; j < 4; j++) { m_TempVerts [j].position -= new Vector3(curRepairDis, 0, 0); } m_TempVerts [0].position *= unitsPerPixel; m_TempVerts [1].position *= unitsPerPixel; m_TempVerts [2].position *= unitsPerPixel; m_TempVerts [3].position *= unitsPerPixel; float pixelOffset = emojiDic [index].size / 32 / 2; m_TempVerts [0].uv1 = new Vector2(emojiDic [index].x + pixelOffset, emojiDic [index].y + pixelOffset); m_TempVerts [1].uv1 = new Vector2(emojiDic [index].x - pixelOffset + emojiDic [index].size, emojiDic [index].y + pixelOffset); m_TempVerts [2].uv1 = new Vector2(emojiDic [index].x - pixelOffset + emojiDic [index].size, emojiDic [index].y - pixelOffset + emojiDic [index].size); m_TempVerts [3].uv1 = new Vector2(emojiDic [index].x + pixelOffset, emojiDic [index].y - pixelOffset + emojiDic [index].size); toFill.AddUIVertexQuad(m_TempVerts); i += 4 * info.len - 1; } else { int tempVertsIndex = i & 3; if (tempVertsIndex == 0 && verts [i].position.y < repairY) { repairY = verts [i + 3].position.y; repairDistance = repairDistanceHalf; repairDistanceHalf = 0; } m_TempVerts [tempVertsIndex] = verts [i]; m_TempVerts [tempVertsIndex].position -= new Vector3(repairDistance, 0, 0); m_TempVerts [tempVertsIndex].position *= unitsPerPixel; if (tempVertsIndex == 3) { toFill.AddUIVertexQuad(m_TempVerts); } } } } m_DisableFontTextureRebuiltCallback = false; }
/// <summary> /// 将中文或者表情放到list中 /// 参考java的codePoint /// 两个表情挨着的情况暂时没处理 /// out的resultText,将表情符号替换为█,用来计算Text的cachedTextGenerator /// </summary> public static List <EmojiElement> getEmojiList(string str, out string resultText) { resultText = str; List <EmojiElement> arr = new List <EmojiElement>(); StringInfo si = new StringInfo(str); StringBuilder builder = new StringBuilder(); int emojiCount = 0; for (int i = 0; i < si.LengthInTextElements; i++) { string ele = si.SubstringByTextElements(i, 1); string unicode = "0x" + toUnicode(ele); //Debug.Log("i : " + i); string nextUnicode = string.Empty; if (i < si.LengthInTextElements - 1) { string element1 = si.SubstringByTextElements(i + 1, 1); nextUnicode = "0x" + toUnicode(element1); } try { int e = Convert.ToInt32(unicode, 16); bool isEmoji = isEmojiCharacter(e); int nextInt = 0; bool isNextEmoji = false; if (!string.IsNullOrEmpty(nextUnicode)) { nextInt = Convert.ToInt32(nextUnicode, 16); isNextEmoji = isEmojiCharacter(nextInt); } if (isEmoji) { builder.Append(ele); emojiCount++; if (isGetEmoji(e, nextInt, emojiCount)) { EmojiElement ee1 = new EmojiElement(); ee1.isEmoji = true; ee1.unicode = toUnicode(builder.ToString()); ee1.originalText = builder.ToString(); resultText = resultText.Replace(ee1.originalText, replaceStr); arr.Add(ee1); builder.Remove(0, builder.Length); emojiCount = 0; } } else { if (!string.IsNullOrEmpty(builder.ToString())) { EmojiElement ee1 = new EmojiElement(); ee1.isEmoji = true; ee1.unicode = toUnicode(builder.ToString()); ee1.originalText = builder.ToString(); resultText = resultText.Replace(ee1.originalText, replaceStr); arr.Add(ee1); builder.Remove(0, builder.Length); emojiCount = 0; } EmojiElement ee = new EmojiElement(); ee.isEmoji = false; arr.Add(ee); } if (i == si.LengthInTextElements - 1) { if (!string.IsNullOrEmpty(builder.ToString())) { EmojiElement ee1 = new EmojiElement(); ee1.isEmoji = true; ee1.unicode = toUnicode(builder.ToString()); ee1.originalText = builder.ToString(); resultText = resultText.Replace(ee1.originalText, replaceStr); arr.Add(ee1); builder.Remove(0, builder.Length); emojiCount = 0; } } } catch (Exception ex) { Debug.Log(ex.ToString()); } } return(arr); }