AxibugEmuOnline/AxibugEmuOnline.Client.Transplant/Assets/Plugins/Coffee/UIExtensions/UIEffect/Scripts/UIGradient.cs

387 lines
11 KiB
C#

using UnityEngine;
using UnityEngine.UI;
namespace Coffee.UIExtensions
{
/// <summary>
/// UIGradient.
/// </summary>
[DisallowMultipleComponent]
[AddComponentMenu("UI/MeshEffectForTextMeshPro/UIGradient", 101)]
public class UIGradient : BaseMeshEffect
{
//################################
// Constant or Static Members.
//################################
/// <summary>
/// Gradient direction.
/// </summary>
public enum Direction
{
Horizontal,
Vertical,
Angle,
Diagonal,
}
/// <summary>
/// Gradient space for Text.
/// </summary>
public enum GradientStyle
{
Rect,
Fit,
Split,
}
//################################
// Serialize Members.
//################################
[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;
//################################
// Public Members.
//################################
public Graphic targetGraphic { get { return base.graphic; } }
/// <summary>
/// Gradient Direction.
/// </summary>
public Direction direction
{
get { return m_Direction; }
set
{
if (m_Direction != value)
{
m_Direction = value;
SetVerticesDirty();
}
}
}
/// <summary>
/// Color1: Top or Left.
/// </summary>
public Color color1
{
get { return m_Color1; }
set
{
if (m_Color1 != value)
{
m_Color1 = value;
SetVerticesDirty();
}
}
}
/// <summary>
/// Color2: Bottom or Right.
/// </summary>
public Color color2
{
get { return m_Color2; }
set
{
if (m_Color2 != value)
{
m_Color2 = value;
SetVerticesDirty();
}
}
}
/// <summary>
/// Color3: For diagonal.
/// </summary>
public Color color3
{
get { return m_Color3; }
set
{
if (m_Color3 != value)
{
m_Color3 = value;
SetVerticesDirty();
}
}
}
/// <summary>
/// Color4: For diagonal.
/// </summary>
public Color color4
{
get { return m_Color4; }
set
{
if (m_Color4 != value)
{
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))
{
m_Rotation = value;
SetVerticesDirty();
}
}
}
/// <summary>
/// Gradient offset for Horizontal, Vertical or Angle.
/// </summary>
public float offset
{
get { return m_Offset1; }
set
{
if (m_Offset1 != value)
{
m_Offset1 = value;
SetVerticesDirty();
}
}
}
/// <summary>
/// Gradient offset for Diagonal.
/// </summary>
public Vector2 offset2
{
get { return new Vector2(m_Offset2, m_Offset1); }
set
{
if (m_Offset1 != value.y || m_Offset2 != value.x)
{
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)
{
m_GradientStyle = value;
SetVerticesDirty();
}
}
}
/// <summary>
/// Color space to correct color.
/// </summary>
public ColorSpace colorSpace
{
get { return m_ColorSpace; }
set
{
if (m_ColorSpace != value)
{
m_ColorSpace = value;
SetVerticesDirty();
}
}
}
/// <summary>
/// Ignore aspect ratio.
/// </summary>
public bool ignoreAspectRatio
{
get { return m_IgnoreAspectRatio; }
set
{
if (m_IgnoreAspectRatio != value)
{
m_IgnoreAspectRatio = value;
SetVerticesDirty();
}
}
}
/// <summary>
/// Call used to modify mesh.
/// </summary>
public override void ModifyMesh(VertexHelper vh)
{
if (!IsActive())
return;
// Gradient space.
Rect rect = default(Rect);
UIVertex vertex = default(UIVertex);
if (m_GradientStyle == GradientStyle.Rect)
{
// RectTransform.
rect = graphic.rectTransform.rect;
}
else if (m_GradientStyle == GradientStyle.Split)
{
// Each characters.
rect.Set(0, 0, 1, 1);
}
else if (m_GradientStyle == GradientStyle.Fit)
{
// Fit to contents.
rect.xMin = rect.yMin = float.MaxValue;
rect.xMax = rect.yMax = float.MinValue;
for (int 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);
}
}
// Gradient rotation.
float rad = rotation * Mathf.Deg2Rad;
Vector2 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.
Color color;
Vector2 nomalizedPos;
Matrix2x3 localMatrix = new Matrix2x3(rect, dir.x, dir.y); // Get local matrix.
for (int i = 0; i < vh.currentVertCount; i++)
{
vh.PopulateUIVertex(ref vertex, i);
// Normalize vertex position by local matrix.
if (m_GradientStyle == GradientStyle.Split)
{
// Each characters.
nomalizedPos = localMatrix * s_SplitedCharacterPosition[i % 4] + offset2;
}
else
{
nomalizedPos = localMatrix * vertex.position + offset2;
}
// Interpolate vertex color.
if (direction == Direction.Diagonal)
{
color = Color.LerpUnclamped(
Color.LerpUnclamped(m_Color1, m_Color2, nomalizedPos.x),
Color.LerpUnclamped(m_Color3, m_Color4, nomalizedPos.x),
nomalizedPos.y);
}
else
{
color = Color.LerpUnclamped(m_Color2, m_Color1, nomalizedPos.y);
}
// Correct color.
vertex.color *= (m_ColorSpace == ColorSpace.Gamma) ? color.gamma
: (m_ColorSpace == ColorSpace.Linear) ? color.linear
: color;
vh.SetUIVertex(vertex, i);
}
}
//################################
// Private Members.
//################################
static readonly Vector2[] s_SplitedCharacterPosition = { Vector2.up, Vector2.one, Vector2.right, Vector2.zero };
/// <summary>
/// Matrix2x3.
/// </summary>
struct Matrix2x3
{
public float m00, m01, m02, m10, m11, m12;
public Matrix2x3(Rect rect, float cos, float sin)
{
const float center = 0.5f;
float dx = -rect.xMin / rect.width - center;
float dy = -rect.yMin / rect.height - center;
m00 = cos / rect.width;
m01 = -sin / rect.height;
m02 = dx * cos - dy * sin + center;
m10 = sin / rect.width;
m11 = cos / rect.height;
m12 = dx * sin + dy * cos + center;
}
public static Vector2 operator *(Matrix2x3 m, Vector2 v)
{
return new Vector2(
(m.m00 * v.x) + (m.m01 * v.y) + m.m02,
(m.m10 * v.x) + (m.m11 * v.y) + m.m12
);
}
}
}
}