123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- #if FAIRYGUI_TMPRO
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.TextCore;
- using TMPro;
- namespace FairyGUI
- {
- /// <summary>
- /// TextMeshPro text adapter for FairyGUI. Most of codes were taken from TextMeshPro!
- /// Note that not all of TextMeshPro features are supported.
- /// </summary>
- public class TMPFont : BaseFont
- {
- protected TMP_FontAsset _fontAsset;
- FontStyles _style;
- float _scale;
- float _padding;
- float _stylePadding;
- float _ascent;
- float _lineHeight;
- float _boldMultiplier;
- FontWeight _defaultFontWeight;
- FontWeight _fontWeight;
- TextFormat _format;
- TMP_Character _char;
- TMP_Character _lineChar;
- Material _material;
- MaterialManager _manager;
- public TMPFont()
- {
- this.canTint = true;
- this.shader = "FairyGUI/TextMeshPro/Distance Field";
- this.keepCrisp = true;
- _defaultFontWeight = FontWeight.Medium;
- }
- override public void Dispose()
- {
- Release();
- }
- public TMP_FontAsset fontAsset
- {
- get { return _fontAsset; }
- set
- {
- _fontAsset = value;
- Init();
- }
- }
- public FontWeight fontWeight
- {
- get { return _defaultFontWeight; }
- set { _defaultFontWeight = value; }
- }
- void Release()
- {
- if (_manager != null)
- {
- _manager.onCreateNewMaterial -= OnCreateNewMaterial;
- _manager = null;
- }
- if (mainTexture != null)
- {
- mainTexture.Dispose();
- mainTexture = null;
- }
- if (_material != null)
- {
- Material.DestroyImmediate(_material);
- _material = null;
- }
- }
- void Init()
- {
- Release();
- mainTexture = new NTexture(_fontAsset.atlasTexture);
- mainTexture.destroyMethod = DestroyMethod.None;
- _manager = mainTexture.GetMaterialManager(this.shader);
- _manager.onCreateNewMaterial += OnCreateNewMaterial;
- _material = new Material(_fontAsset.material); //copy
- _material.SetFloat(ShaderUtilities.ID_TextureWidth, mainTexture.width);
- _material.SetFloat(ShaderUtilities.ID_TextureHeight, mainTexture.height);
- _material.SetFloat(ShaderUtilities.ID_GradientScale, fontAsset.atlasPadding + 1);
- _material.SetFloat(ShaderUtilities.ID_WeightNormal, fontAsset.normalStyle);
- _material.SetFloat(ShaderUtilities.ID_WeightBold, fontAsset.boldStyle);
- // _ascent = _fontAsset.faceInfo.ascentLine;
- // _lineHeight = _fontAsset.faceInfo.lineHeight;
- _ascent = _fontAsset.faceInfo.pointSize;
- _lineHeight = _fontAsset.faceInfo.pointSize * 1.25f;
- _lineChar = GetCharacterFromFontAsset('_', FontStyles.Normal);
- }
- void OnCreateNewMaterial(Material mat)
- {
- mat.SetFloat(ShaderUtilities.ID_TextureWidth, mainTexture.width);
- mat.SetFloat(ShaderUtilities.ID_TextureHeight, mainTexture.height);
- mat.SetFloat(ShaderUtilities.ID_GradientScale, fontAsset.atlasPadding + 1);
- mat.SetFloat(ShaderUtilities.ID_WeightNormal, fontAsset.normalStyle);
- mat.SetFloat(ShaderUtilities.ID_WeightBold, fontAsset.boldStyle);
- }
- override public void UpdateGraphics(NGraphics graphics)
- {
- MaterialPropertyBlock block = graphics.materialPropertyBlock;
- if (_format.outline > 0)
- {
- graphics.ToggleKeyword("OUTLINE_ON", true);
- block.SetFloat(ShaderUtilities.ID_OutlineWidth, _format.outline);
- block.SetColor(ShaderUtilities.ID_OutlineColor, _format.outlineColor);
- }
- else
- {
- graphics.ToggleKeyword("OUTLINE_ON", false);
- block.SetFloat(ShaderUtilities.ID_OutlineWidth, 0);
- }
- if (_format.shadowOffset.x != 0 || _format.shadowOffset.y != 0)
- {
- graphics.ToggleKeyword("UNDERLAY_ON", true);
- block.SetColor(ShaderUtilities.ID_UnderlayColor, _format.shadowColor);
- block.SetFloat(ShaderUtilities.ID_UnderlayOffsetX, _format.shadowOffset.x);
- block.SetFloat(ShaderUtilities.ID_UnderlayOffsetY, -_format.shadowOffset.y);
- block.SetFloat(ShaderUtilities.ID_UnderlaySoftness, _format.underlaySoftness);
- }
- else
- {
- graphics.ToggleKeyword("UNDERLAY_ON", false);
- block.SetFloat(ShaderUtilities.ID_UnderlayOffsetX, 0);
- block.SetFloat(ShaderUtilities.ID_UnderlayOffsetY, 0);
- block.SetFloat(ShaderUtilities.ID_UnderlaySoftness, 0);
- }
- block.SetFloat(ShaderUtilities.ID_FaceDilate, _format.faceDilate);
- block.SetFloat(ShaderUtilities.ID_OutlineSoftness, _format.outlineSoftness);
- if (_material.HasProperty(ShaderUtilities.ID_ScaleRatio_A))
- {
- //ShaderUtilities.GetPadding does not support handle materialproperyblock, we have to use a temp material
- _material.SetFloat(ShaderUtilities.ID_OutlineWidth, block.GetFloat(ShaderUtilities.ID_OutlineWidth));
- _material.SetFloat(ShaderUtilities.ID_UnderlayOffsetX, block.GetFloat(ShaderUtilities.ID_UnderlayOffsetX));
- _material.SetFloat(ShaderUtilities.ID_UnderlayOffsetY, block.GetFloat(ShaderUtilities.ID_UnderlayOffsetY));
- _material.SetFloat(ShaderUtilities.ID_UnderlaySoftness, block.GetFloat(ShaderUtilities.ID_UnderlaySoftness));
- _material.SetFloat(ShaderUtilities.ID_FaceDilate, block.GetFloat(ShaderUtilities.ID_FaceDilate));
- _material.SetFloat(ShaderUtilities.ID_OutlineSoftness, block.GetFloat(ShaderUtilities.ID_OutlineSoftness));
- _padding = ShaderUtilities.GetPadding(_material, false, false);
- //and then set back the properteis
- block.SetFloat(ShaderUtilities.ID_ScaleRatio_A, _material.GetFloat(ShaderUtilities.ID_ScaleRatio_A));
- block.SetFloat(ShaderUtilities.ID_ScaleRatio_B, _material.GetFloat(ShaderUtilities.ID_ScaleRatio_B));
- block.SetFloat(ShaderUtilities.ID_ScaleRatio_C, _material.GetFloat(ShaderUtilities.ID_ScaleRatio_C));
- }
- // Set Padding based on selected font style
- #region Handle Style Padding
- if (((_style & FontStyles.Bold) == FontStyles.Bold)) // Checks for any combination of Bold Style.
- {
- if (_material.HasProperty(ShaderUtilities.ID_GradientScale))
- {
- float gradientScale = _material.GetFloat(ShaderUtilities.ID_GradientScale);
- _stylePadding = _fontAsset.boldStyle / 4.0f * gradientScale * _material.GetFloat(ShaderUtilities.ID_ScaleRatio_A);
- // Clamp overall padding to Gradient Scale size.
- if (_stylePadding + _padding > gradientScale)
- _padding = gradientScale - _stylePadding;
- }
- else
- _stylePadding = 0;
- }
- else
- {
- if (_material.HasProperty(ShaderUtilities.ID_GradientScale))
- {
- float gradientScale = _material.GetFloat(ShaderUtilities.ID_GradientScale);
- _stylePadding = _fontAsset.normalStyle / 4.0f * gradientScale * _material.GetFloat(ShaderUtilities.ID_ScaleRatio_A);
- // Clamp overall padding to Gradient Scale size.
- if (_stylePadding + _padding > gradientScale)
- _padding = gradientScale - _stylePadding;
- }
- else
- _stylePadding = 0;
- }
- #endregion Handle Style Padding
- }
- override public void SetFormat(TextFormat format, float fontSizeScale)
- {
- _format = format;
- float size = format.size * fontSizeScale;
- if (_format.specialStyle == TextFormat.SpecialStyle.Subscript || _format.specialStyle == TextFormat.SpecialStyle.Superscript)
- size *= SupScale;
- _scale = size / _fontAsset.faceInfo.pointSize * _fontAsset.faceInfo.scale;
- _style = FontStyles.Normal;
- if (format.bold)
- {
- _style |= FontStyles.Bold;
- _fontWeight = FontWeight.Bold;
- _boldMultiplier = 1 + _fontAsset.boldSpacing * 0.01f;
- }
- else
- {
- _fontWeight = _defaultFontWeight;
- _boldMultiplier = 1.0f;
- }
- if (format.italic)
- _style |= FontStyles.Italic;
- format.FillVertexColors(vertexColors);
- }
- override public bool GetGlyph(char ch, out float width, out float height, out float baseline)
- {
- _char = GetCharacterFromFontAsset(ch, _style);
- if (_char != null)
- {
- width = _char.glyph.metrics.horizontalAdvance * _boldMultiplier * _scale;
- height = _lineHeight * _scale;
- baseline = _ascent * _scale;
- if (_format.specialStyle == TextFormat.SpecialStyle.Subscript)
- {
- height /= SupScale;
- baseline /= SupScale;
- }
- else if (_format.specialStyle == TextFormat.SpecialStyle.Superscript)
- {
- height = height / SupScale + baseline * SupOffset;
- baseline *= (SupOffset + 1 / SupScale);
- }
- height = Mathf.RoundToInt(height);
- baseline = Mathf.RoundToInt(baseline);
- return true;
- }
- else
- {
- width = 0;
- height = 0;
- baseline = 0;
- return false;
- }
- }
- TMP_Character GetCharacterFromFontAsset(uint unicode, FontStyles fontStyle)
- {
- bool isAlternativeTypeface;
- #pragma warning disable
- TMP_FontAsset actualAsset;
- #pragma warning restore
- return TMP_FontAssetUtilities.GetCharacterFromFontAsset(unicode, _fontAsset, true, fontStyle, _fontWeight,
- out isAlternativeTypeface
- //,out actualAsset //old TMP version need this line
- );
- }
- static Vector3 bottomLeft;
- static Vector3 topLeft;
- static Vector3 topRight;
- static Vector3 bottomRight;
- static Vector4 uvBottomLeft;
- static Vector4 uvTopLeft;
- static Vector4 uvTopRight;
- static Vector4 uvBottomRight;
- static Vector4 uv2BottomLeft;
- static Vector4 uv2TopLeft;
- static Vector4 uv2TopRight;
- static Vector4 uv2BottomRight;
- static Color32[] vertexColors = new Color32[4];
- override public int DrawGlyph(float x, float y,
- List<Vector3> vertList, List<Vector2> uvList, List<Vector2> uv2List, List<Color32> colList)
- {
- GlyphMetrics metrics = _char.glyph.metrics;
- GlyphRect rect = _char.glyph.glyphRect;
- if (_format.specialStyle == TextFormat.SpecialStyle.Subscript)
- y = y - Mathf.RoundToInt(_ascent * _scale * SupOffset);
- else if (_format.specialStyle == TextFormat.SpecialStyle.Superscript)
- y = y + Mathf.RoundToInt(_ascent * _scale * (1 / SupScale - 1 + SupOffset));
- topLeft.x = x + (metrics.horizontalBearingX - _padding - _stylePadding) * _scale;
- topLeft.y = y + (metrics.horizontalBearingY + _padding) * _scale;
- bottomRight.x = topLeft.x + (metrics.width + _padding * 2 + _stylePadding * 2) * _scale;
- bottomRight.y = topLeft.y - (metrics.height + _padding * 2) * _scale;
- topRight.x = bottomRight.x;
- topRight.y = topLeft.y;
- bottomLeft.x = topLeft.x;
- bottomLeft.y = bottomRight.y;
- #region Handle Italic & Shearing
- if (((_style & FontStyles.Italic) == FontStyles.Italic))
- {
- // Shift Top vertices forward by half (Shear Value * height of character) and Bottom vertices back by same amount.
- float shear_value = _fontAsset.italicStyle * 0.01f;
- Vector3 topShear = new Vector3(shear_value * ((metrics.horizontalBearingY + _padding + _stylePadding) * _scale), 0, 0);
- Vector3 bottomShear = new Vector3(shear_value * (((metrics.horizontalBearingY - metrics.height - _padding - _stylePadding)) * _scale), 0, 0);
- topLeft += topShear;
- bottomLeft += bottomShear;
- topRight += topShear;
- bottomRight += bottomShear;
- }
- #endregion Handle Italics & Shearing
- vertList.Add(bottomLeft);
- vertList.Add(topLeft);
- vertList.Add(topRight);
- vertList.Add(bottomRight);
- float u = (rect.x - _padding - _stylePadding) / _fontAsset.atlasWidth;
- float v = (rect.y - _padding - _stylePadding) / _fontAsset.atlasHeight;
- float uw = (rect.width + _padding * 2 + _stylePadding * 2) / _fontAsset.atlasWidth;
- float vw = (rect.height + _padding * 2 + _stylePadding * 2) / _fontAsset.atlasHeight;
- uvBottomLeft = new Vector2(u, v);
- uvTopLeft = new Vector2(u, v + vw);
- uvTopRight = new Vector2(u + uw, v + vw);
- uvBottomRight = new Vector2(u + uw, v);
- float xScale = _scale * 0.01f;
- if (_format.bold)
- xScale *= -1;
- uv2BottomLeft = new Vector2(0, xScale);
- uv2TopLeft = new Vector2(511, xScale);
- uv2TopRight = new Vector2(2093567, xScale);
- uv2BottomRight = new Vector2(2093056, xScale);
- uvList.Add(uvBottomLeft);
- uvList.Add(uvTopLeft);
- uvList.Add(uvTopRight);
- uvList.Add(uvBottomRight);
- uv2List.Add(uv2BottomLeft);
- uv2List.Add(uv2TopLeft);
- uv2List.Add(uv2TopRight);
- uv2List.Add(uv2BottomRight);
- colList.Add(vertexColors[0]);
- colList.Add(vertexColors[1]);
- colList.Add(vertexColors[2]);
- colList.Add(vertexColors[3]);
- return 4;
- }
- override public int DrawLine(float x, float y, float width, int fontSize, int type,
- List<Vector3> vertList, List<Vector2> uvList, List<Vector2> uv2List, List<Color32> colList)
- {
- if (_lineChar == null)
- return 0;
- float thickness;
- float offset;
- if (type == 0)
- {
- thickness = _fontAsset.faceInfo.underlineThickness;
- offset = _fontAsset.faceInfo.underlineOffset;
- }
- else
- {
- thickness = _fontAsset.faceInfo.strikethroughThickness;
- offset = _fontAsset.faceInfo.strikethroughOffset;
- }
- float scale = (float)fontSize / _fontAsset.faceInfo.pointSize * _fontAsset.faceInfo.scale;
- float segmentWidth = _lineChar.glyph.metrics.width / 2 * scale;
- if (width < _lineChar.glyph.metrics.width * scale)
- segmentWidth = width / 2f;
- // UNDERLINE VERTICES FOR (3) LINE SEGMENTS
- #region UNDERLINE VERTICES
- thickness = thickness * scale;
- if (thickness < 1)
- thickness = 1;
- offset = Mathf.RoundToInt(offset * scale);
- // Front Part of the Underline
- y += offset;
- topLeft.x = x;
- topLeft.y = y + _padding * scale;
- bottomRight.x = x + segmentWidth;
- bottomRight.y = y - thickness - _padding * scale;
- topRight.x = bottomRight.x;
- topRight.y = topLeft.y;
- bottomLeft.x = topLeft.x;
- bottomLeft.y = bottomRight.y;
- vertList.Add(bottomLeft);
- vertList.Add(topLeft);
- vertList.Add(topRight);
- vertList.Add(bottomRight);
- // Middle Part of the Underline
- topLeft = topRight;
- bottomLeft = bottomRight;
- topRight.x = x + width - segmentWidth;
- bottomRight.x = topRight.x;
- vertList.Add(bottomLeft);
- vertList.Add(topLeft);
- vertList.Add(topRight);
- vertList.Add(bottomRight);
- // End Part of the Underline
- topLeft = topRight;
- bottomLeft = bottomRight;
- topRight.x = x + width;
- bottomRight.x = topRight.x;
- vertList.Add(bottomLeft);
- vertList.Add(topLeft);
- vertList.Add(topRight);
- vertList.Add(bottomRight);
- #endregion
- // UNDERLINE UV0
- #region HANDLE UV0
- // Calculate UV required to setup the 3 Quads for the Underline.
- Vector2 uv0 = new Vector2((_lineChar.glyph.glyphRect.x - _padding) / _fontAsset.atlasWidth, (_lineChar.glyph.glyphRect.y - _padding) / _fontAsset.atlasHeight); // bottom left
- Vector2 uv1 = new Vector2(uv0.x, (_lineChar.glyph.glyphRect.y + _lineChar.glyph.glyphRect.height + _padding) / _fontAsset.atlasHeight); // top left
- Vector2 uv2 = new Vector2((_lineChar.glyph.glyphRect.x - _padding + (float)_lineChar.glyph.glyphRect.width / 2) / _fontAsset.atlasWidth, uv1.y); // Mid Top Left
- Vector2 uv3 = new Vector2(uv2.x, uv0.y); // Mid Bottom Left
- Vector2 uv4 = new Vector2((_lineChar.glyph.glyphRect.x + _padding + (float)_lineChar.glyph.glyphRect.width / 2) / _fontAsset.atlasWidth, uv1.y); // Mid Top Right
- Vector2 uv5 = new Vector2(uv4.x, uv0.y); // Mid Bottom right
- Vector2 uv6 = new Vector2((_lineChar.glyph.glyphRect.x + _padding + _lineChar.glyph.glyphRect.width) / _fontAsset.atlasWidth, uv1.y); // End Part - Bottom Right
- Vector2 uv7 = new Vector2(uv6.x, uv0.y); // End Part - Top Right
- uvList.Add(uv0);
- uvList.Add(uv1);
- uvList.Add(uv2);
- uvList.Add(uv3);
- // Middle Part of the Underline
- uvList.Add(new Vector2(uv2.x - uv2.x * 0.001f, uv0.y));
- uvList.Add(new Vector2(uv2.x - uv2.x * 0.001f, uv1.y));
- uvList.Add(new Vector2(uv2.x + uv2.x * 0.001f, uv1.y));
- uvList.Add(new Vector2(uv2.x + uv2.x * 0.001f, uv0.y));
- // Right Part of the Underline
- uvList.Add(uv5);
- uvList.Add(uv4);
- uvList.Add(uv6);
- uvList.Add(uv7);
- #endregion
- // UNDERLINE UV2
- #region HANDLE UV2 - SDF SCALE
- // UV1 contains Face / Border UV layout.
- float segUv1 = segmentWidth / width;
- float segUv2 = 1 - segUv1;
- //Calculate the xScale or how much the UV's are getting stretched on the X axis for the middle section of the underline.
- float xScale = scale * 0.01f;
- uv2List.Add(PackUV(0, 0, xScale));
- uv2List.Add(PackUV(0, 1, xScale));
- uv2List.Add(PackUV(segUv1, 1, xScale));
- uv2List.Add(PackUV(segUv1, 0, xScale));
- uv2List.Add(PackUV(segUv1, 0, xScale));
- uv2List.Add(PackUV(segUv1, 1, xScale));
- uv2List.Add(PackUV(segUv2, 1, xScale));
- uv2List.Add(PackUV(segUv2, 0, xScale));
- uv2List.Add(PackUV(segUv2, 0, xScale));
- uv2List.Add(PackUV(segUv2, 1, xScale));
- uv2List.Add(PackUV(1, 1, xScale));
- uv2List.Add(PackUV(1, 0, xScale));
- #endregion
- // UNDERLINE VERTEX COLORS
- #region
- // Alpha is the lower of the vertex color or tag color alpha used.
- for (int i = 0; i < 12; i++)
- colList.Add(vertexColors[0]);
- #endregion
- return 12;
- }
- Vector2 PackUV(float x, float y, float xScale)
- {
- double x0 = (int)(x * 511);
- double y0 = (int)(y * 511);
- return new Vector2((float)((x0 * 4096) + y0), xScale);
- }
- override public bool HasCharacter(char ch)
- {
- return _fontAsset.HasCharacter(ch);
- }
- override public int GetLineHeight(int size)
- {
- return Mathf.RoundToInt(_lineHeight * ((float)size / _fontAsset.faceInfo.pointSize * _fontAsset.faceInfo.scale));
- }
- }
- }
- #endif
|