// this function is static to ensure that no fields are changed during this call private static void ConvertString(tk2dColoredText formattedText, tk2dTextMeshData meshData) { const char NonBreakableSpace = (char)17; if (meshData.UseShortNumbers) { formattedText.ApplyShortNumber(); } if (!meshData.DisableNumberGrouping) { int currentNumberCount = 0; for (int i = formattedText.Length - 1; i >= 0; i--) { var curChar = formattedText[i]; if (curChar >= '0' && curChar <= '9') { currentNumberCount += 1; } else { currentNumberCount = 0; } if (currentNumberCount == 4) { // add device control char -> if you add normal space -> // code lower will make new lines formattedText.Insert(i + 1, new string(NonBreakableSpace, 1)); currentNumberCount = 1; } } } // reset line break scale before calculate the dimentions meshData.lineBreakScale = Vector3.one; Vector2 dims = meshData.GetMeshDimensionsForString(formattedText); if (dims.x > meshData.maxTextLength) { if (meshData.maxTextLength > 0.0f) { switch (meshData.BreakMode) { case LineBreakMode.ScaleDown: { float curScale = meshData.maxTextLength / dims.x; meshData.lineBreakScale.Set(curScale, curScale, curScale); } break; case LineBreakMode.ThreeDots: { formattedText.Append("..."); for (int i = formattedText.Length - 4; i >= 0 && meshData.GetMeshDimensionsForString(formattedText).x > meshData.MaxTextLength; i--) { formattedText.Remove(i); } } break; case LineBreakMode.LineBreak: { int curStartIndex = 0; int curFinishIndex = 0; while (curFinishIndex < (formattedText.Length - 1)) { int curNextSpace = formattedText.IndexOf(' ', curFinishIndex + 1); int curLastIndex = (curNextSpace != -1) ? curNextSpace : (formattedText.Length - 1); if (meshData.GetMeshDimensionsForString(formattedText, curStartIndex, (curLastIndex - curStartIndex + 1)).x > meshData.maxTextLength) { int actualFinishIndex = (curFinishIndex > curStartIndex) ? curFinishIndex : curLastIndex; formattedText[actualFinishIndex] = '\n'; curFinishIndex = curStartIndex = actualFinishIndex + 1; } else { curFinishIndex = curLastIndex; } } } break; } } } float dimsY = Mathf.Abs(meshData.GetMeshDimensionsForString(formattedText).y); if (dimsY > meshData.maxTextHeight) { if (meshData.maxTextHeight > 0.0f) { float curScale = meshData.lineBreakScale.x; float newScale = meshData.maxTextHeight / dimsY; curScale = Math.Min(curScale, newScale); meshData.lineBreakScale.Set(curScale, curScale, curScale); } } if (meshData.ShouldScaleInCellSize) { float newScale = Mathf.Min(meshData.maxTextLength / dims.x, meshData.MaxTextHeight / Mathf.Abs(dims.y)); meshData.lineBreakScale.Set(newScale, newScale, newScale); } formattedText.Replace(NonBreakableSpace, ' '); }
public static void SetTextMeshGeom(this GeomData geomData, Vector3[] pos, Vector2[] uv, Vector2[] uv2, Color32[] color, int offset) { tk2dTextMeshData data = geomData.TextMeshData; tk2dFontData fontInst = data.FontInst; tk2dColoredText formattedText = data.FormattedText; InlineStyler curStyler = new InlineStyler(); curStyler.meshTopColor = new Color32(255, 255, 255, 255); curStyler.meshBottomColor = new Color32(255, 255, 255, 255); curStyler.meshGradientTexU = (float)data.textureGradient / (float)((fontInst.gradientCount > 0) ? fontInst.gradientCount : 1); curStyler.curGradientCount = fontInst.gradientCount; Vector2 dims = data.GetMeshDimensionsForString(formattedText); float offsetY = data.GetYAnchorForHeight(dims.y); float cursorX = 0.0f; float cursorY = 0.0f; // target is required due to invisible '\n' character int target = 0; int alignStartTarget = 0; for (int i = 0; i < formattedText.Length && target < geomData.CurrentAllocatedCharacters; ++i) { formattedText.ApplyColorCommand(curStyler, i); int idx = formattedText[i]; tk2dFontChar chr = fontInst.GetCharForIndex(idx, 0); if (idx == '\n') { float lineWidth = cursorX; int alignEndTarget = target; // this is one after the last filled character if (alignStartTarget != target) { float xOffset = data.GetXAnchorForWidth(lineWidth); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } alignStartTarget = target; cursorX = 0.0f; cursorY -= data.ActualLineSpaceHeight; } else { pos[offset + target * 4 + 0] = new Vector3(cursorX + chr.p0.x * data.TotalScale.x, offsetY + cursorY + chr.p0.y * data.TotalScale.y, 0); pos[offset + target * 4 + 1] = new Vector3(cursorX + chr.p1.x * data.TotalScale.x, offsetY + cursorY + chr.p0.y * data.TotalScale.y, 0); pos[offset + target * 4 + 2] = new Vector3(cursorX + chr.p0.x * data.TotalScale.x, offsetY + cursorY + chr.p1.y * data.TotalScale.y, 0); pos[offset + target * 4 + 3] = new Vector3(cursorX + chr.p1.x * data.TotalScale.x, offsetY + cursorY + chr.p1.y * data.TotalScale.y, 0); if (chr.flipped) { uv[offset + target * 4 + 0] = new Vector2(chr.uv1.x, chr.uv1.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv0.x, chr.uv0.y); } else { uv[offset + target * 4 + 0] = new Vector2(chr.uv0.x, chr.uv0.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv1.x, chr.uv1.y); } if (fontInst.textureGradients) { uv2[offset + target * 4 + 0] = chr.gradientUv[0] + new Vector2(curStyler.meshGradientTexU, 0); uv2[offset + target * 4 + 1] = chr.gradientUv[1] + new Vector2(curStyler.meshGradientTexU, 0); uv2[offset + target * 4 + 2] = chr.gradientUv[2] + new Vector2(curStyler.meshGradientTexU, 0); uv2[offset + target * 4 + 3] = chr.gradientUv[3] + new Vector2(curStyler.meshGradientTexU, 0); } if (fontInst.isPacked) { Color32 c = channelSelectColors[chr.channel]; color[offset + target * 4 + 0] = c; color[offset + target * 4 + 1] = c; color[offset + target * 4 + 2] = c; color[offset + target * 4 + 3] = c; } else { color[offset + target * 4 + 0] = curStyler.meshTopColor; color[offset + target * 4 + 1] = curStyler.meshTopColor; color[offset + target * 4 + 2] = curStyler.meshBottomColor; color[offset + target * 4 + 3] = curStyler.meshBottomColor; } cursorX += (chr.advance + data.Spacing) * data.TotalScale.x; if (data.kerning && i < formattedText.Length - 1) { foreach (var k in fontInst.kerning) { if (k.c0 == formattedText[i] && k.c1 == formattedText[i + 1]) { cursorX += k.amount * data.TotalScale.x; break; } } } target++; } } if (alignStartTarget != target) { float lineWidth = cursorX; int alignEndTarget = target; float xOffset = data.GetXAnchorForWidth(lineWidth); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } for (int i = target; i < geomData.CurrentAllocatedCharacters; ++i) { pos[offset + i * 4 + 0] = pos[offset + i * 4 + 1] = pos[offset + i * 4 + 2] = pos[offset + i * 4 + 3] = Vector3.zero; uv[offset + i * 4 + 0] = uv[offset + i * 4 + 1] = uv[offset + i * 4 + 2] = uv[offset + i * 4 + 3] = Vector2.zero; if (fontInst.textureGradients) { uv2[offset + i * 4 + 0] = uv2[offset + i * 4 + 1] = uv2[offset + i * 4 + 2] = uv2[offset + i * 4 + 3] = Vector2.zero; } color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = Color.clear; } }