Skip to content

Instantly share code, notes, and snippets.

@arif-pandu
Created July 5, 2024 15:58
Show Gist options
  • Save arif-pandu/ff3038a1596fed407effdd73070cc3c0 to your computer and use it in GitHub Desktop.
Save arif-pandu/ff3038a1596fed407effdd73070cc3c0 to your computer and use it in GitHub Desktop.
Unity procedural UI component, Rounded Rect script
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