com.unity.uiextensions.nosa.../Runtime/Scripts/Effects/NicerOutline.cs

195 lines
4.7 KiB
C#
Raw Normal View History

/// 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<UIVertex>();
//
// 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<Text>();
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<UIVertex> 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<triangleCount; ++i)
{
int start = startIndex + 3 * i;
vh.AddTriangle(start + 0, start + 1, start + 2);
}
return length;
}
private int ApplyText(List<UIVertex> 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
}
}