/// /// Created by Freezy - ElicitIce.nl /// Posted on Unity Forums http://forum.unity3d.com/threads/cut-corners-primative.359494/ /// /// Free for any use and alteration, source code may not be sold without my permission. /// If you make improvements on this script please share them with the community. /// /// /// Here is a script that will take a rectangular TransformRect and cut off some corners based on the corner size. /// This is great for when you need a quick and easy non-square panel/image. /// Enjoy! /// It adds an additional square if the relevant side has a corner cut, it then offsets the ends to simulate a cut corner. /// UVs are being set, but might be skewed when a texture is applied. /// You could hide the additional colors by using the following: /// http://rumorgames.com/hide-in-inspector/ /// /// namespace UnityEngine.UI.Extensions { [AddComponentMenu("UI/Extensions/Primitives/Cut Corners")] public class UICornerCut : UIPrimitiveBase { public Vector2 cornerSize = new Vector2(16, 16); [Header("Corners to cut")] [SerializeField] private bool m_cutUL = true; [SerializeField] private bool m_cutUR; [SerializeField] private bool m_cutLL; [SerializeField] private bool m_cutLR; [Tooltip("Up-Down colors become Left-Right colors")] [SerializeField] private bool m_makeColumns; [Header("Color the cut bars differently")] [SerializeField] private bool m_useColorUp; [SerializeField] private Color32 m_colorUp; [SerializeField] private bool m_useColorDown; [SerializeField] private Color32 m_colorDown; public bool CutUL { get { return m_cutUL; } set { m_cutUL = value; SetAllDirty(); } } public bool CutUR { get { return m_cutUR; } set { m_cutUR = value; SetAllDirty(); } } public bool CutLL { get { return m_cutLL; } set { m_cutLL = value; SetAllDirty(); } } public bool CutLR { get { return m_cutLR; } set { m_cutLR = value; SetAllDirty(); } } public bool MakeColumns { get { return m_makeColumns; } set { m_makeColumns = value; SetAllDirty(); } } public bool UseColorUp { get { return m_useColorUp; } set { m_useColorUp = value; } } public Color32 ColorUp { get { return m_colorUp; } set { m_colorUp = value; } } public bool UseColorDown { get { return m_useColorDown; } set { m_useColorDown = value; } } public Color32 ColorDown { get { return m_colorDown; } set { m_colorDown = value; } } protected override void OnPopulateMesh(VertexHelper vh) { var rect = rectTransform.rect; var rectNew = rect; Color32 color32 = color; bool up = m_cutUL | m_cutUR; bool down = m_cutLL | m_cutLR; bool left = m_cutLL | m_cutUL; bool right = m_cutLR | m_cutUR; bool any = up | down; if (any && cornerSize.sqrMagnitude > 0) { //nibble off the sides vh.Clear(); if (left) rectNew.xMin += cornerSize.x; if (down) rectNew.yMin += cornerSize.y; if (up) rectNew.yMax -= cornerSize.y; if (right) rectNew.xMax -= cornerSize.x; //add two squares to the main square Vector2 ul, ur, ll, lr; if (m_makeColumns) { ul = new Vector2(rect.xMin, m_cutUL ? rectNew.yMax : rect.yMax); ur = new Vector2(rect.xMax, m_cutUR ? rectNew.yMax : rect.yMax); ll = new Vector2(rect.xMin, m_cutLL ? rectNew.yMin : rect.yMin); lr = new Vector2(rect.xMax, m_cutLR ? rectNew.yMin : rect.yMin); if (left) AddSquare( ll, ul, new Vector2(rectNew.xMin, rect.yMax), new Vector2(rectNew.xMin, rect.yMin), rect, m_useColorUp ? m_colorUp : color32, vh); if (right) AddSquare( ur, lr, new Vector2(rectNew.xMax, rect.yMin), new Vector2(rectNew.xMax, rect.yMax), rect, m_useColorDown ? m_colorDown : color32, vh); } else { ul = new Vector2(m_cutUL ? rectNew.xMin : rect.xMin, rect.yMax); ur = new Vector2(m_cutUR ? rectNew.xMax : rect.xMax, rect.yMax); ll = new Vector2(m_cutLL ? rectNew.xMin : rect.xMin, rect.yMin); lr = new Vector2(m_cutLR ? rectNew.xMax : rect.xMax, rect.yMin); if (down) AddSquare( lr, ll, new Vector2(rect.xMin, rectNew.yMin), new Vector2(rect.xMax, rectNew.yMin), rect, m_useColorDown ? m_colorDown : color32, vh); if (up) AddSquare( ul, ur, new Vector2(rect.xMax, rectNew.yMax), new Vector2(rect.xMin, rectNew.yMax), rect, m_useColorUp ? m_colorUp : color32, vh); } //center if (m_makeColumns) AddSquare(new Rect(rectNew.xMin, rect.yMin, rectNew.width, rect.height), rect, color32, vh); else AddSquare(new Rect(rect.xMin, rectNew.yMin, rect.width, rectNew.height), rect, color32, vh); } } private static void AddSquare(Rect rect, Rect rectUV, Color32 color32, VertexHelper vh) { int v0 = AddVert(rect.xMin, rect.yMin, rectUV, color32, vh); int v1 = AddVert(rect.xMin, rect.yMax, rectUV, color32, vh); int v2 = AddVert(rect.xMax, rect.yMax, rectUV, color32, vh); int v3 = AddVert(rect.xMax, rect.yMin, rectUV, color32, vh); vh.AddTriangle(v0, v1, v2); vh.AddTriangle(v2, v3, v0); } private static void AddSquare(Vector2 a, Vector2 b, Vector2 c, Vector2 d, Rect rectUV, Color32 color32, VertexHelper vh) { int v0 = AddVert(a.x, a.y, rectUV, color32, vh); int v1 = AddVert(b.x, b.y, rectUV, color32, vh); int v2 = AddVert(c.x, c.y, rectUV, color32, vh); int v3 = AddVert(d.x, d.y, rectUV, color32, vh); vh.AddTriangle(v0, v1, v2); vh.AddTriangle(v2, v3, v0); } /// /// Auto UV handler within the assigned area /// /// /// /// /// /// private static int AddVert(float x, float y, Rect area, Color32 color32, VertexHelper vh) { var uv = new Vector2( Mathf.InverseLerp(area.xMin, area.xMax, x), Mathf.InverseLerp(area.yMin, area.yMax, y) ); vh.AddVert(new Vector3(x, y), color32, uv); return vh.currentVertCount - 1; } } }