Created
October 17, 2023 22:20
-
-
Save mitay-walle/8310d6cdf19d6a122bbe1a88c1acfdca to your computer and use it in GitHub Desktop.
Unity uGUI Circle Layout Group
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEditor; | |
using UnityEngine; | |
using UnityEngine.UI; | |
namespace Plugins.mitaywalle.UI.Layout | |
{ | |
[ExecuteAlways] | |
public class UICircleLayoutGroup : LayoutGroup | |
{ | |
static readonly Vector2 HALF_VECTOR = new Vector2(0.5f, 0.5f); | |
[SerializeField] float innerRadius = 100; | |
[Range(-360, 360)] public float offset; | |
[Range(0, 360)] public float maxDegree = 360; | |
[SerializeField] bool Resize = true; | |
[SerializeField] bool reverseArrangement; | |
public int count { get; private set; } | |
public int ChildCount() => rectChildren.Count; | |
public float IndexOf(RectTransform rectTransform1) => rectChildren.IndexOf(rectTransform1); | |
protected override void OnTransformChildrenChanged() | |
{ | |
base.OnTransformChildrenChanged(); | |
CalculateRadial(); | |
} | |
public override void SetLayoutVertical() => CalculateRadial(); | |
public override void SetLayoutHorizontal() => CalculateRadial(); | |
public override void CalculateLayoutInputVertical() => CalculateRadial(); | |
public override void CalculateLayoutInputHorizontal() => CalculateRadial(); | |
protected override void OnRectTransformDimensionsChange() => CalculateRadial(); | |
void CalculateRadial() | |
{ | |
if (transform.childCount == 0) return; | |
base.CalculateLayoutInputHorizontal(); | |
var children = rectChildren; | |
int childrenToFormat = children.Count; | |
m_Tracker.Clear(); | |
count = childrenToFormat; | |
Rect rect = rectTransform.rect; | |
float radiusX = rect.width / 2; | |
float radiusY = rect.height / 2; | |
radiusX -= innerRadius / 2; | |
radiusY -= innerRadius / 2; | |
float degreeStep = maxDegree / childrenToFormat; | |
float currentDegree = offset + degreeStep / 2; | |
if (reverseArrangement) | |
{ | |
degreeStep *= -1; | |
currentDegree *= -1; | |
} | |
DrivenTransformProperties properties = DrivenTransformProperties.Anchors | | |
DrivenTransformProperties.AnchoredPosition | | |
DrivenTransformProperties.Pivot; | |
Vector2 sizeVector = default; | |
if (Resize) properties |= DrivenTransformProperties.SizeDelta; | |
if (Resize) | |
{ | |
float size = GetSize(childrenToFormat, maxDegree); | |
sizeVector = new Vector2(size, size); | |
} | |
for (int i = 0; i < childrenToFormat; i++) | |
{ | |
RectTransform child = children[i]; | |
m_Tracker.Add(this, child, properties); | |
var vector = new Vector3(Mathf.Cos(currentDegree * Mathf.Deg2Rad) * radiusX, Mathf.Sin(currentDegree * Mathf.Deg2Rad) * radiusY, 0); | |
child.localPosition = vector; | |
child.anchorMin = child.anchorMax = child.pivot = HALF_VECTOR; | |
if (Resize) child.sizeDelta = sizeVector; | |
currentDegree += degreeStep; | |
} | |
LayoutRebuilder.MarkLayoutForRebuild(rectTransform); | |
} | |
float GetSize(int childrenCount, float maxAngle) | |
{ | |
float outer = rectTransform.rect.width / 2; | |
float inner = outer - innerRadius; | |
float halfRadius = outer - inner; | |
float size1 = Mathf.Abs(outer - inner); | |
float step = maxAngle / childrenCount; | |
Vector3 vector = new Vector2(1 * halfRadius, 0); | |
Vector3 vector2 = new Vector2(Mathf.Cos(step * Mathf.Deg2Rad) * halfRadius, Mathf.Sin(step * Mathf.Deg2Rad) * halfRadius); | |
float size2 = (vector - vector2).magnitude; | |
float size = Mathf.Min(size1, size2); | |
return size; | |
} | |
#if UNITY_EDITOR | |
protected override void OnValidate() | |
{ | |
base.OnValidate(); | |
EditorApplication.delayCall += CalculateRadial; | |
} | |
#endif | |
} | |
} |
Author
mitay-walle
commented
Oct 17, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment