美文网首页
FairyGUI对TextMeshPro的fallback fo

FairyGUI对TextMeshPro的fallback fo

作者: 不正经的搬砖工 | 来源:发表于2022-03-04 11:12 被阅读0次

最近项目中某些文字效果,使用TextMeshPro能更好、更快速的实现,看FairyGUI对TextMeshPro也有了支持,就决定使用了。项目中涉及多语言,但给的字体库不支持中文,只能使用备用字体库,看TMP中有个Fallback Font Assets(如图1-1),以为就可以这么愉快的搞定了,奈何FairyGUI并不支持这个特性,求助FairyGUI官网群也无果,只能自己解决了。

图 1-1 Fallback Font Assets

看了一下UGUI中对这一特性的支持,它就是额外创建了一个TMP_SubMeshUI使用备用字体绘制文本。

图 1-2 UGUI中对TMP Fallback的支持 

(1)参照这个思路,在FairyGUI中创建一个GSubTextField使用备用字体绘制文本,GSubTextField基本上就是GTextField的拷贝,只是对Setup_BeforeAdd做了一些改动,当创建GSubTextField时,完全用GTextField的各种属性设置GSubTextField。由于TMP_FontAsset中的fallbackFontAssets为私有属性无法访问,我直接在GSubTextField中手动设置了备用字体。代码如下:

public void Setup_BeforeAdd(TextFormat ptf, GTextField gtf)

        {

            SetXY(gtf.x, gtf.y);

            SetSize(gtf.width, gtf.height, true);

            minWidth = gtf.minWidth;

            maxWidth = gtf.maxWidth;

            minHeight = gtf.minHeight;

            maxHeight = gtf.maxHeight;

            SetScale(gtf.scaleX, gtf.scaleY);

            this.skew = gtf.skew;

            SetPivot(gtf.pivot.x, gtf.pivot.y, gtf.pivotAsAnchor);

            this.alpha = gtf.alpha;

            this.rotation = gtf.rotation;

            this.visible = gtf.visible;

            this.touchable = false;

            this.grayed = gtf.grayed;

            this.blendMode = gtf.blendMode;

            TextFormat tf = _textField.textFormat;

            tf.font = UIConfig.defaultFont;

            tf.size = ptf.size;

            tf.color = ptf.color;

            this.align = gtf.align;

            this.verticalAlign = gtf.verticalAlign;

            tf.lineSpacing = ptf.lineSpacing;

            tf.letterSpacing = ptf.letterSpacing;

            _ubbEnabled = gtf.UBBEnabled;

            this.autoSize = gtf.autoSize;

            tf.underline = ptf.underline;

            tf.italic = ptf.italic;

            tf.bold = ptf.bold;

            this.singleLine = gtf.singleLine;

            tf.outlineColor = ptf.outlineColor;

            tf.outline = ptf.outline;

            tf.shadowColor = ptf.shadowColor;

            tf.shadowOffset = new Vector2(ptf.shadowOffset.x, ptf.shadowOffset.y);

            if(gtf.templateVars != null)

                _templateVars = new Dictionary<string, string>();

            tf.strikethrough = ptf.strikethrough;

            tf.faceDilate = ptf.faceDilate;

            tf.outlineSoftness = ptf.outlineSoftness;

            tf.underlaySoftness = ptf.underlaySoftness;

            _textField.textFormat = tf;

            SetUnderlayDilate(ptf.underlayDilate);

        }

(2)GTextField中实现创建GSubTextField的接口和刷新文字的接口:如下所示:

#if FAIRYGUI_TMPRO

        public void CreateSubTextField()

        {

            if (_subGTextField == null)

            {

                _subGTextField = new GSubTextField();

                _subGTextField.Setup_BeforeAdd(_textField.textFormat, this);

                _subGTextField.relations.CopyFrom(this.relations);

                if (parent!=null)

                {

                    parent.AddChild(_subGTextField);

                }

            }

        }

        public void RefreshSubText()

        {

            if (_subGTextField != null)

            {

                if (_text.Equals(_subGTextField.text) == false)

                {

                    _subGTextField.text = _text;

                }

            }

        }

