Skip to content

Commit

Permalink
feat: add Gradation Offset and Gradation Scale options
Browse files Browse the repository at this point in the history
close #277
  • Loading branch information
mob-sakai committed Dec 14, 2024
1 parent 622a936 commit 056836e
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 51 deletions.
6 changes: 6 additions & 0 deletions Packages/src/Editor/UIEffectEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public class UIEffect2Editor : Editor
private SerializedProperty _gradationColor1;
private SerializedProperty _gradationColor2;
private SerializedProperty _gradationGradient;
private SerializedProperty _gradationOffset;
private SerializedProperty _gradationScale;

private bool _expandOthers;
private SerializedProperty _allowExtendVertex;
Expand Down Expand Up @@ -121,6 +123,8 @@ private void OnEnable()
_gradationColor1 = serializedObject.FindProperty("m_GradationColor1");
_gradationColor2 = serializedObject.FindProperty("m_GradationColor2");
_gradationGradient = serializedObject.FindProperty("m_GradationGradient");
_gradationOffset = serializedObject.FindProperty("m_GradationOffset");
_gradationScale = serializedObject.FindProperty("m_GradationScale");

_allowExtendVertex = serializedObject.FindProperty("m_AllowExtendVertex");
}
Expand Down Expand Up @@ -280,6 +284,8 @@ public void DrawProperties()
break;
}

EditorGUILayout.PropertyField(_gradationOffset);
EditorGUILayout.PropertyField(_gradationScale);
EditorGUI.indentLevel--;
}

Expand Down
3 changes: 2 additions & 1 deletion Packages/src/Runtime/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ public enum GradationMode
HorizontalGradient,
Vertical,
VerticalGradient,
Radial,
RadialFast,
RadialDetail,
DiagonalLeftTopToRightBottom,
DiagonalRightTopToLeftBottom
}
Expand Down
39 changes: 39 additions & 0 deletions Packages/src/Runtime/UIEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ public class UIEffect : UIEffectBase
[SerializeField]
private Gradient m_GradationGradient = new Gradient();

[Range(-1, 1)]
[SerializeField]
protected float m_GradationOffset = 0;

[Range(0.01f, 1)]
[SerializeField]
protected float m_GradationScale = 1;

[SerializeField]
protected bool m_AllowExtendVertex = true;

Expand Down Expand Up @@ -611,6 +619,28 @@ public Gradient gradationGradient
}
}

public float gradationOffset
{
get => m_GradationOffset;
set
{
if (Mathf.Approximately(m_GradationOffset, value)) return;
context.gradationOffset = m_GradationOffset = value;
SetVerticesDirty();
}
}

public float gradationScale
{
get => m_GradationScale;
set
{
if (Mathf.Approximately(m_GradationScale, value)) return;
context.gradationScale = m_GradationScale = value;
SetVerticesDirty();
}
}

public bool allowExtendVertex
{
get => m_AllowExtendVertex;
Expand Down Expand Up @@ -711,6 +741,8 @@ protected override void UpdateContext(UIEffectContext c)
c.gradationColor1 = m_GradationColor1;
c.gradationColor2 = m_GradationColor2;
c.gradationGradient = m_GradationGradient;
c.gradationOffset = m_GradationOffset;
c.gradationScale = m_GradationScale;
c.allowExtendVertex = m_AllowExtendVertex;
}

Expand Down Expand Up @@ -745,6 +777,11 @@ public override void SetRate(float rate, UIEffectTweener.CullingMask mask)
{
transitionRate = rate;
}

if (gradationMode != GradationMode.None && 0 < (mask & UIEffectTweener.CullingMask.Gradiation))
{
gradationOffset = Mathf.Lerp(-1f, 1f, rate);
}
}

public override bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
Expand Down Expand Up @@ -865,6 +902,8 @@ internal void CopyFrom(UIEffectContext c)
m_GradationColor1 = c.gradationColor1;
m_GradationColor2 = c.gradationColor2;
m_GradationGradient = c.gradationGradient;
m_GradationOffset = c.gradationOffset;
m_GradationScale = c.gradationScale;

m_AllowExtendVertex = c.allowExtendVertex;

Expand Down
6 changes: 5 additions & 1 deletion Packages/src/Runtime/UIEffectContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ public class UIEffectContext
public Color gradationColor2;
public Gradient gradationGradient;
public bool allowExtendVertex;
public float gradationOffset;
public float gradationScale;

