void BuildMesh()
{
_requireUpdateMesh = false;
if (_textWidth == 0 && _lines.Count == 1)
{
graphics.ClearMesh();
if (_charPositions != null && _charPositions.Count == 0)
_charPositions.Add(new CharPosition());
if (_richTextField != null)
_richTextField.RefreshObjects();
return;
}
int letterSpacing = _textFormat.letterSpacing;
float rectWidth = _contentRect.width - GUTTER_X * 2;
TextFormat format = _textFormat;
_font.SetFormat(format, _fontSizeScale);
Color32 color = format.color;
Color32[] gradientColor = format.gradientColor;
bool boldVertice = format.bold && (_font.customBold || (format.italic && _font.customBoldAndItalic));
if (_input)
letterSpacing++;
if (_charPositions != null)
_charPositions.Clear();
if (_fontSizeScale != 1) //不为1,表示在Shrink的作用下,字体变小了,所以要重新请求
RequestText();
Vector3 v0 = Vector3.zero, v1 = Vector3.zero;
Vector2 u0, u1, u2, u3;
float specFlag;
List<Vector3> vertList = sCachedVerts;
List<Vector2> uvList = sCachedUVs;
List<Color32> colList = sCachedCols;
vertList.Clear();
uvList.Clear();
colList.Clear();
HtmlLink currentLink = null;
float linkStartX = 0;
int linkStartLine = 0;
float charX = 0;
float xIndent;
float yIndent = 0;
bool clipped = !_input && _autoSize == AutoSizeType.None;
bool lineClipped;
int lineCount = _lines.Count;
for (int i = 0; i < lineCount; ++i)
{
LineInfo line = _lines[i];
lineClipped = clipped && i != 0 && line.y + line.height > _contentRect.height; //超出区域,剪裁
if (_align == AlignType.Center)
xIndent = (int)((rectWidth - line.width) / 2);
else if (_align == AlignType.Right)
xIndent = rectWidth - line.width;
else
xIndent = 0;
if (_input && xIndent < 0)
xIndent = 0;
charX = GUTTER_X + xIndent;
int textLength = line.text.Length;
for (int j = 0; j < textLength; j++)
{
char ch = line.text[j];
if (ch == E_TAG)
{
int elementIndex = (int)line.text[++j] - 33;
HtmlElement element = _elements[elementIndex];
if (element.type == HtmlElementType.Text)
{
format = element.format;
_font.SetFormat(format, _fontSizeScale);
color = format.color;
gradientColor = format.gradientColor;
boldVertice = format.bold && (_font.customBold || (format.italic && _font.customBoldAndItalic));
}
else if (element.type == HtmlElementType.Link)
{
currentLink = (HtmlLink)element.htmlObject;
if (currentLink != null)
{
element.position = Vector2.zero;
currentLink.SetPosition(0, 0);
linkStartX = charX;
linkStartLine = i;
}
}
else if (element.type == HtmlElementType.LinkEnd)
{
if (currentLink != null)
{
currentLink.SetArea(linkStartLine, linkStartX, i, charX);
currentLink = null;
}
}
else
{
IHtmlObject htmlObj = element.htmlObject;
if (htmlObj != null)
{
if (_charPositions != null)
{
CharPosition cp = new CharPosition();
cp.lineIndex = (short)i;
cp.charIndex = (short)j;
cp.caretIndex = _charPositions.Count;
cp.vertCount = -1 - elementIndex; //借用
cp.offsetX = (int)charX;
_charPositions.Add(cp);
}
element.position = new Vector2(charX + 1, line.y + (int)((line.height - htmlObj.height) / 2));
htmlObj.SetPosition(element.position.x, element.position.y);
if (lineClipped || clipped && charX + htmlObj.width > _contentRect.width - GUTTER_X)
element.status |= 1;
else
element.status &= 254;
charX += htmlObj.width + letterSpacing + 2;
}
}
continue;
}
if (_font.GetGlyph(ch, glyph))
{
if (lineClipped || clipped && charX != 0 && charX + glyph.width > _contentRect.width - GUTTER_X) //超出区域,剪裁
{
charX += letterSpacing + glyph.width;
continue;
}
yIndent = (int)((line.height + line.textHeight) / 2) - glyph.height;
v0.x = charX + glyph.vert.xMin;
v0.y = -line.y - yIndent + glyph.vert.yMin;
v1.x = charX + glyph.vert.xMax;
v1.y = -line.y - yIndent + glyph.vert.yMax;
u0 = glyph.uvBottomLeft;
u1 = glyph.uvTopLeft;
u2 = glyph.uvTopRight;
u3 = glyph.uvBottomRight;
specFlag = 0;
if (_font.hasChannel)
{
//对于由BMFont生成的字体,使用这个特殊的设置告诉着色器告诉用的是哪个通道
if (glyph.channel != 0)
{
specFlag = 10 * (glyph.channel - 1);
u0.x += specFlag;
u1.x += specFlag;
u2.x += specFlag;
u3.x += specFlag;
}
}
else if (_font.canLight && format.bold)
{
//对于动态字体,使用这个特殊的设置告诉着色器这个文字不需要点亮(粗体亮度足够,不需要)
specFlag = 10;
u0.x += specFlag;
u1.x += specFlag;
u2.x += specFlag;
u3.x += specFlag;
}
if (!boldVertice)
{
uvList.Add(u0);
uvList.Add(u1);
uvList.Add(u2);
uvList.Add(u3);
vertList.Add(v0);
vertList.Add(new Vector3(v0.x, v1.y));
vertList.Add(new Vector3(v1.x, v1.y));
vertList.Add(new Vector3(v1.x, v0.y));
if (gradientColor != null)
{
colList.Add(gradientColor[1]);
colList.Add(gradientColor[0]);
colList.Add(gradientColor[2]);
colList.Add(gradientColor[3]);
}
else
{
colList.Add(color);
colList.Add(color);
colList.Add(color);
colList.Add(color);
}
}
else
{
for (int b = 0; b < 4; b++)
{
uvList.Add(u0);
uvList.Add(u1);
uvList.Add(u2);
uvList.Add(u3);
float fx = BOLD_OFFSET[b * 2];
float fy = BOLD_OFFSET[b * 2 + 1];
vertList.Add(new Vector3(v0.x + fx, v0.y + fy));
vertList.Add(new Vector3(v0.x + fx, v1.y + fy));
vertList.Add(new Vector3(v1.x + fx, v1.y + fy));
vertList.Add(new Vector3(v1.x + fx, v0.y + fy));
if (gradientColor != null)
{
colList.Add(gradientColor[1]);
colList.Add(gradientColor[0]);
colList.Add(gradientColor[2]);
colList.Add(gradientColor[3]);
}
else
{
colList.Add(color);
colList.Add(color);
colList.Add(color);
colList.Add(color);
}
}
}
if (format.underline)
{
if (_font.GetGlyph('_', glyph2))
{
//取中点的UV
if (glyph2.uvBottomLeft.x != glyph2.uvBottomRight.x)
u0.x = (glyph2.uvBottomLeft.x + glyph2.uvBottomRight.x) * 0.5f;
else
u0.x = (glyph2.uvBottomLeft.x + glyph2.uvTopLeft.x) * 0.5f;
u0.x += specFlag;
if (glyph2.uvBottomLeft.y != glyph2.uvTopLeft.y)
u0.y = (glyph2.uvBottomLeft.y + glyph2.uvTopLeft.y) * 0.5f;
else
u0.y = (glyph2.uvBottomLeft.y + glyph2.uvBottomRight.y) * 0.5f;
uvList.Add(u0);
uvList.Add(u0);
uvList.Add(u0);
uvList.Add(u0);
v0.y = -line.y - yIndent + glyph2.vert.yMin - 1;
v1.y = -line.y - yIndent + glyph2.vert.yMax - 1;
float tmpX = charX + letterSpacing + glyph.width;
vertList.Add(new Vector3(charX, v0.y));
vertList.Add(new Vector3(charX, v1.y));
vertList.Add(new Vector3(tmpX, v1.y));
vertList.Add(new Vector3(tmpX, v0.y));
colList.Add(color);
colList.Add(color);
colList.Add(color);
colList.Add(color);
}
else
format.underline = false;
}
if (_charPositions != null)
{
CharPosition cp = new CharPosition();
cp.lineIndex = (short)i;
cp.charIndex = (short)j;
cp.caretIndex = _charPositions.Count;
cp.vertCount = ((boldVertice ? 4 : 1) + (format.underline ? 1 : 0)) * 4;
cp.offsetX = (int)charX;
_charPositions.Add(cp);
}
charX += letterSpacing + glyph.width;
}
else //if GetGlyph failed
{
if (_charPositions != null)
{
CharPosition cp = new CharPosition();
cp.lineIndex = (short)i;
cp.charIndex = (short)j;
cp.caretIndex = _charPositions.Count;
cp.vertCount = 0;
cp.offsetX = (int)charX;
_charPositions.Add(cp);
}
charX += letterSpacing;
}
}//text loop
}//line loop
if (_charPositions != null)
{
CharPosition cp = new CharPosition();
cp.lineIndex = (short)(lineCount - 1);
cp.caretIndex = _charPositions.Count;
cp.offsetX = (int)charX;
_charPositions.Add(cp);
}
bool hasShadow = _shadowOffset.x != 0 || _shadowOffset.y != 0;
if ((_stroke != 0 || hasShadow) && _font.canOutline)
{
int count = vertList.Count;
int allocCount = count;
if (_stroke != 0)
allocCount += count * 4;
if (hasShadow)
allocCount += count;
graphics.Alloc(allocCount);
Vector3[] vertBuf = graphics.vertices;
Vector2[] uvBuf = graphics.uv;
Color32[] colBuf = graphics.colors;
int start = allocCount - count;
vertList.CopyTo(0, vertBuf, start, count);
uvList.CopyTo(0, uvBuf, start, count);
if (_font.canTint)
{
for (int i = 0; i < count; i++)
colBuf[start + i] = colList[i];
}
else
{
for (int i = 0; i < count; i++)
colBuf[start + i] = Color.white;
}
Color32 strokeColor = _strokeColor;
if (_stroke != 0)
{
start = allocCount - count * 5;
for (int j = 0; j < 4; j++)
{
for (int i = 0; i < count; i++)
{
Vector3 vert = vertList[i];
Vector2 u = uvList[i];
//使用这个特殊的设置告诉着色器这个是描边
if (_font.canOutline)
u.y = 10 + u.y;
uvBuf[start] = u;
vertBuf[start] = new Vector3(vert.x + STROKE_OFFSET[j * 2] * _stroke, vert.y + STROKE_OFFSET[j * 2 + 1] * _stroke, 0);
colBuf[start] = strokeColor;
start++;
}
}
}
if (hasShadow)
{
for (int i = 0; i < count; i++)
{
Vector3 vert = vertList[i];
Vector2 u = uvList[i];
//使用这个特殊的设置告诉着色器这个是描边
if (_font.canOutline)
u.y = 10 + u.y;
uvBuf[i] = u;
vertBuf[i] = new Vector3(vert.x + _shadowOffset.x, vert.y - _shadowOffset.y, 0);
colBuf[i] = strokeColor;
}
}
}
else
{
int count = vertList.Count;
graphics.Alloc(count);
vertList.CopyTo(0, graphics.vertices, 0, count);
uvList.CopyTo(0, graphics.uv, 0, count);
Color32[] colors = graphics.colors;
if (_font.canTint)
{
for (int i = 0; i < count; i++)
colors[i] = colList[i];
}
else
{
for (int i = 0; i < count; i++)
colors[i] = Color.white;
}
}
graphics.FillTriangles();
graphics.UpdateMesh();
if (_richTextField != null)
_richTextField.RefreshObjects();
}