Created
July 5, 2024 15:58
-
-
Save arif-pandu/ff3038a1596fed407effdd73070cc3c0 to your computer and use it in GitHub Desktop.
Unity procedural UI component, Rounded Rect script
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 UnityEngine; | |
using UnityEngine.UI; | |
[RequireComponent(typeof(CanvasRenderer))] | |
public class RoundedRect : Graphic | |
{ | |
[SerializeField] private float m_CornerRadius = 10f; | |
[SerializeField] private float m_BorderWidth = 1f; | |
[SerializeField] private Color m_BorderColor = Color.black; | |
[SerializeField] private int m_CornerSegments = 20; | |
public float cornerRadius | |
{ | |
get { return m_CornerRadius; } | |
set | |
{ | |
m_CornerRadius = value; | |
SetVerticesDirty(); | |
} | |
} | |
public float borderWidth | |
{ | |
get { return m_BorderWidth; } | |
set | |
{ | |
m_BorderWidth = value; | |
SetVerticesDirty(); | |
} | |
} | |
public Color borderColor | |
{ | |
get { return m_BorderColor; } | |
set | |
{ | |
m_BorderColor = value; | |
SetVerticesDirty(); | |
} | |
} | |
protected override void OnPopulateMesh(VertexHelper vh) | |
{ | |
vh.Clear(); | |
Rect rect = rectTransform.rect; | |
Vector2 pivot = rectTransform.pivot; | |
Vector2 bottomLeft = -rect.size * pivot; | |
Vector2 topRight = rect.size - rect.size * pivot; | |
float minSize = Mathf.Min(rect.width, rect.height); | |
float radius = Mathf.Clamp(m_CornerRadius, 0, minSize / 2); | |
if (m_BorderWidth > 0) | |
{ | |
// Outer rectangle (border) | |
AddRoundedRectangle(vh, bottomLeft, topRight, radius, m_BorderColor); | |
// Inner rectangle (fill) | |
AddRoundedRectangle(vh, | |
bottomLeft + Vector2.one * m_BorderWidth, | |
topRight - Vector2.one * m_BorderWidth, | |
Mathf.Max(0, radius - m_BorderWidth), | |
color); | |
} | |
else | |
{ | |
// Only fill if there is no border | |
AddRoundedRectangle(vh, bottomLeft, topRight, radius, color); | |
} | |
} | |
private void AddRoundedRectangle(VertexHelper vh, Vector2 bottomLeft, Vector2 topRight, float radius, Color vertexColor) | |
{ | |
int startIndex = vh.currentVertCount; | |
// Add corners | |
AddCorner(vh, bottomLeft + new Vector2(radius, radius), radius, 180, 270, vertexColor); | |
AddCorner(vh, new Vector2(topRight.x - radius, bottomLeft.y + radius), radius, 270, 360, vertexColor); | |
AddCorner(vh, topRight - new Vector2(radius, radius), radius, 0, 90, vertexColor); | |
AddCorner(vh, new Vector2(bottomLeft.x + radius, topRight.y - radius), radius, 90, 180, vertexColor); | |
// Add center vertices | |
vh.AddVert(new Vector3(bottomLeft.x, bottomLeft.y + radius), vertexColor, Vector2.zero); | |
vh.AddVert(new Vector3(bottomLeft.x, topRight.y - radius), vertexColor, Vector2.zero); | |
vh.AddVert(new Vector3(bottomLeft.x + radius, bottomLeft.y), vertexColor, Vector2.zero); | |
vh.AddVert(new Vector3(topRight.x - radius, bottomLeft.y), vertexColor, Vector2.zero); | |
vh.AddVert(new Vector3(topRight.x, bottomLeft.y + radius), vertexColor, Vector2.zero); | |
vh.AddVert(new Vector3(topRight.x, topRight.y - radius), vertexColor, Vector2.zero); | |
vh.AddVert(new Vector3(topRight.x - radius, topRight.y), vertexColor, Vector2.zero); | |
vh.AddVert(new Vector3(bottomLeft.x + radius, topRight.y), vertexColor, Vector2.zero); | |
// Add center vertex | |
vh.AddVert(new Vector3((bottomLeft.x + topRight.x) / 2, (bottomLeft.y + topRight.y) / 2), vertexColor, Vector2.zero); | |
int centerIndex = vh.currentVertCount - 1; | |
// Add triangles | |
int vertexCount = vh.currentVertCount - startIndex; | |
for (int i = startIndex; i < startIndex + vertexCount - 1; i++) | |
{ | |
vh.AddTriangle(i, i + 1, centerIndex); | |
} | |
vh.AddTriangle(startIndex + vertexCount - 1, startIndex, centerIndex); | |
} | |
private void AddCorner(VertexHelper vh, Vector2 center, float radius, float startAngle, float endAngle, Color vertexColor) | |
{ | |
float angleStep = (endAngle - startAngle) / m_CornerSegments; | |
for (int i = 0; i <= m_CornerSegments; i++) | |
{ | |
float angle = (startAngle + i * angleStep) * Mathf.Deg2Rad; | |
float cosAngle = Mathf.Cos(angle); | |
float sinAngle = Mathf.Sin(angle); | |
float x = center.x + radius * cosAngle; | |
float y = center.y + radius * sinAngle; | |
vh.AddVert(new Vector3(x, y), vertexColor, Vector2.zero); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment