diff options
author | chai <chaifix@163.com> | 2021-04-07 21:33:14 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-04-07 21:33:14 +0800 |
commit | c47b92e92cf33ae8bf2f38929e137294397e4735 (patch) | |
tree | c67ae3419eaf15e84f1679186e107f598de33978 /Assets/Scripts/UIGradient.cs |
Diffstat (limited to 'Assets/Scripts/UIGradient.cs')
-rw-r--r-- | Assets/Scripts/UIGradient.cs | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/Assets/Scripts/UIGradient.cs b/Assets/Scripts/UIGradient.cs new file mode 100644 index 0000000..b184182 --- /dev/null +++ b/Assets/Scripts/UIGradient.cs @@ -0,0 +1,319 @@ +using UnityEngine; +using UnityEngine.UI; + +namespace Coffee.UIEffects +{ + /// <summary> + /// UIGradient. + /// </summary> + [DisallowMultipleComponent] + [AddComponentMenu("UI/UIEffects/UIGradient", 101)] + public class UIGradient : BaseMeshEffect + { + static readonly Vector2[] s_SplitedCharacterPosition = {Vector2.up, Vector2.one, Vector2.right, Vector2.zero}; + + /// <summary> + /// Gradient direction. + /// </summary> + public enum Direction + { + Horizontal, + Vertical, + Angle, + Diagonal, + } + + /// <summary> + /// Gradient space for Text. + /// </summary> + public enum GradientStyle + { + Rect, + Fit, + Split, + } + + + [Tooltip("Gradient Direction.")] [SerializeField] + Direction m_Direction; + + [Tooltip("Color1: Top or Left.")] [SerializeField] + Color m_Color1 = Color.white; + + [Tooltip("Color2: Bottom or Right.")] [SerializeField] + Color m_Color2 = Color.white; + + [Tooltip("Color3: For diagonal.")] [SerializeField] + Color m_Color3 = Color.white; + + [Tooltip("Color4: For diagonal.")] [SerializeField] + Color m_Color4 = Color.white; + + [Tooltip("Gradient rotation.")] [SerializeField] [Range(-180, 180)] + float m_Rotation; + + [Tooltip("Gradient offset for Horizontal, Vertical or Angle.")] [SerializeField] [Range(-1, 1)] + float m_Offset1; + + [Tooltip("Gradient offset for Diagonal.")] [SerializeField] [Range(-1, 1)] + float m_Offset2; + + [Tooltip("Gradient style for Text.")] [SerializeField] + GradientStyle m_GradientStyle; + + [Tooltip("Color space to correct color.")] [SerializeField] + ColorSpace m_ColorSpace = ColorSpace.Uninitialized; + + [Tooltip("Ignore aspect ratio.")] [SerializeField] + bool m_IgnoreAspectRatio = true; + + /// <summary> + /// Gradient Direction. + /// </summary> + public Direction direction + { + get { return m_Direction; } + set + { + if (m_Direction == value) return; + m_Direction = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color1: Top or Left. + /// </summary> + public Color color1 + { + get { return m_Color1; } + set + { + if (m_Color1 == value) return; + m_Color1 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color2: Bottom or Right. + /// </summary> + public Color color2 + { + get { return m_Color2; } + set + { + if (m_Color2 == value) return; + m_Color2 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color3: For diagonal. + /// </summary> + public Color color3 + { + get { return m_Color3; } + set + { + if (m_Color3 == value) return; + m_Color3 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color4: For diagonal. + /// </summary> + public Color color4 + { + get { return m_Color4; } + set + { + if (m_Color4 == value) return; + m_Color4 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gradient rotation. + /// </summary> + public float rotation + { + get + { + return m_Direction == Direction.Horizontal ? -90 + : m_Direction == Direction.Vertical ? 0 + : m_Rotation; + } + set + { + if (Mathf.Approximately(m_Rotation, value)) return; + m_Rotation = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gradient offset for Horizontal, Vertical or Angle. + /// </summary> + public float offset + { + get { return m_Offset1; } + set + { + if (Mathf.Approximately(m_Offset1, value)) return; + m_Offset1 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gradient offset for Diagonal. + /// </summary> + public Vector2 offset2 + { + get { return new Vector2(m_Offset2, m_Offset1); } + set + { + if (Mathf.Approximately(m_Offset1, value.y) && Mathf.Approximately(m_Offset2, value.x)) return; + m_Offset1 = value.y; + m_Offset2 = value.x; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gradient style for Text. + /// </summary> + public GradientStyle gradientStyle + { + get { return m_GradientStyle; } + set + { + if (m_GradientStyle == value) return; + m_GradientStyle = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color space to correct color. + /// </summary> + public ColorSpace colorSpace + { + get { return m_ColorSpace; } + set + { + if (m_ColorSpace == value) return; + m_ColorSpace = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Ignore aspect ratio. + /// </summary> + public bool ignoreAspectRatio + { + get { return m_IgnoreAspectRatio; } + set + { + if (m_IgnoreAspectRatio == value) return; + m_IgnoreAspectRatio = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Call used to modify mesh. + /// </summary> + public override void ModifyMesh(VertexHelper vh, Graphic graphic) + { + if (!isActiveAndEnabled) + return; + + // Gradient space. + var rect = default(Rect); + var vertex = default(UIVertex); + switch (m_GradientStyle) + { + case GradientStyle.Rect: + // RectTransform. + rect = graphic.rectTransform.rect; + break; + case GradientStyle.Split: + // Each characters. + rect.Set(0, 0, 1, 1); + break; + case GradientStyle.Fit: + { + // Fit to contents. + rect.xMin = rect.yMin = float.MaxValue; + rect.xMax = rect.yMax = float.MinValue; + for (var i = 0; i < vh.currentVertCount; i++) + { + vh.PopulateUIVertex(ref vertex, i); + rect.xMin = Mathf.Min(rect.xMin, vertex.position.x); + rect.yMin = Mathf.Min(rect.yMin, vertex.position.y); + rect.xMax = Mathf.Max(rect.xMax, vertex.position.x); + rect.yMax = Mathf.Max(rect.yMax, vertex.position.y); + } + + break; + } + } + + // Gradient rotation. + var rad = rotation * Mathf.Deg2Rad; + var dir = new Vector2(Mathf.Cos(rad), Mathf.Sin(rad)); + if (!m_IgnoreAspectRatio && Direction.Angle <= m_Direction) + { + dir.x *= rect.height / rect.width; + dir = dir.normalized; + } + + // Calculate vertex color. + var localMatrix = new Matrix2x3(rect, dir.x, dir.y); // Get local matrix. + for (var i = 0; i < vh.currentVertCount; i++) + { + vh.PopulateUIVertex(ref vertex, i); + + // Normalize vertex position by local matrix. + Vector2 normalizedPos; + if (m_GradientStyle == GradientStyle.Split) + { + // Each characters. + normalizedPos = localMatrix * s_SplitedCharacterPosition[i % 4] + offset2; + } + else + { + normalizedPos = localMatrix * vertex.position + offset2; + } + + // Interpolate vertex color. + Color color; + if (direction == Direction.Diagonal) + { + color = Color.LerpUnclamped( + Color.LerpUnclamped(m_Color1, m_Color2, normalizedPos.x), + Color.LerpUnclamped(m_Color3, m_Color4, normalizedPos.x), + normalizedPos.y); + } + else + { + color = Color.LerpUnclamped(m_Color2, m_Color1, normalizedPos.y); + } + + // Correct color. + vertex.color *= (m_ColorSpace == ColorSpace.Gamma) ? color.gamma + : (m_ColorSpace == ColorSpace.Linear) ? color.linear + : color; + + vh.SetUIVertex(vertex, i); + } + } + } +} |