#endif

(3)FairyGUI中每次修改文本时都会调用TextField中的BuildLines2()重新构建字符,我们在这个接口中根据文本需不需要备用字体来决定是否需要创建GSubTextField及刷不刷新GSubTextField的文本,实现如下:

void BuildLines2()

        {

            float letterSpacing = _textFormat.letterSpacing * _fontSizeScale;

            float lineSpacing = (_textFormat.lineSpacing - 1) * _fontSizeScale;

            float rectWidth = _contentRect.width - GUTTER_X * 2;

            float glyphWidth = 0, glyphHeight = 0, baseline = 0;

#if FAIRYGUI_TMPRO

            bool isFallback;

            bool fallback = false;

#endif

            short wordLen = 0;

            bool wordPossible = false;

            float posx = 0;

            TextFormat format = _textFormat;

            _font.SetFormat(format, _fontSizeScale);

            bool wrap = _wordWrap && !_singleLine;

            if (_maxWidth > 0)

            {

                wrap = true;

                rectWidth = _maxWidth - GUTTER_X * 2;

            }

            _textWidth = _textHeight = 0;

            RequestText();

            int elementCount = _elements.Count;

            int elementIndex = 0;

            HtmlElement element = null;

            if (elementCount > 0)

                element = _elements[elementIndex];

            int textLength = _parsedText.Length;

            LineInfo line = LineInfo.Borrow();

            _lines.Add(line);

            line.y = line.y2 = GUTTER_Y;

            sLineChars.Clear();

            for (int charIndex = 0; charIndex < textLength; charIndex++)

            {

                char ch = _parsedText[charIndex];

                glyphWidth = glyphHeight = baseline = 0;

                while (element != null && element.charIndex == charIndex)

                {

                    if (element.type == HtmlElementType.Text)

                    {

                        format = element.format;

                        _font.SetFormat(format, _fontSizeScale);

                    }

                    else

                    {

                        IHtmlObject htmlObject = element.htmlObject;

                        if (_richTextField != null && htmlObject == null)

                        {

                            element.space = (int)(rectWidth - line.width - 4);

                            htmlObject = _richTextField.htmlPageContext.CreateObject(_richTextField, element);

                            element.htmlObject = htmlObject;

                        }

                        if (htmlObject != null)

                        {

                            glyphWidth = htmlObject.width + 2;

                            glyphHeight = htmlObject.height;

                            baseline = glyphHeight * IMAGE_BASELINE;

                        }

                        if (element.isEntity)

                            ch = '\0'; //indicate it is a place holder

                    }

                    elementIndex++;

                    if (elementIndex < elementCount)

                        element = _elements[elementIndex];

                    else

                        element = null;

                }

                if (ch == '\0' || ch == '\n')

                {

                    wordPossible = false;

                }

#if FAIRYGUI_TMPRO

                else if (_font.GetGlyphWithFallback(ch == '\t' ? ' ' : ch, out glyphWidth, out glyphHeight, out baseline,out isFallback))

                {

                    if ((isFallback == true)&&(this.gOwner!=null))

                    {

                        if(this.gOwner.GetType()==typeof(GTextField))

                        {

                            fallback = true;

                            if(isFirst == true)

                            {

                                isFirst = false;

                                ((GTextField)gOwner).CreateSubTextField();

                            }

                        }

                    }

#else

                else if (_font.GetGlyph(ch == '\t' ? ' ' : ch, out glyphWidth, out glyphHeight, out baseline))

                {

#endif

                    if (ch == '\t')

                        glyphWidth *= 4;

                    if (wordPossible)

                    {

                        if (char.IsWhiteSpace(ch))

                        {

                            wordLen = 0;

                        }

                        else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z'

                            || ch >= '0' && ch <= '9'

                            || ch == '.' || ch == '"' || ch == '\''

                            || format.specialStyle == TextFormat.SpecialStyle.Subscript

                            || format.specialStyle == TextFormat.SpecialStyle.Superscript

                            || _textDirection != RTLSupport.DirectionType.UNKNOW && RTLSupport.IsArabicLetter(ch))

                        {

                            wordLen++;

                        }

                        else

                            wordPossible = false;

                    }

                    else if (char.IsWhiteSpace(ch))

                    {

                        wordLen = 0;

                        wordPossible = true;

                    }

                    else if (format.specialStyle == TextFormat.SpecialStyle.Subscript

                        || format.specialStyle == TextFormat.SpecialStyle.Superscript)

                    {

                        if (sLineChars.Count > 0)

                        {

                            wordLen = 2; //避免上标和下标折到下一行

                            wordPossible = true;

                        }

                    }

                    else

                        wordPossible = false;

                }

                else

                    wordPossible = false;

                sLineChars.Add(new LineCharInfo() { width = glyphWidth, height = glyphHeight, baseline = baseline });

                if (glyphWidth != 0)

                {

                    if (posx != 0)

                        posx += letterSpacing;

                    posx += glyphWidth;

                }

                if (ch == '\n' && !_singleLine)

                {

                    UpdateLineInfo(line, letterSpacing, sLineChars.Count);

                    LineInfo newLine = LineInfo.Borrow();

                    _lines.Add(newLine);

                    newLine.y = line.y + (line.height + lineSpacing);

                    if (newLine.y < GUTTER_Y) //lineSpacing maybe negative

                        newLine.y = GUTTER_Y;

                    newLine.y2 = newLine.y;

                    newLine.charIndex = line.charIndex + line.charCount;

                    sLineChars.Clear();

                    wordPossible = false;

                    posx = 0;

                    line = newLine;

                }

                else if (wrap && posx > rectWidth)

                {

                    int lineCharCount = sLineChars.Count;

                    int toMoveChars;

                    if (wordPossible && wordLen < 20 && lineCharCount > 2) //if word had broken, move word to new line

                    {

                        toMoveChars = wordLen;

                        //we caculate the line width WITHOUT the tailing space

                        UpdateLineInfo(line, letterSpacing, lineCharCount - (toMoveChars + 1));

                        line.charCount++; //but keep it in this line.

                    }

                    else

                    {

                        toMoveChars = lineCharCount > 1 ? 1 : 0; //if only one char here, we cant move it to new line

                        UpdateLineInfo(line, letterSpacing, lineCharCount - toMoveChars);

                    }

                    LineInfo newLine = LineInfo.Borrow();

                    _lines.Add(newLine);

                    newLine.y = line.y + (line.height + lineSpacing);

                    if (newLine.y < GUTTER_Y)

                        newLine.y = GUTTER_Y;

                    newLine.y2 = newLine.y;

                    newLine.charIndex = line.charIndex + line.charCount;

                    posx = 0;

                    if (toMoveChars != 0)

                    {

                        for (int i = line.charCount; i < lineCharCount; i++)

                        {

                            LineCharInfo ci = sLineChars[i];

                            if (posx != 0)

                                posx += letterSpacing;

                            posx += ci.width;

                        }

                        sLineChars.RemoveRange(0, line.charCount);

                    }

                    else

                        sLineChars.Clear();

                    wordPossible = false;

                    line = newLine;

                }

            }

            UpdateLineInfo(line, letterSpacing, sLineChars.Count);

            if (_textWidth > 0)

                _textWidth += GUTTER_X * 2;

            _textHeight = line.y + line.height + GUTTER_Y;

            _textWidth = Mathf.RoundToInt(_textWidth);

            _textHeight = Mathf.RoundToInt(_textHeight);

#if FAIRYGUI_TMPRO

            if ((fallback==true)||(fallback != lastNeedFallback))

            {

                lastNeedFallback = fallback;

                ((GTextField)gOwner).RefreshSubText();

            }

#endif

        }