public bool willModifyMaterial => samplingFilter != SamplingFilter.None
|| transitionFilter != TransitionFilter.None
Expand Down Expand Up @@ -203,6 +205,8 @@ public void CopyFrom(UIEffectContext preset)
gradationColor1 = preset.gradationColor1;
gradationColor2 = preset.gradationColor2;
gradationGradient = preset.gradationGradient;
gradationOffset = preset.gradationOffset;
gradationScale = preset.gradationScale;

allowExtendVertex = preset.allowExtendVertex;
}
Expand Down Expand Up @@ -423,7 +427,7 @@ public void ModifyMesh(Graphic graphic, RectTransform transitionRoot, VertexHelp

// Apply gradation.
GradientUtil.DoGradient(gradationMode, verts, gradationColor1, gradationColor2, gradationGradient,
transitionRoot.rect);
gradationOffset, gradationScale, transitionRoot.rect);

// Apply shadow.
switch (shadowMode)
Expand Down
3 changes: 2 additions & 1 deletion Packages/src/Runtime/UIEffectTweener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public enum CullingMask
Tone = 1 << 0,
Color = 1 << 1,
Sampling = 1 << 2,
Transition = 1 << 3
Transition = 1 << 3,
Gradiation = 1 << 5
}

public enum UpdateMode
Expand Down
149 changes: 101 additions & 48 deletions Packages/src/Runtime/Utilities/GradientUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,111 +9,153 @@ public static class GradientUtil
private static readonly List<float> s_KeyTimes = new List<float>();

public static void DoGradient(GradationMode mode, List<UIVertex> verts, Color a, Color b, Gradient gradient,
Rect rect)
float offset, float scale, Rect rect)
{
switch (mode)
{
case GradationMode.Horizontal:
DoHorizontalGradient(verts, a, b, rect);
DoHorizontalGradient(verts, a, b, offset, scale, rect);
break;
case GradationMode.Vertical:
DoVerticalGradient(verts, a, b, rect);
DoVerticalGradient(verts, a, b, offset, scale, rect);
break;
case GradationMode.DiagonalLeftTopToRightBottom:
DoDiagonalGradientLeftTopToRightBottom(verts, a, b, rect);
DoDiagonalGradientLeftTopToRightBottom(verts, a, b, offset, scale, rect);
break;
case GradationMode.DiagonalRightTopToLeftBottom:
DoDiagonalGradientRightTopToLeftBottom(verts, a, b, rect);
DoDiagonalGradientRightTopToLeftBottom(verts, a, b, offset, scale, rect);
break;
case GradationMode.RadialFast:
DoRadialGradient(verts, a, b, offset, scale, rect, 4);
break;
case GradationMode.Radial:
DoRadialGradient(verts, a, b, rect);
case GradationMode.RadialDetail:
DoRadialGradient(verts, a, b, offset, scale, rect, 12);
break;
case GradationMode.HorizontalGradient:
DoHorizontalGradient(verts, gradient, rect);
DoHorizontalGradient(verts, gradient, offset, scale, rect);
break;
case GradationMode.VerticalGradient:
DoVerticalGradient(verts, gradient, rect);
DoVerticalGradient(verts, gradient, offset, scale, rect);
break;
}
}

private static void DoHorizontalGradient(List<UIVertex> verts, Color a, Color b, Rect rect)
private static void DoHorizontalGradient(List<UIVertex> verts, Color a, Color b, float offset, float scale,
Rect rect)
{
DoGradient(verts, a, b, rect, (x, y) => x);
DoGradient(verts, a, b, rect,
(x, y) => Mathf.Clamp01(offset + (x - 0.5f) * scale + 0.5f));
}

