From 39dc7f109baa49516e8061830e0cfc5cf563f2c2 Mon Sep 17 00:00:00 2001 From: mob-sakai <12690315+mob-sakai@users.noreply.github.com> Date: Wed, 8 Jan 2025 04:13:31 +0900 Subject: [PATCH] feat: `Angle Gradient` gradation supports RectTransform pivot --- Packages/src/Runtime/UIEffectContext.cs | 2 ++ .../src/Runtime/Utilities/GradientUtil.cs | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Packages/src/Runtime/UIEffectContext.cs b/Packages/src/Runtime/UIEffectContext.cs index 82ac251..276078a 100644 --- a/Packages/src/Runtime/UIEffectContext.cs +++ b/Packages/src/Runtime/UIEffectContext.cs @@ -462,6 +462,7 @@ private void ApplyGradation(List verts, Rect rect, Matrix4x4 m, bool c GradientUtil.DoRadialGradient(verts, a, b, offset, scale, rect, m, 12); break; case GradationMode.Angle: + rect = GradientUtil.RotateRectAsNormalized(rect, rot); m = Matrix4x4.Rotate(Quaternion.Euler(0, 0, rot)) * m; GradientUtil.DoHorizontalGradient(verts, a, b, offset, scale, rect, m); break; @@ -517,6 +518,7 @@ private void ApplyGradation(List verts, Rect rect, Matrix4x4 m, bool c GradientUtil.GetKeyTimes(grad, _keyTimes); } + rect = GradientUtil.RotateRectAsNormalized(rect, rot); m = Matrix4x4.Rotate(Quaternion.Euler(0, 0, rot)) * m; if (canModifyShape) { diff --git a/Packages/src/Runtime/Utilities/GradientUtil.cs b/Packages/src/Runtime/Utilities/GradientUtil.cs index 26aaaff..2ef54ea 100644 --- a/Packages/src/Runtime/Utilities/GradientUtil.cs +++ b/Packages/src/Runtime/Utilities/GradientUtil.cs @@ -339,5 +339,41 @@ static bool Contains(List list, float v) return false; } } + + public static Rect RotateRectAsNormalized(Rect rect, float rot) + { + var rad = -rot * Mathf.Deg2Rad; + var cos = Mathf.Cos(rad); + var sin = Mathf.Sin(rad); + var dir = new Vector2(cos, sin); + var center = rect.center; + + if (Mathf.Abs(dir.x) < 0.0001f) + { + rect.width = rect.height; + } + else if (Mathf.Abs(dir.y) < 0.0001f) + { + rect.height = rect.width; + } + else + { + var d0 = GetPointToLineDistance(new Vector2(rect.xMin, rect.yMax), center, dir, out var p0); + var d1 = GetPointToLineDistance(new Vector2(rect.xMin, rect.yMin), center, dir, out var p1); + var closest = d0 < d1 ? p0 : p1; + rect.width = rect.height = Vector2.Distance(center, closest) * 2; + } + + rect.center = new Vector2(Vector2.Dot(center, dir), 0); + return rect; + } + + private static float GetPointToLineDistance(Vector2 point, Vector2 origin, Vector2 dir, out Vector2 closest) + { + var dirNormalized = dir.normalized; + var time = Vector2.Dot(point - origin, dirNormalized); + closest = origin + time * dirNormalized; + return Vector2.Distance(point, closest); + } } }