/// Credit Steve Westhoff, jack.sydorenko, firagon /// Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/324 /// Refactored and updated for performance from UILineRenderer by Steve Westhoff using System.Collections.Generic; namespace UnityEngine.UI.Extensions { [AddComponentMenu("UI/Extensions/Primitives/UILineRendererFIFO")] [RequireComponent(typeof(RectTransform))] public class UILineRendererFIFO : UIPrimitiveBase { private static readonly Vector2[] middleUvs = new[] { new Vector2(0.5f, 0), new Vector2(0.5f, 1), new Vector2(0.5f, 1), new Vector2(0.5f, 0) }; private List addedPoints = new List(); private bool needsResize; [SerializeField, Tooltip("Thickness of the line")] private float lineThickness = 1; [SerializeField, Tooltip("Points to draw lines between\n Can be improved using the Resolution Option")] private List points = new List(); [SerializeField, Tooltip("Segments to be drawn\n This is a list of arrays of points")] private List segments = new List(); /// /// Thickness of the line /// public float LineThickness { get { return lineThickness; } set { lineThickness = value; SetAllDirty(); } } /// /// Points to be drawn in the line. /// /// Don't add points to the list directly, use the add / remove functions public List Points { get { return points; } set { if (points == value) return; points = value; SetAllDirty(); } } /// /// Adds to head /// /// public void AddPoint(Vector2 point) { points.Add(point); addedPoints.Add(point); } /// /// Removes from tail (FIFO) /// public void RemovePoint() { points.RemoveAt(0); needsResize = true; } /// /// Clear all the points from the LineRenderer /// public void ClearPoints() { segments.Clear(); points.Clear(); addedPoints.Clear(); needsResize = false; } public void Resize() { needsResize = true; } protected override void OnPopulateMesh(VertexHelper vertexHelper) { vertexHelper.Clear(); if(needsResize) { needsResize = false; segments.Clear(); addedPoints = new List(points); } int count = addedPoints.Count; if(count > 1) { PopulateMesh(addedPoints, vertexHelper); if(count % 2 == 0) { addedPoints.Clear(); } else { Vector2 extraPoint = addedPoints[count - 1]; addedPoints.Clear(); addedPoints.Add(extraPoint); } } } void PopulateMesh(List pointsToDraw, VertexHelper vertexHelper) { if(ImproveResolution != ResolutionMode.None) { pointsToDraw = IncreaseResolution(pointsToDraw); } float sizeX = rectTransform.rect.width; float sizeY = rectTransform.rect.height; float offsetX = -rectTransform.pivot.x * sizeX; float offsetY = -rectTransform.pivot.y * sizeY; for(int i = 1; i < pointsToDraw.Count; i += 2) { Vector2 start = pointsToDraw[i - 1]; Vector2 end = pointsToDraw[i]; start = new Vector2(start.x * sizeX + offsetX, start.y * sizeY + offsetY); end = new Vector2(end.x * sizeX + offsetX, end.y * sizeY + offsetY); UIVertex[] segment = CreateLineSegment(start, end, segments.Count > 1 ? segments[segments.Count - 2] : null); segments.Add(segment); } for(int i = 0; i < segments.Count; i++) { vertexHelper.AddUIVertexQuad(segments[i]); } if(vertexHelper.currentVertCount > 64000) { Debug.LogError("Max Verticies size is 64000, current mesh vertcies count is [" + vertexHelper.currentVertCount + "] - Cannot Draw"); vertexHelper.Clear(); } } UIVertex[] CreateLineSegment(Vector2 start, Vector2 end, UIVertex[] previousVert = null) { Vector2 offset = new Vector2(start.y - end.y, end.x - start.x).normalized * lineThickness * 0.5f; Vector2 v1; Vector2 v2; if(previousVert != null) { v1 = new Vector2(previousVert[3].position.x, previousVert[3].position.y); v2 = new Vector2(previousVert[2].position.x, previousVert[2].position.y); } else { v1 = start - offset; v2 = start + offset; } return SetVbo(new[] { v1, v2, end + offset, end - offset }, middleUvs); } } }