private static void DoHorizontalGradient(List<UIVertex> verts, Gradient gradient, Rect rect)
private static void DoHorizontalGradient(List<UIVertex> verts, Gradient gradient, float offset, float scale,
Rect rect)
{
GetKeyTimes(gradient, s_KeyTimes);
GetKeyTimes(gradient, s_KeyTimes, offset, scale);
var count = verts.Count;
for (var i = 0; i < verts.Count; i += 6)
{
GetBundle(verts, i, out var lb, out var lt, out var rt, out var rb);

if (i + 5 < count)
{
SplitHorizontal(verts, lb, lt, ref rb, ref rt, rect, s_KeyTimes);
}

lb.color *= gradient.Evaluate(Mathf.InverseLerp(rect.xMin, rect.xMax, lb.position.x + 0.0001f));
lt.color *= gradient.Evaluate(Mathf.InverseLerp(rect.xMin, rect.xMax, lt.position.x + 0.0001f));
rt.color *= gradient.Evaluate(Mathf.InverseLerp(rect.xMin, rect.xMax, rt.position.x - 0.0001f));
rb.color *= gradient.Evaluate(Mathf.InverseLerp(rect.xMin, rect.xMax, rb.position.x - 0.0001f));
lb.color *= EvaluateHorizontal(gradient, rect, lb.position.x + 0.0001f, offset, scale);
lt.color *= EvaluateHorizontal(gradient, rect, lt.position.x + 0.0001f, offset, scale);
rt.color *= EvaluateHorizontal(gradient, rect, rt.position.x - 0.0001f, offset, scale);
rb.color *= EvaluateHorizontal(gradient, rect, rb.position.x - 0.0001f, offset, scale);
SetBundle(verts, i, lb, lt, rt, rb);
}

return;

static Color EvaluateHorizontal(Gradient gradient, Rect rect, float t, float offset, float scale)
{
t = Mathf.InverseLerp(rect.xMin, rect.xMax, t);
t = Mathf.Repeat(t * scale - 1 + scale - scale * offset, 1);
return gradient.Evaluate(t);
}
}

private static void DoVerticalGradient(List<UIVertex> verts, Color a, Color b, Rect rect)
private static void DoVerticalGradient(List<UIVertex> verts, Color a, Color b, float offset, float scale,
Rect rect)
{
DoGradient(verts, a, b, rect, (x, y) => 1 - y);
DoGradient(verts, a, b, rect,
(x, y) => Mathf.Clamp01(offset + (0.5f - y) * scale + 0.5f));
}

private static void DoVerticalGradient(List<UIVertex> verts, Gradient gradient, Rect rect)
private static void DoVerticalGradient(List<UIVertex> verts, Gradient gradient, float offset, float scale,
Rect rect)
{
GetKeyTimes(gradient, s_KeyTimes);
GetKeyTimes(gradient, s_KeyTimes, offset, scale);
var count = verts.Count;
for (var i = 0; i < verts.Count; i += 6)
{
GetBundle(verts, i, out var lb, out var lt, out var rt, out var rb);

if (i + 5 < count)
{
SplitVertical(verts, lb, ref lt, rb, ref rt, rect, s_KeyTimes);
}

lb.color *= gradient.Evaluate(Mathf.InverseLerp(rect.yMin, rect.yMax, lb.position.y + 0.0001f));
lt.color *= gradient.Evaluate(Mathf.InverseLerp(rect.yMin, rect.yMax, lt.position.y - 0.0001f));
rt.color *= gradient.Evaluate(Mathf.InverseLerp(rect.yMin, rect.yMax, rt.position.y - 0.0001f));
rb.color *= gradient.Evaluate(Mathf.InverseLerp(rect.yMin, rect.yMax, rb.position.y + 0.0001f));
lb.color *= EvaluateVertical(gradient, rect, lb.position.y + 0.0001f, offset, scale);
lt.color *= EvaluateVertical(gradient, rect, lt.position.y + 0.0001f, offset, scale);
rt.color *= EvaluateVertical(gradient, rect, rt.position.y - 0.0001f, offset, scale);
rb.color *= EvaluateVertical(gradient, rect, rb.position.y - 0.0001f, offset, scale);
SetBundle(verts, i, lb, lt, rt, rb);
}

return;

static Color EvaluateVertical(Gradient gradient, Rect rect, float t, float offset, float scale)
{
t = Mathf.InverseLerp(rect.yMin, rect.yMax, t);
t = Mathf.Repeat(t * scale - 1 + scale - scale * offset, 1);
return gradient.Evaluate(t);
}
}

private static void DoDiagonalGradientLeftTopToRightBottom(List<UIVertex> verts, Color a, Color b, Rect rect)
private static void DoDiagonalGradientLeftTopToRightBottom(List<UIVertex> verts, Color a, Color b, float offset,
float scale,
Rect rect)
{
DoGradient(verts, a, b, rect, (x, y) => 1 - (1 - x + y) / 2);
DoGradient(verts, a, b, rect,
(x, y) => Mathf.Clamp01(0.5f * scale + 0.5f + offset - (1 - x + y) * scale / 2));
}

