/// Credit jonbro5556 /// Based on original LineRender script by jack.sydorenko /// Sourced from - http://forum.unity3d.com/threads/new-ui-and-line-drawing.253772/ using System.Collections.Generic; namespace UnityEngine.UI.Extensions { [AddComponentMenu("UI/Extensions/Primitives/UILineTextureRenderer")] public class UILineTextureRenderer : UIPrimativeBase { [SerializeField] Rect m_UVRect = new Rect(0f, 0f, 1f, 1f); [SerializeField] private Vector2[] m_points; public float LineThickness = 2; public bool UseMargins; public Vector2 Margin; public bool relativeSize; /// /// UV rectangle used by the texture. /// public Rect uvRect { get { return m_UVRect; } set { if (m_UVRect == value) return; m_UVRect = value; SetVerticesDirty(); } } /// /// Points to be drawn in the line. /// public Vector2[] Points { get { return m_points; } set { if (m_points == value) return; m_points = value; SetAllDirty(); } } protected override void OnPopulateMesh(VertexHelper vh) { // requires sets of quads if (m_points == null || m_points.Length < 2) m_points = new[] { new Vector2(0, 0), new Vector2(1, 1) }; var capSize = 24; var sizeX = rectTransform.rect.width; var sizeY = rectTransform.rect.height; var offsetX = -rectTransform.pivot.x * rectTransform.rect.width; var offsetY = -rectTransform.pivot.y * rectTransform.rect.height; // don't want to scale based on the size of the rect, so this is switchable now if (!relativeSize) { sizeX = 1; sizeY = 1; } // build a new set of m_points taking into account the cap sizes. // would be cool to support corners too, but that might be a bit tough :) var pointList = new List(); pointList.Add(m_points[0]); var capPoint = m_points[0] + (m_points[1] - m_points[0]).normalized * capSize; pointList.Add(capPoint); // should bail before the last point to add another cap point for (int i = 1; i < m_points.Length - 1; i++) { pointList.Add(m_points[i]); } capPoint = m_points[m_points.Length - 1] - (m_points[m_points.Length - 1] - m_points[m_points.Length - 2]).normalized * capSize; pointList.Add(capPoint); pointList.Add(m_points[m_points.Length - 1]); var Tempm_points = pointList.ToArray(); if (UseMargins) { sizeX -= Margin.x; sizeY -= Margin.y; offsetX += Margin.x / 2f; offsetY += Margin.y / 2f; } vh.Clear(); Vector2 prevV1 = Vector2.zero; Vector2 prevV2 = Vector2.zero; for (int i = 1; i < Tempm_points.Length; i++) { var prev = Tempm_points[i - 1]; var cur = Tempm_points[i]; prev = new Vector2(prev.x * sizeX + offsetX, prev.y * sizeY + offsetY); cur = new Vector2(cur.x * sizeX + offsetX, cur.y * sizeY + offsetY); float angle = Mathf.Atan2(cur.y - prev.y, cur.x - prev.x) * 180f / Mathf.PI; var v1 = prev + new Vector2(0, -LineThickness / 2); var v2 = prev + new Vector2(0, +LineThickness / 2); var v3 = cur + new Vector2(0, +LineThickness / 2); var v4 = cur + new Vector2(0, -LineThickness / 2); v1 = RotatePointAroundPivot(v1, prev, new Vector3(0, 0, angle)); v2 = RotatePointAroundPivot(v2, prev, new Vector3(0, 0, angle)); v3 = RotatePointAroundPivot(v3, cur, new Vector3(0, 0, angle)); v4 = RotatePointAroundPivot(v4, cur, new Vector3(0, 0, angle)); Vector2 uvTopLeft = Vector2.zero; Vector2 uvBottomLeft = new Vector2(0, 1); Vector2 uvTopCenter = new Vector2(0.5f, 0); Vector2 uvBottomCenter = new Vector2(0.5f, 1); Vector2 uvTopRight = new Vector2(1, 0); Vector2 uvBottomRight = new Vector2(1, 1); Vector2[] uvs = new[] { uvTopCenter, uvBottomCenter, uvBottomCenter, uvTopCenter }; if (i > 1) vh.AddUIVertexQuad(SetVbo(new[] { prevV1, prevV2, v1, v2 }, uvs)); if (i == 1) uvs = new[] { uvTopLeft, uvBottomLeft, uvBottomCenter, uvTopCenter }; else if (i == Tempm_points.Length - 1) uvs = new[] { uvTopCenter, uvBottomCenter, uvBottomRight, uvTopRight }; vh.AddUIVertexQuad(SetVbo(new[] { v1, v2, v3, v4 }, uvs)); prevV1 = v3; prevV2 = v4; } } public Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angles) { Vector3 dir = point - pivot; // get point direction relative to pivot dir = Quaternion.Euler(angles) * dir; // rotate it point = dir + pivot; // calculate rotated point return point; // return it } } }