/// <summary> /// Lines the size. /// </summary> /// <returns>The size.</returns> /// <param name="vtext">Vtext.</param> /// <param name="str">String.</param> public Vector2 LineSize(VTextInterface vtext, string str) { float xmax = 0.0f; float ymax = 0.0f; float lw = 0.0f; float lh = 0.0f; if (vtext.layout.Horizontal) { Vector2 kern = new Vector2(0f, 0f); char prev = '\0'; for (int i = 0; i < str.Length; i++) { VGlyphInfo gi = FetchGlyphInfo(m_glyphs, str[i]); if (null != gi) { if ('\0' != prev) { kern = Kerning(prev, str[i]); } if (i < str.Length - 1) { lw += gi.advance.x + kern.x; } else { lw += gi.size.x + kern.x; } lh = gi.advance.y + kern.y; if (ymax < lh) { ymax = lh; } prev = str[i]; } } // Debug.Log(" width " + lw); if (lw > xmax) { xmax = lw; } } else // vertical layout { for (int i = 0; i < str.Length; i++) { VGlyphInfo gi = FetchGlyphInfo(m_glyphs, str[i]); if (null != gi) { lh += gi.advance.y; } } ymax = lh; lw = GetAscender(m_fontHandle); // Debug.Log(" Ascender width " + lw); xmax = lw; } return(new Vector2(xmax * vtext.layout.Size, ymax * vtext.layout.Size)); }
/// <summary> /// Fetchs the glyph info. /// </summary> /// <returns>The glyph info.</returns> /// <param name="glyphs">Glyphs.</param> /// <param name="c">C.</param> protected VGlyphInfo FetchGlyphInfo(Hashtable glyphs, char c) { if (((int)c) > 16) { if (!glyphs.ContainsKey(c)) { VGlyphInfo gi = new VGlyphInfo(m_fontHandle, c); glyphs.Add(c, gi); } if (glyphs.ContainsKey(c)) { VGlyphInfo gi = (VGlyphInfo)glyphs[c]; return(gi); } } return(null); }
/// <summary> /// Creates the text /// /// based on settings in VTextInterface /// </summary> /// <param name="vtext">Vtext.</param> /// <param name="str">String.</param> protected void CreateText(VTextInterface vtext, string str, bool layoutOnly) { if (System.IntPtr.Zero == m_fontHandle) { return; } if (null == m_glyphs) { m_glyphs = new Hashtable(); } // Debug.Log("Font info create text " + str); float xoffset = 0.0f; float yoffset = 0.0f; float ascender = GetAscender(m_fontHandle); // float descender = GetDescender(m_fontHandle); // Debug.Log(ascender + " descender " + descender); float xSpacing = ascender * vtext.layout.Spacing; float ySpacing = 0.0f; // Debug.Log("*** yoff " + yoffset + " " + ySpacing); string[] sa = str.Split('\n'); //Debug.Log(sa.Length + " lines in text " + str); Vector2 glyphShift = new Vector2(-glyphMinX, -glyphMinY); Vector2 maxGlyphSize = new Vector2(glyphMaxX - glyphMinX, glyphMaxY - glyphMinY); // calculate linesizes and total Vector2 [] linesizes = new Vector2[sa.Length]; float maxWidth = 0.0f; float maxHeight = 0.0f; Vector2 kern = new Vector2(0f, 0f); Vector3 locpos = new Vector3(0f, 0f, 0f); Vector3 locScale = new Vector3(vtext.layout.Size, vtext.layout.Size, vtext.layout.Size); // calc bounds for (int k = 0; k < sa.Length; k++) { linesizes[k] = LineSize(vtext, sa[k]); if (sa[k].Length > 0) { float h = linesizes[k].y * vtext.layout.Spacing; if (h > ySpacing) { ySpacing = h; // Debug.Log(k + " *** ysize " + linesizes[k].y + " " + ySpacing); } } if (vtext.layout.Horizontal) { if (linesizes[k].x > maxWidth) { maxWidth = linesizes[k].x; } maxHeight += linesizes[k].y; } else { maxWidth += linesizes[k].x; if (linesizes[k].y > maxHeight) { maxHeight = linesizes[k].y; } } } float startX = 0.0f; // Debug.Log("text size " + maxWidth + " " + maxHeight); // now create/layout meshes line by line int childIndex = 0; for (int k = 0; k < sa.Length; k++) { if (vtext.layout.Horizontal) { switch (vtext.layout.Major) { case VTextLayout.align.Base: xoffset = 0.0f; break; case VTextLayout.align.Center: xoffset = (-linesizes[k].x * 0.5f); startX = -maxWidth * 0.5f; break; case VTextLayout.align.End: xoffset = -linesizes[k].x; startX = -maxWidth; break; case VTextLayout.align.Start: xoffset = 0.0f; break; } switch (vtext.layout.Minor) { case VTextLayout.align.Base: yoffset = 0.0f; break; case VTextLayout.align.Center: yoffset = (maxHeight * 0.5f - ascender); break; case VTextLayout.align.End: yoffset = (maxHeight - ascender); break; case VTextLayout.align.Start: yoffset = -ascender * vtext.layout.Size; break; } yoffset -= k * ySpacing; // Debug.Log(k + " yoff " + yoffset + " " + ySpacing); } else // vertical { switch (vtext.layout.Major) { case VTextLayout.align.Base: yoffset = 0.0f; break; case VTextLayout.align.Center: yoffset = linesizes[k].y * 0.5f; break; case VTextLayout.align.End: yoffset = linesizes[k].y - ascender; break; case VTextLayout.align.Start: yoffset = 0.0f; break; } switch (vtext.layout.Minor) { case VTextLayout.align.Base: xoffset = 0.0f; break; case VTextLayout.align.Center: xoffset = -maxWidth * 0.5f; break; case VTextLayout.align.End: xoffset = -maxWidth; break; case VTextLayout.align.Start: xoffset = 0.0f; break; } xoffset += k * xSpacing; // Debug.Log(k + " xoff " + xoffset + " " + xSpacing); } char c; char prev = '\0'; float adjustX = 0.0f; for (int j = 0; j < sa[k].Length; j++) { c = sa[k][j]; if (c >= ' ') { if (m_glyphs.ContainsKey(c)) { VGlyphInfo gi = (VGlyphInfo)m_glyphs[c]; if (!vtext.layout.Horizontal) { // adjust x to center of glyph adjustX = (((xSpacing - gi.size.x) * 0.5f) - gi.horizontalBearing.x) * vtext.layout.Size; // Debug.Log(gi.horizontalBearing + " adjust " + adjustX + " sz " + gi.size.x); } if ('\0' != prev) { if (vtext.layout.Horizontal) { // only horizontal kerning adjust! kern = Kerning(prev, c); } } if (c > ' ') { // no GameObject for space string gname = ("G" + k + "_" + j + "_" + c); GameObject go = null; if (layoutOnly) { go = vtext.transform.GetChild(childIndex).gameObject; if (go.name != gname) { Debug.LogWarning(go.name + " != " + gname); } childIndex++; } else { go = new GameObject(gname); } locpos.x = xoffset + adjustX + kern.x; float normX = (maxWidth > 0f) ? (locpos.x - startX) / maxWidth : 0f; //Debug.Log("normX: " + normX + " startX " + startX + " locX " + locpos.x + " maxw " + maxWidth); float y0 = vtext.layout.CurveXY.Evaluate(normX); locpos.y = yoffset + kern.y + y0; float z0 = vtext.layout.CurveXZ.Evaluate(normX); locpos.z = z0; Quaternion orient = new Quaternion(0f, 0f, 0f, 1f); const float txDelta = 0.01f; float x1 = normX + txDelta; if (maxWidth > 0.0f) { if (vtext.layout.OrientationXY) { float y1 = vtext.layout.CurveXY.Evaluate(x1); float dY = (y1 - y0) / maxWidth; float rotZ = Mathf.Atan2(dY, txDelta); orient *= Quaternion.AngleAxis(Mathf.Rad2Deg * rotZ, new Vector3(0f, 0f, 1f)); } if (vtext.layout.OrientationXZ) { float z1 = vtext.layout.CurveXZ.Evaluate(x1); float dZ = (z1 - z0) / maxWidth; float rotY = Mathf.Atan2(dZ, txDelta); orient *= Quaternion.AngleAxis(Mathf.Rad2Deg * rotY, new Vector3(0f, -1f, 0f)); } if (vtext.layout.OrientationCircular) { //---------------------Artur isz here----------------------------------------------------------------< normX *= maxWidth; normX += gi.advance.x * 0.5f; normX = normX / maxWidth; float angle = Mathf.Lerp(-vtext.layout.StartRadius, -vtext.layout.EndRadius, normX); Quaternion rot = Quaternion.AngleAxis(angle, new Vector3(0f, 1f, 0f)); locpos.x = 0.0f; float fac = vtext.layout.CircleRadius * vtext.layout.Size; if (vtext.layout.AnimateRadius) { fac *= vtext.layout.CurveRadius.Evaluate(normX); } locpos += (rot * new Vector3(0.0f, 0.0f, -1.0f)) * fac; //locpos += (rot * new Vector3(-gi.advance.x * 0.5f, 0.0f, 0.0f)); locpos += (rot * new Vector3(-gi.advance.x * 0.5f, 0.0f, 0.0f)); orient *= rot; //---------------------Artur woz here----------------------------------------------------------------< } } if (!layoutOnly) { go.transform.parent = vtext.transform; } go.transform.localPosition = locpos; go.transform.localRotation = orient; go.transform.localScale = locScale; go.layer = vtext.gameObject.layer; go.isStatic = vtext.gameObject.isStatic; if (layoutOnly) { MeshRenderer mr = go.GetComponent <MeshRenderer>(); #if UNITY_5 mr.shadowCastingMode = vtext.layout.ShadowCastMode; #else mr.castShadows = vtext.layout.CastShadows; #endif mr.receiveShadows = vtext.layout.ReceiveShadows; mr.useLightProbes = vtext.layout.UseLightProbes; } else { Mesh mesh = gi.GetMesh(glyphShift, maxGlyphSize, vtext, GetAscender(m_fontHandle)); if (null != mesh) { go.AddComponent(typeof(MeshFilter)); go.AddComponent(typeof(MeshRenderer)); MeshFilter mf = go.GetComponent <MeshFilter>(); mf.sharedMesh = mesh; MeshRenderer mr = go.GetComponent <MeshRenderer>(); mr.sharedMaterials = vtext.materials; #if UNITY_5 mr.shadowCastingMode = vtext.layout.ShadowCastMode; #else mr.castShadows = vtext.layout.CastShadows; #endif mr.receiveShadows = vtext.layout.ReceiveShadows; mr.useLightProbes = vtext.layout.UseLightProbes; } else { Debug.LogWarning(gname + " no mesh"); } } } prev = c; if (vtext.layout.Horizontal) { xoffset += gi.advance.x * vtext.layout.Size; } else { yoffset -= gi.advance.y * vtext.layout.Size; adjustX = 0.0f; } } else { Debug.LogWarning("\"" + c + "\" not in glyphs"); } } } } }