/// Credit Melang, Lee Hui /// Sourced from - http://forum.unity3d.com/members/melang.593409/ /// GC Alloc fix - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/pull-requests/130 using System.Collections.Generic; namespace UnityEngine.UI.Extensions { //An outline that looks a bit nicer than the default one. It has less "holes" in the outline by drawing more copies of the effect [AddComponentMenu("UI/Effects/Extensions/Nicer Outline")] public class NicerOutline : BaseMeshEffect { [SerializeField] private Color m_EffectColor = new Color (0f, 0f, 0f, 0.5f); [SerializeField] private Vector2 m_EffectDistance = new Vector2 (1f, -1f); [SerializeField] private bool m_UseGraphicAlpha = true; private List < UIVertex > m_Verts = new List(); // // Properties // public Color effectColor { get { return this.m_EffectColor; } set { this.m_EffectColor = value; if (base.graphic != null) { base.graphic.SetVerticesDirty (); } } } public Vector2 effectDistance { get { return this.m_EffectDistance; } set { if (value.x > 600f) { value.x = 600f; } if (value.x < -600f) { value.x = -600f; } if (value.y > 600f) { value.y = 600f; } if (value.y < -600f) { value.y = -600f; } if (this.m_EffectDistance == value) { return; } this.m_EffectDistance = value; if (base.graphic != null) { base.graphic.SetVerticesDirty (); } } } public bool useGraphicAlpha { get { return this.m_UseGraphicAlpha; } set { this.m_UseGraphicAlpha = value; if (base.graphic != null) { base.graphic.SetVerticesDirty (); } } } public override void ModifyMesh(VertexHelper vh) { if (!this.IsActive ()) { return; } m_Verts.Clear(); vh.GetUIVertexStream(m_Verts); Text foundtext = GetComponent(); float best_fit_adjustment = 1f; if (foundtext && foundtext.resizeTextForBestFit) { best_fit_adjustment = (float)foundtext.cachedTextGenerator.fontSizeUsedForBestFit / (foundtext.resizeTextMaxSize-1); //max size seems to be exclusive } float distanceX = this.effectDistance.x * best_fit_adjustment; float distanceY = this.effectDistance.y * best_fit_adjustment; vh.Clear(); int start = 0; // Apply Outline start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, distanceX, distanceY, vh, start); start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, distanceX, -distanceY, vh, start); start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, -distanceX, distanceY, vh, start); start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, -distanceX, -distanceY, vh, start); start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, distanceX, 0, vh, start); start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, -distanceX, 0, vh, start); start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, 0, distanceY, vh, start); start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, 0, -distanceY, vh, start); // Apply self Text stuff start += ApplyText(m_Verts, vh, start); } private int ApplyOutlineNoGC(List verts, Color color, float x, float y, VertexHelper vh, int startIndex) { int length = verts.Count; for (int i = 0; i < length; ++i) { UIVertex vt = verts[i]; Vector3 v = vt.position; v.x += x; v.y += y; vt.position = v; var newColor = color; if (m_UseGraphicAlpha) newColor.a = (byte)((newColor.a * verts[i].color.a) / 255); vt.color = newColor; // Tips: Since two triangles share same two vertices, in theory vertices can reduce to 4 / 6 // But VertexHelper.FillMesh forbid, so leave it be. vh.AddVert(vt); } int triangleCount = length / 3; for(int i=0; i verts, VertexHelper vh, int startIndex) { int length = verts.Count; for (int i = 0; i < length; ++i) { vh.AddVert(verts[i]); } int triangleCount = length / 3; for (int i = 0; i < triangleCount; ++i) { int start = startIndex + 3 * i; vh.AddTriangle(start + 0, start + 1, start + 2); } return length; } #if UNITY_EDITOR protected override void OnValidate () { this.effectDistance = this.m_EffectDistance; base.OnValidate (); } #endif } }