Health/Assets/Shift - Complete Sci-Fi UI/Scripts/Rendering/GradientEffect.cs

277 lines
7.8 KiB
C#

using UnityEngine;
using UnityEngine.UI;
namespace Michsky.UI.Shift
{
public class GradientEffect : BaseMeshEffect
{
[Header("Gradient Style")]
[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;
[Header("Settings")]
[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 Graphic TargetGraphic { get { return base.graphic; } }
public enum Direction
{
Horizontal,
Vertical,
Angle,
Diagonal,
}
public enum GradientStyle
{
Rect,
Fit,
Split,
}
public Direction DirectionMain
{
get { return m_Direction; }
set
{
if (m_Direction != value)
m_Direction = value;
}
}
public Color Color1
{
get { return m_Color1; }
set
{
if (m_Color1 != value)
m_Color1 = value;
}
}
public Color Color2
{
get { return m_Color2; }
set
{
if (m_Color2 != value)
m_Color2 = value;
}
}
public Color Color3
{
get { return m_Color3; }
set
{
if (m_Color3 != value)
m_Color3 = value;
}
}
public Color Color4
{
get { return m_Color4; }
set
{
if (m_Color4 != value)
m_Color4 = value;
}
}
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;
}
}
public float Offset
{
get { return m_Offset1; }
set
{
if (m_Offset1 != value)
m_Offset1 = value;
}
}
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;
}
}
}
public GradientStyle GradientStyleMain
{
get { return m_GradientStyle; }
set
{
if (m_GradientStyle != value)
m_GradientStyle = value;
}
}
public ColorSpace ColorSpace
{
get { return m_ColorSpace; }
set
{
if (m_ColorSpace != value)
m_ColorSpace = value;
}
}
public bool IgnoreAspectRatio
{
get { return m_IgnoreAspectRatio; }
set
{
if (m_IgnoreAspectRatio != value)
m_IgnoreAspectRatio = value;
}
}
public override void ModifyMesh(VertexHelper vh)
{
if (!IsActive())
return;
Rect rect = default(Rect);
UIVertex vertex = default(UIVertex);
if (m_GradientStyle == GradientStyle.Rect)
rect = graphic.rectTransform.rect;
else if (m_GradientStyle == GradientStyle.Split)
rect.Set(0, 0, 1, 1);
else if (m_GradientStyle == GradientStyle.Fit)
{
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);
}
}
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;
}
Color color;
Vector2 nomalizedPos;
Matrix2x3 localMatrix = new Matrix2x3(rect, dir.x, dir.y);
for (int i = 0; i < vh.currentVertCount; i++)
{
vh.PopulateUIVertex(ref vertex, i);
if (m_GradientStyle == GradientStyle.Split)
nomalizedPos = localMatrix * s_SplitedCharacterPosition[i % 4] + Offset2;
else
nomalizedPos = localMatrix * vertex.position + Offset2;
if (DirectionMain == 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);
vertex.color *= (m_ColorSpace == ColorSpace.Gamma) ? color.gamma
: (m_ColorSpace == ColorSpace.Linear) ? color.linear
: color;
vh.SetUIVertex(vertex, i);
}
}
static readonly Vector2[] s_SplitedCharacterPosition = { Vector2.up, Vector2.one, Vector2.right, Vector2.zero };
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
);
}
}
}
}