/// <summary> /// Calculates the mesh dimensions for the given string /// and returns a width and height. /// </summary> public static Vector2 GetMeshDimensionsForString(string str, CurvedGeomData CurvedGeomData) { tk2dCurvedTextMeshData data = CurvedGeomData.textMeshData; tk2dFontData _fontInst = CurvedGeomData.fontInst; float maxWidth = 0.0f; float cursorX = 0.0f; float cursorY = 0.0f; bool ignoreNextCharacter = false; int target = 0; for (int i = 0; i < str.Length && target < data.maxChars; ++i) { if (ignoreNextCharacter) { ignoreNextCharacter = false; continue; } int idx = str[i]; if (idx == '\n') { maxWidth = Mathf.Max(cursorX, maxWidth); cursorX = 0.0f; cursorY -= (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; continue; } else if (data.inlineStyling) { if (idx == '^' && i + 1 < str.Length) { if (str[i + 1] == '^') { ignoreNextCharacter = true; } else { int cmdLength = 0; switch (str[i + 1]) { case 'c': cmdLength = 5; break; case 'C': cmdLength = 9; break; case 'g': cmdLength = 9; break; case 'G': cmdLength = 17; break; } i += cmdLength; continue; } } } bool inlineHatChar = (idx == '^'); // Get the character from dictionary / array tk2dFontChar chr; if (_fontInst.useDictionary) { if (!_fontInst.charDict.ContainsKey(idx)) idx = 0; chr = _fontInst.charDict[idx]; } else { if (idx >= _fontInst.chars.Length) idx = 0; // should be space chr = _fontInst.chars[idx]; } if (inlineHatChar) idx = '^'; cursorX += (chr.advance + data.spacing) * data.scale.x; if (data.kerning && i < str.Length - 1) { foreach (var k in _fontInst.kerning) { if (k.c0 == str[i] && k.c1 == str[i+1]) { cursorX += k.amount * data.scale.x; break; } } } ++target; } maxWidth = Mathf.Max(cursorX, maxWidth); cursorY -= (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; return new Vector2(maxWidth, cursorY); }
public static void SetTextMeshIndices(int[] indices, int offset, int vStart, CurvedGeomData CurvedGeomData, int target) { tk2dCurvedTextMeshData data = CurvedGeomData.textMeshData; for (int i = 0; i < data.maxChars; ++i) { indices[offset + i * 6 + 0] = vStart + i * 4 + 0; indices[offset + i * 6 + 1] = vStart + i * 4 + 1; indices[offset + i * 6 + 2] = vStart + i * 4 + 3; indices[offset + i * 6 + 3] = vStart + i * 4 + 2; indices[offset + i * 6 + 4] = vStart + i * 4 + 0; indices[offset + i * 6 + 5] = vStart + i * 4 + 3; } }
public static int SetTextMeshGeom(Vector3[] pos, Vector2[] uv, Vector2[] uv2, Color32[] color, int offset, CurvedGeomData CurvedGeomData, float curveWidth = 0f, float curveStrength = 1f) { tk2dCurvedTextMeshData data = CurvedGeomData.textMeshData; tk2dFontData fontInst = CurvedGeomData.fontInst; string formattedText = CurvedGeomData.formattedText; meshTopColor = new Color32(255, 255, 255, 255); meshBottomColor = new Color32(255, 255, 255, 255); meshGradientTexU = (float)data.textureGradient / (float)((fontInst.gradientCount > 0) ? fontInst.gradientCount : 1); curGradientCount = fontInst.gradientCount; Vector2 dims = GetMeshDimensionsForString(CurvedGeomData.formattedText, CurvedGeomData); float offsetY = GetYAnchorForHeight(dims.y, CurvedGeomData); float cursorX = 0.0f; float cursorY = 0.0f; int target = 0; int alignStartTarget = 0; for (int i = 0; i < formattedText.Length && target < data.maxChars; ++i) { int idx = formattedText[i]; tk2dFontChar chr; bool inlineHatChar = (idx == '^'); if (fontInst.useDictionary) { if (!fontInst.charDict.ContainsKey(idx)) idx = 0; chr = fontInst.charDict[idx]; } else { if (idx >= fontInst.chars.Length) idx = 0; // should be space chr = fontInst.chars[idx]; } if (inlineHatChar) idx = '^'; if (idx == '\n') { float lineWidth = cursorX; int alignEndTarget = target; // this is one after the last filled character if (alignStartTarget != target) { float xOffset = GetXAnchorForWidth(lineWidth, CurvedGeomData); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } alignStartTarget = target; cursorX = 0.0f; cursorY -= (fontInst.lineHeight + data.lineSpacing) * data.scale.y; continue; } else if (data.inlineStyling) { if (idx == '^') { if (i + 1 < formattedText.Length && formattedText[i + 1] == '^') { ++i; } else { i += HandleStyleCommand(formattedText.Substring(i + 1)); continue; } } } pos[offset + target * 4 + 0] = new Vector3(cursorX + chr.p0.x * data.scale.x, offsetY + cursorY + chr.p0.y * data.scale.y, 0); pos[offset + target * 4 + 1] = new Vector3(cursorX + chr.p1.x * data.scale.x, offsetY + cursorY + chr.p0.y * data.scale.y, 0); pos[offset + target * 4 + 2] = new Vector3(cursorX + chr.p0.x * data.scale.x, offsetY + cursorY + chr.p1.y * data.scale.y, 0); pos[offset + target * 4 + 3] = new Vector3(cursorX + chr.p1.x * data.scale.x, offsetY + cursorY + chr.p1.y * data.scale.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(meshGradientTexU, 0); uv2[offset + target * 4 + 1] = chr.gradientUv[1] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 2] = chr.gradientUv[2] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 3] = chr.gradientUv[3] + new Vector2(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] = meshTopColor; color[offset + target * 4 + 1] = meshTopColor; color[offset + target * 4 + 2] = meshBottomColor; color[offset + target * 4 + 3] = meshBottomColor; } cursorX += (chr.advance + data.spacing) * data.scale.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.scale.x; break; } } } ++target; } if (alignStartTarget != target) { float lineWidth = cursorX; int alignEndTarget = target; float xOffset = GetXAnchorForWidth(lineWidth, CurvedGeomData); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); if(curveWidth != 0) ApplyTextCurve(pos, offset, alignStartTarget, alignEndTarget, curveWidth, curveStrength); } for (int i = target; i < data.maxChars; ++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; } if (!fontInst.isPacked) { color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = meshTopColor; color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = meshBottomColor; } else { color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = Color.clear; } } return target; }
public static float GetYAnchorForHeight(float textHeight, CurvedGeomData CurvedGeomData) { tk2dCurvedTextMeshData data = CurvedGeomData.textMeshData; tk2dFontData _fontInst = CurvedGeomData.fontInst; int heightAnchor = (int)data.anchor / 3; float lineHeight = (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; switch (heightAnchor) { case 0: return -lineHeight; case 1: { float y = -textHeight / 2.0f - lineHeight; if (_fontInst.version >= 2) { float ty = _fontInst.texelSize.y * data.scale.y; return Mathf.Floor(y / ty) * ty; } else return y; } case 2: return -textHeight - lineHeight; } return -lineHeight; }
public static float GetXAnchorForWidth(float lineWidth, CurvedGeomData CurvedGeomData) { tk2dCurvedTextMeshData data = CurvedGeomData.textMeshData; tk2dFontData _fontInst = CurvedGeomData.fontInst; int widthAnchor = (int)data.anchor % 3; switch (widthAnchor) { case 0: return 0.0f; // left case 1: // center { float x = -lineWidth / 2.0f; if (_fontInst.version >= 2) { float tx = _fontInst.texelSize.x * data.scale.x; return Mathf.Floor(x / tx) * tx; } return x; } case 2: return -lineWidth; // right } return 0.0f; }
public static void GetTextMeshGeomDesc(out int numVertices, out int numIndices, CurvedGeomData CurvedGeomData) { tk2dCurvedTextMeshData data = CurvedGeomData.textMeshData; numVertices = data.maxChars * 4; numIndices = data.maxChars * 6; }