另外在TMPFont中添加了一个接口以便判断文本是否需要备用字体,实现如下:

override public bool GetGlyphWithFallback(char ch, out float width, out float height, out float baseline,out bool isFallback)

        {

            isFallback = false;

            _char = GetCharacterFromFontAssetWithoutFallback(ch, _style);

            if (_char == null)

            {

                _char = GetCharacterFromFontAsset(ch, _style);

                if(_char != null)

                {

                    isFallback = true;

                }   

            }

            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;

            }

            width = 0;

            height = 0;

            baseline = 0;

            return false;

        }

        TMP_Character GetCharacterFromFontAssetWithoutFallback(uint unicode, FontStyles fontStyle)

        {

            bool isAlternativeTypeface;

#pragma warning disable

            TMP_FontAsset actualAsset;

#pragma warning restore

            return TMP_FontAssetUtilities.GetCharacterFromFontAsset(unicode, _fontAsset, false, fontStyle, _fontWeight,

                out isAlternativeTypeface

            //,out actualAsset //old TMP version need this line

            );

        }

(4)最后修改textField中的OnPopulateMesh,根据字符是否在当前字体中决定是否绘制字形用于渲染,修改如下:

public void OnPopulateMesh(VertexBuffer vb)

        {

            if (_textWidth == 0 && _lines.Count == 1)

            {

                if (_charPositions != null)

                {

                    _charPositions.Clear();

                    _charPositions.Add(new CharPosition());

                }

                if (_richTextField != null)

                    _richTextField.RefreshObjects();

                return;

            }

            float letterSpacing = _textFormat.letterSpacing * _fontSizeScale;

            TextFormat format = _textFormat;

            _font.SetFormat(format, _fontSizeScale);

            _font.UpdateGraphics(graphics);

            float rectWidth = _contentRect.width > 0 ? (_contentRect.width - GUTTER_X * 2) : 0;

            float rectHeight = _contentRect.height > 0 ? Mathf.Max(_contentRect.height, _font.GetLineHeight(format.size)) : 0;

            if (_charPositions != null)

                _charPositions.Clear();

            List<Vector3> vertList = vb.vertices;

            List<Vector2> uvList = vb.uvs;

            List<Vector2> uv2List = vb.uvs2;

            List<Color32> colList = vb.colors;

            HtmlLink currentLink = null;

            float linkStartX = 0;

            int linkStartLine = 0;

            float posx = 0;

            float indent_x;

            bool clipping = !_input && _autoSize == AutoSizeType.None;

            bool lineClipped;

            AlignType lineAlign;

            float glyphWidth, glyphHeight, baseline;

            bool isFallback;

            short vertCount;

            float underlineStart;

            float strikethroughStart;

            int minFontSize;

            int maxFontSize;

            string rtlLine = null;

            int elementIndex = 0;

            int elementCount = _elements.Count;

            HtmlElement element = null;

            if (elementCount > 0)

                element = _elements[elementIndex];

            int lineCount = _lines.Count;

            for (int i = 0; i < lineCount; ++i)

            {

                LineInfo line = _lines[i];

                if (line.charCount == 0)

                    continue;

                lineClipped = clipping && i != 0 && line.y + line.height > rectHeight;

                lineAlign = format.align;

                if (element != null && element.charIndex == line.charIndex)

                    lineAlign = element.format.align;

                else

                    lineAlign = format.align;

                if (_textDirection == RTLSupport.DirectionType.RTL)

                {

                    if (lineAlign == AlignType.Center)

                        indent_x = (int)((rectWidth + line.width) / 2);

                    else if (lineAlign == AlignType.Right)

                        indent_x = rectWidth;

                    else

                        indent_x = line.width + GUTTER_X * 2;

                    if (indent_x > rectWidth)

                        indent_x = rectWidth;

                    posx = indent_x - GUTTER_X;

                }

                else

                {

                    if (lineAlign == AlignType.Center)

                        indent_x = (int)((rectWidth - line.width) / 2);

                    else if (lineAlign == AlignType.Right)

                        indent_x = rectWidth - line.width;

                    else

                        indent_x = 0;

                    if (indent_x < 0)

                        indent_x = 0;

                    posx = GUTTER_X + indent_x;

                }

                int lineCharCount = line.charCount;

                underlineStart = posx;

                strikethroughStart = posx;

                minFontSize = maxFontSize = format.size;

                if (_textDirection != RTLSupport.DirectionType.UNKNOW)

                {

                    rtlLine = _parsedText.Substring(line.charIndex, lineCharCount);

                    if (_textDirection == RTLSupport.DirectionType.RTL)

                        rtlLine = RTLSupport.ConvertLineR(rtlLine);

                    else

                        rtlLine = RTLSupport.ConvertLineL(rtlLine);

                    lineCharCount = rtlLine.Length;

                }

                for (int j = 0; j < lineCharCount; j++)

                {

                    int charIndex = line.charIndex + j;

                    char ch = rtlLine != null ? rtlLine[j] : _parsedText[charIndex];

                    while (element != null && charIndex == element.charIndex)

                    {

                        if (element.type == HtmlElementType.Text)

                        {

                            vertCount = 0;

                            if (format.underline != element.format.underline)

                            {

                                if (format.underline)

                                {

                                    if (!lineClipped)

                                    {

                                        float lineWidth;

                                        if (_textDirection == RTLSupport.DirectionType.UNKNOW)

                                            lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - underlineStart;

                                        else

                                            lineWidth = underlineStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);

                                        if (lineWidth > 0)

                                            vertCount += (short)_font.DrawLine(underlineStart < posx ? underlineStart : posx, -(line.y + line.baseline), lineWidth,

                                                maxFontSize, 0, vertList, uvList, uv2List, colList);

                                    }

                                    maxFontSize = 0;

                                }

                                else

                                    underlineStart = posx;

                            }

                            if (format.strikethrough != element.format.strikethrough)

                            {

                                if (format.strikethrough)

                                {

                                    if (!lineClipped)

                                    {

                                        float lineWidth;

                                        if (_textDirection == RTLSupport.DirectionType.UNKNOW)

                                            lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - strikethroughStart;

                                        else

                                            lineWidth = strikethroughStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);

                                        if (lineWidth > 0)

                                            vertCount += (short)_font.DrawLine(strikethroughStart < posx ? strikethroughStart : posx, -(line.y + line.baseline), lineWidth,

                                                minFontSize, 1, vertList, uvList, uv2List, colList);

                                    }

                                    minFontSize = int.MaxValue;

                                }

                                else

                                    strikethroughStart = posx;

                            }

                            if (vertCount > 0 && _charPositions != null)

                            {

                                CharPosition cp = _charPositions[_charPositions.Count - 1];

                                cp.vertCount += vertCount;

                                _charPositions[_charPositions.Count - 1] = cp;

                            }

                            format = element.format;

                            minFontSize = Math.Min(minFontSize, format.size);

                            maxFontSize = Math.Max(maxFontSize, format.size);

                            _font.SetFormat(format, _fontSizeScale);

                        }

                        else if (element.type == HtmlElementType.Link)

                        {

                            currentLink = (HtmlLink)element.htmlObject;

                            if (currentLink != null)

                            {

                                element.position = Vector2.zero;

                                currentLink.SetPosition(0, 0);

                                linkStartX = posx;

                                linkStartLine = i;

                            }

                        }

                        else if (element.type == HtmlElementType.LinkEnd)

                        {

                            if (currentLink != null)

                            {

                                currentLink.SetArea(linkStartLine, linkStartX, i, posx);

                                currentLink = null;

                            }

                        }

                        else

                        {

                            IHtmlObject htmlObj = element.htmlObject;

                            if (htmlObj != null)

                            {

                                if (_textDirection == RTLSupport.DirectionType.RTL)

                                    posx -= htmlObj.width - 2;

                                if (_charPositions != null)

                                {

                                    CharPosition cp = new CharPosition();

                                    cp.lineIndex = (short)i;

                                    cp.charIndex = _charPositions.Count;

                                    cp.imgIndex = (short)(elementIndex + 1);

                                    cp.offsetX = posx;

                                    cp.width = (short)htmlObj.width;

                                    _charPositions.Add(cp);

                                }

                                if (lineClipped || clipping && (posx < GUTTER_X || posx > GUTTER_X && posx + htmlObj.width > _contentRect.width - GUTTER_X))

                                    element.status |= 1;

                                else

                                    element.status &= 254;

                                element.position = new Vector2(posx + 1, line.y + line.baseline - htmlObj.height * IMAGE_BASELINE);

                                htmlObj.SetPosition(element.position.x, element.position.y);

                                if (_textDirection == RTLSupport.DirectionType.RTL)

                                    posx -= letterSpacing;

                                else

                                    posx += htmlObj.width + letterSpacing + 2;

                            }

                        }

                        if (element.isEntity)

                            ch = '\0';

                        elementIndex++;

                        if (elementIndex < elementCount)

                            element = _elements[elementIndex];

                        else

                            element = null;

                    }

                    if (ch == '\0')

                        continue;

#if FAIRYGUI_TMPRO

                    if(_font.GetType() == typeof(TMPFont))

                    {

                        if (_font.GetGlyphWithFallback(ch == '\t' ? ' ' : ch, out glyphWidth, out glyphHeight, out baseline,out isFallback))

                        {

                            if (ch == '\t')

                                glyphWidth *= 4;

                            if (_textDirection == RTLSupport.DirectionType.RTL)

                            {

                                if (lineClipped || clipping && (rectWidth < 7 || posx != (indent_x - GUTTER_X)) && posx < GUTTER_X - 0.5f) //超出区域,剪裁

                                {

                                    posx -= (letterSpacing + glyphWidth);

                                    continue;

                                }

                                posx -= glyphWidth;

                            }

                            else

                            {

                                if (lineClipped || clipping && (rectWidth < 7 || posx != (GUTTER_X + indent_x)) && posx + glyphWidth > _contentRect.width - GUTTER_X + 0.5f) //超出区域,剪裁

                                {

                                    posx += letterSpacing + glyphWidth;

                                    continue;

                                }

                            }

                            if (isFallback == false)

                            {

                                vertCount = (short)_font.DrawGlyph(posx, -(line.y + line.baseline), vertList, uvList, uv2List, colList);

                                if (_charPositions != null)

                                {

                                    CharPosition cp = new CharPosition();

                                    cp.lineIndex = (short)i;

                                    cp.charIndex = _charPositions.Count;

                                    cp.vertCount = vertCount;

                                    cp.offsetX = posx;

                                    cp.width = (short)glyphWidth;

                                    _charPositions.Add(cp);

                                }

                            }

                            if (_textDirection == RTLSupport.DirectionType.RTL)

                                posx -= letterSpacing;

                            else

                                posx += letterSpacing + glyphWidth;

                        }

                        else //if GetGlyph failed

                        {

                            if (_charPositions != null)

                            {

                                CharPosition cp = new CharPosition();

                                cp.lineIndex = (short)i;

                                cp.charIndex = _charPositions.Count;

                                cp.offsetX = posx;

                                _charPositions.Add(cp);

                            }

                            if (_textDirection == RTLSupport.DirectionType.RTL)

                                posx -= letterSpacing;

                            else

                                posx += letterSpacing;

                        }

                    }

                    else

                    {

                        if (_font.GetGlyph(ch == '\t' ? ' ' : ch, out glyphWidth, out glyphHeight, out baseline))

                        {

                            if (ch == '\t')

                                glyphWidth *= 4;

                            if (_textDirection == RTLSupport.DirectionType.RTL)

                            {

                                if (lineClipped || clipping && (rectWidth < 7 || posx != (indent_x - GUTTER_X)) && posx < GUTTER_X - 0.5f) //超出区域,剪裁

                                {

                                    posx -= (letterSpacing + glyphWidth);

                                    continue;

                                }

                                posx -= glyphWidth;

                            }

                            else

                            {

                                if (lineClipped || clipping && (rectWidth < 7 || posx != (GUTTER_X + indent_x)) && posx + glyphWidth > _contentRect.width - GUTTER_X + 0.5f) //超出区域,剪裁

                                {

                                    posx += letterSpacing + glyphWidth;

                                    continue;

                                }

                            }

                            vertCount = (short)_font.DrawGlyph(posx, -(line.y + line.baseline), vertList, uvList, uv2List, colList);

                            if (_charPositions != null)

                            {

                                CharPosition cp = new CharPosition();

                                cp.lineIndex = (short)i;

                                cp.charIndex = _charPositions.Count;

                                cp.vertCount = vertCount;

                                cp.offsetX = posx;

                                cp.width = (short)glyphWidth;

                                _charPositions.Add(cp);

                            }

                            if (_textDirection == RTLSupport.DirectionType.RTL)

                                posx -= letterSpacing;

                            else

                                posx += letterSpacing + glyphWidth;

                        }

                        else //if GetGlyph failed

                        {

                            if (_charPositions != null)

                            {

                                CharPosition cp = new CharPosition();

                                cp.lineIndex = (short)i;

                                cp.charIndex = _charPositions.Count;

                                cp.offsetX = posx;

                                _charPositions.Add(cp);

                            }

                            if (_textDirection == RTLSupport.DirectionType.RTL)

                                posx -= letterSpacing;

                            else

                                posx += letterSpacing;

                        }

                    }

#else

if (_font.GetGlyph(ch == '\t' ? ' ' : ch, out glyphWidth, out glyphHeight, out baseline))

                        {

                            Debug.Log("OnPopulateMesh GetGlyph:" + ch);

                            if (ch == '\t')

                                glyphWidth *= 4;

                            if (_textDirection == RTLSupport.DirectionType.RTL)

                            {

                                if (lineClipped || clipping && (rectWidth < 7 || posx != (indent_x - GUTTER_X)) && posx < GUTTER_X - 0.5f) //超出区域,剪裁

                                {

                                    posx -= (letterSpacing + glyphWidth);

                                    continue;

                                }

                                posx -= glyphWidth;

                            }

                            else

                            {

                                if (lineClipped || clipping && (rectWidth < 7 || posx != (GUTTER_X + indent_x)) && posx + glyphWidth > _contentRect.width - GUTTER_X + 0.5f) //超出区域,剪裁

                                {

                                    posx += letterSpacing + glyphWidth;

                                    continue;

                                }

                            }

                            vertCount = (short)_font.DrawGlyph(posx, -(line.y + line.baseline), vertList, uvList, uv2List, colList);

                            if (_charPositions != null)

                            {

                                CharPosition cp = new CharPosition();

                                cp.lineIndex = (short)i;

                                cp.charIndex = _charPositions.Count;

                                cp.vertCount = vertCount;

                                cp.offsetX = posx;

                                cp.width = (short)glyphWidth;

                                _charPositions.Add(cp);

                            }

                            if (_textDirection == RTLSupport.DirectionType.RTL)

                                posx -= letterSpacing;

                            else

                                posx += letterSpacing + glyphWidth;

                        }

                        else //if GetGlyph failed

                        {

                            if (_charPositions != null)

                            {

                                CharPosition cp = new CharPosition();

                                cp.lineIndex = (short)i;

                                cp.charIndex = _charPositions.Count;

                                cp.offsetX = posx;

                                _charPositions.Add(cp);

                            }

                            if (_textDirection == RTLSupport.DirectionType.RTL)

                                posx -= letterSpacing;

                            else

                                posx += letterSpacing;

                        }

#endif

                }//text loop

                if (!lineClipped)

                {

                    vertCount = 0;

                    if (format.underline)

                    {

                        float lineWidth;

                        if (_textDirection == RTLSupport.DirectionType.UNKNOW)

                            lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - underlineStart;

                        else

                            lineWidth = underlineStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);

                        if (lineWidth > 0)

                            vertCount += (short)_font.DrawLine(underlineStart < posx ? underlineStart : posx, -(line.y + line.baseline), lineWidth,

                                maxFontSize, 0, vertList, uvList, uv2List, colList);

                    }

                    if (format.strikethrough)

                    {

                        float lineWidth;

                        if (_textDirection == RTLSupport.DirectionType.UNKNOW)

                            lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - strikethroughStart;

                        else

                            lineWidth = strikethroughStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);

                        if (lineWidth > 0)

                            vertCount += (short)_font.DrawLine(strikethroughStart < posx ? strikethroughStart : posx, -(line.y + line.baseline), lineWidth,

                                minFontSize, 1, vertList, uvList, uv2List, colList);

                    }

                    if (vertCount > 0 && _charPositions != null)

                    {

                        CharPosition cp = _charPositions[_charPositions.Count - 1];

                        cp.vertCount += vertCount;

                        _charPositions[_charPositions.Count - 1] = cp;

                    }

                }

            }//line loop

            if (element != null && element.type == HtmlElementType.LinkEnd && currentLink != null)

                currentLink.SetArea(linkStartLine, linkStartX, lineCount - 1, posx);

            if (_charPositions != null)

            {

                CharPosition cp = new CharPosition();

                cp.lineIndex = (short)(lineCount - 1);

                cp.charIndex = _charPositions.Count;

                cp.offsetX = posx;

                _charPositions.Add(cp);

            }

            int count = vertList.Count;

            if (count > 65000)

            {

                Debug.LogWarning("Text is too large. A mesh may not have more than 65000 vertices.");

                vertList.RemoveRange(65000, count - 65000);

                colList.RemoveRange(65000, count - 65000);

                uvList.RemoveRange(65000, count - 65000);

                if (uv2List.Count > 0)

                    uv2List.RemoveRange(65000, count - 65000);

                count = 65000;

            }

            if (_font.customOutline)

            {

                bool hasShadow = _textFormat.shadowOffset.x != 0 || _textFormat.shadowOffset.y != 0;

                int allocCount = count;

                int drawDirs = 0;

                if (_textFormat.outline != 0)

                {

                    drawDirs = UIConfig.enhancedTextOutlineEffect ? 8 : 4;

                    allocCount += count * drawDirs;

                }

                if (hasShadow)

                    allocCount += count;

                if (allocCount > 65000)

                {

                    Debug.LogWarning("Text is too large. Outline/shadow effect cannot be completed.");

                    allocCount = count;

                }

                if (allocCount != count)

                {

                    VertexBuffer vb2 = VertexBuffer.Begin();

                    List<Vector3> vertList2 = vb2.vertices;

                    List<Color32> colList2 = vb2.colors;

                    Color32 col = _textFormat.outlineColor;

                    float outline = _textFormat.outline;

                    if (outline != 0)

                    {

                        for (int j = 0; j < drawDirs; j++)

                        {

                            for (int i = 0; i < count; i++)

                            {

                                Vector3 vert = vertList[i];

                                vertList2.Add(new Vector3(vert.x + STROKE_OFFSET[j * 2] * outline, vert.y + STROKE_OFFSET[j * 2 + 1] * outline, 0));

                                colList2.Add(col);

                            }

                            vb2.uvs.AddRange(uvList);

                            if (uv2List.Count > 0)

                                vb2.uvs2.AddRange(uv2List);

                        }

                    }

                    if (hasShadow)

                    {

                        col = _textFormat.shadowColor;

                        Vector2 offset = _textFormat.shadowOffset;

                        for (int i = 0; i < count; i++)

                        {

                            Vector3 vert = vertList[i];

                            vertList2.Add(new Vector3(vert.x + offset.x, vert.y - offset.y, 0));

                            colList2.Add(col);

                        }

                        vb2.uvs.AddRange(uvList);

                        if (uv2List.Count > 0)

                            vb2.uvs2.AddRange(uv2List);

                    }

                    vb.Insert(vb2);

                    vb2.End();

                }

            }

            vb.AddTriangles();

            if (_richTextField != null)

                _richTextField.RefreshObjects();

        }

目前还有很多支持不完善的地方,如果运行中动态修改GTextField的属性,需要将对应属性的变动同步到GSubTextField中,目前看只能在GTextField每个属性设置的地方添加实现,没找到更容易扩展的方式。开始想把GSubTextField挂在GTextField下作为子节点,这样诸如位置、缩放等的动态改变就不用额外考虑了,但实现中发现GTextField本身不是GComponen组件,由于本身对FairyGUI源码不太熟,不知道如何挂载,只能放在GTextField的同级下。

相关文章

网友评论

      本文标题:FairyGUI对TextMeshPro的fallback fo

      本文链接:https://www.haomeiwen.com/subject/ofiprrtx.html