private static void DoDiagonalGradientRightTopToLeftBottom(List<UIVertex> verts, Color a, Color b, Rect rect)
private static void DoDiagonalGradientRightTopToLeftBottom(List<UIVertex> verts, Color a, Color b, float offset,
float scale,
Rect rect)
{
DoGradient(verts, a, b, rect, (x, y) => 1 - (x + y) / 2);
DoGradient(verts, a, b, rect,
(x, y) => Mathf.Clamp01(0.5f * scale + 0.5f + offset - (x + y) * scale / 2));
}

private static void DoRadialGradient(List<UIVertex> verts, Color a, Color b, Rect rect)
private static void DoRadialGradient(List<UIVertex> verts, Color a, Color b, float offset, float scale,
Rect rect, int divide)
{
var count = verts.Count;
for (var i = 0; i < count; i += 6)
{
GetBundle(verts, i, out var lb, out var lt, out var rt, out var rb);
for (var j = 1; j < divide; j++)
{
SplitHorizontal(verts, lb, lt, ref rb, ref rt, rect, 1f - (float)j / divide);
}

SetBundle(verts, i, lb, lt, rt, rb);
}

count = verts.Count;
for (var i = 0; i < verts.Count; i += 6)
{
GetBundle(verts, i, out var lb, out var lt, out var rt, out var rb);

if (i + 5 < count)
{
SplitHorizontal(verts, lb, lt, ref rb, ref rt, rect, 0.25f);
SplitHorizontal(verts, lb, lt, ref rb, ref rt, rect, 0.5f);
SplitHorizontal(verts, lb, lt, ref rb, ref rt, rect, 0.75f);
SplitVertical(verts, lb, ref lt, rb, ref rt, rect, 0.25f);
SplitVertical(verts, lb, ref lt, rb, ref rt, rect, 0.5f);
SplitVertical(verts, lb, ref lt, rb, ref rt, rect, 0.75f);
for (var j = 1; j < divide; j++)
{
SplitVertical(verts, lb, ref lt, rb, ref rt, rect, 1f - (float)j / divide);
}
}

lb.color *= DoGradient(lb, a, b, rect, Rad);
Expand All @@ -127,7 +169,7 @@ float Rad(float x, float y)
{
x -= 0.5f;
y -= 0.5f;
return Mathf.Sqrt(x * x + y * y) * 2;
return Mathf.Clamp01(offset + Mathf.Sqrt(x * x + y * y) * 2 * scale);
}
}
}
Expand Down Expand Up @@ -228,30 +270,41 @@ private static void SplitVertical(List<UIVertex> verts, UIVertex lb, ref UIVerte
rt = rm;
}

private static void GetKeyTimes(Gradient gradient, List<float> results)
private static void GetKeyTimes(Gradient gradient, List<float> results, float offset, float scale)
{
results.Clear();
var colors = gradient.colorKeys;
for (var i = 0; i < colors.Length; i++)
{
var t = colors[i].time;
if (t <= 0 || 1 <= t) continue;

results.Add(colors[i].time);
AddKeyTime(results, colors[i].time, offset, scale);
}

var alphas = gradient.alphaKeys;
for (var i = 0; i < alphas.Length; i++)
{
var t = alphas[i].time;
if (t <= 0 || 1 <= t || results.Contains(t)) continue;

results.Add(t);
AddKeyTime(results, alphas[i].time, offset, scale);
}

AddKeyTime(results, 0, offset, scale);
AddKeyTime(results, 1, offset, scale);
results.Sort((a, b) => b.CompareTo(a));
}

private static void AddKeyTime(List<float> results, float value, float offset, float scale)
{
scale = 1f / scale;
value = value * scale + offset - 1;
while (value < 1f)
{
if (0 < value && results.FindIndex(x => Mathf.Abs(x - value) < 0.001f) < 0)
{
results.Add(value);
}

value += scale;
}
}

private static void GetBundle(List<UIVertex> verts, int i, out UIVertex lb, out UIVertex lt, out UIVertex rt,
out UIVertex rb)
{
Expand Down

0 comments on commit 056836e

Please sign in to comment.