readonly UIVertex[] m_TempVerts = new UIVertex[4]; protected override void OnPopulateMesh(VertexHelper toFill) { if (font == null) return;
// We don't care if we the font Texture changes while we are doing our Update. // The end result of cachedTextGenerator will be valid for this instance. // Otherwise we can get issues like Case 619238. m_DisableFontTextureRebuiltCallback = true;
Vector2 extents = rectTransform.rect.size;
var settings = GetGenerationSettings(extents); cachedTextGenerator.PopulateWithErrors(text, settings, gameObject);
// Apply the offset to the vertices IList<UIVertex> verts = cachedTextGenerator.verts; float unitsPerPixel = 1 / pixelsPerUnit; //Last 4 verts are always a new line... (\n) int vertCount = verts.Count - 4;
Vector2 roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel; roundingOffset = PixelAdjustPoint(roundingOffset) - roundingOffset; toFill.Clear(); if (roundingOffset != Vector2.zero) { for (int i = 0; i < vertCount; ++i) { int tempVertsIndex = i & 3; m_TempVerts[tempVertsIndex] = verts[i]; m_TempVerts[tempVertsIndex].position *= unitsPerPixel; m_TempVerts[tempVertsIndex].position.x += roundingOffset.x; m_TempVerts[tempVertsIndex].position.y += roundingOffset.y; if (tempVertsIndex == 3) toFill.AddUIVertexQuad(m_TempVerts); } } else { for (int i = 0; i < vertCount; ++i) { int tempVertsIndex = i & 3; m_TempVerts[tempVertsIndex] = verts[i]; m_TempVerts[tempVertsIndex].position *= unitsPerPixel; if (tempVertsIndex == 3) toFill.AddUIVertexQuad(m_TempVerts); } }
public void FontTextureChanged() { // Only invoke if we are not destroyed. if (!this) return;
if (m_DisableFontTextureRebuiltCallback) return;
cachedTextGenerator.Invalidate();
if (!IsActive()) return;
// this is a bit hacky, but it is currently the // cleanest solution.... // if we detect the font texture has changed and are in a rebuild loop // we just regenerate the verts for the new UV's if (CanvasUpdateRegistry.IsRebuildingGraphics() || CanvasUpdateRegistry.IsRebuildingLayout()) UpdateGeometry(); else SetAllDirty(); }
public static class FontUpdateTracker { static Dictionary<Font, HashSet<Text>> m_Tracked = new Dictionary<Font, HashSet<Text>>();
public static void TrackText(Text t) { if (t.font == null) return;
HashSet<Text> exists; m_Tracked.TryGetValue(t.font, out exists); if (exists == null) { // The textureRebuilt event is global for all fonts, so we add our delegate the first time we register *any* Text if (m_Tracked.Count == 0) Font.textureRebuilt += RebuildForFont;
exists = new HashSet<Text>(); m_Tracked.Add(t.font, exists); }
foreach (var text in texts) text.FontTextureChanged(); }
public static void UntrackText(Text t) { if (t.font == null) return;
HashSet<Text> texts; m_Tracked.TryGetValue(t.font, out texts);
if (texts == null) return;
texts.Remove(t);
if (texts.Count == 0) { m_Tracked.Remove(t.font);
// There is a global textureRebuilt event for all fonts, so once the last Text reference goes away, remove our delegate if (m_Tracked.Count == 0) Font.textureRebuilt -= RebuildForFont; } } }
public bool PopulateWithErrors(string str, TextGenerationSettings settings, GameObject context) { TextGenerationError textGenerationError = this.PopulateWithError(str, settings); bool result; if (textGenerationError == TextGenerationError.None) { result = true; } else { if ((textGenerationError & TextGenerationError.CustomSizeOnNonDynamicFont) != TextGenerationError.None) { Debug.LogErrorFormat(context, "Font '{0}' is not dynamic, which is required to override its size", new object[] { settings.font }); } if ((textGenerationError & TextGenerationError.CustomStyleOnNonDynamicFont) != TextGenerationError.None) { Debug.LogErrorFormat(context, "Font '{0}' is not dynamic, which is required to override its style", new object[] { settings.font }); } result = false; } return result; }
里边层层判断和嵌套,最终会调用一个extern方法,其实现封装在动态库里:
1 2 3
[GeneratedByOldBindingsGenerator] [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool INTERNAL_CALL_Populate_Internal_cpp(TextGenerator self, string str, Font font, ref Color color, int fontSize, float scaleFactor, float lineSpacing, FontStyle style, bool richText, bool resizeTextForBestFit, int resizeTextMinSize, int resizeTextMaxSize, int verticalOverFlow, int horizontalOverflow, bool updateBounds, TextAnchor anchor, float extentsX, float extentsY, float pivotX, float pivotY, bool generateOutOfBounds, bool alignByGeometry, out uint error);
public extern Material material { [GeneratedByOldBindingsGenerator] [MethodImpl(MethodImplOptions.InternalCall)] get; [GeneratedByOldBindingsGenerator] [MethodImpl(MethodImplOptions.InternalCall)] set; }