Skip to content

Instantly share code, notes, and snippets.

@CGPala
Created November 19, 2016 12:29
Show Gist options
  • Save CGPala/d1ace7dddbfbe78cd2de2bb9e40f6393 to your computer and use it in GitHub Desktop.
Save CGPala/d1ace7dddbfbe78cd2de2bb9e40f6393 to your computer and use it in GitHub Desktop.
Unity simple UI line renderer
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class UILineRenderer : Graphic
{
[SerializeField] Texture m_Texture;
[SerializeField] Rect m_UVRect = new Rect(0f, 0f, 1f, 1f);
public float LineThickness = 2;
public bool UseMargins;
public Vector2 Margin;
public Vector2[] Points;
public bool relativeSize;
public override Texture mainTexture
{
get
{
return m_Texture == null ? s_WhiteTexture : m_Texture;
}
}
/// <summary>
/// Texture to be used.
/// </summary>
public Texture texture
{
get
{
return m_Texture;
}
set
{
if (m_Texture == value)
return;
m_Texture = value;
SetVerticesDirty();
SetMaterialDirty();
}
}
/// <summary>
/// UV rectangle used by the texture.
/// </summary>
public Rect uvRect
{
get
{
return m_UVRect;
}
set
{
if (m_UVRect == value)
return;
m_UVRect = value;
SetVerticesDirty();
}
}
protected override void OnFillVBO(List<UIVertex> vbo)
{
// requires sets of quads
if (Points == null || Points.Length < 2)
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 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<Vector2> ();
pointList.Add (Points [0]);
var capPoint = Points [0] + (Points [1] - Points [0]).normalized * capSize;
pointList.Add (capPoint);
// should bail before the last point to add another cap point
for (int i = 1; i < Points.Length-1; i++)
{
pointList.Add (Points [i]);
}
capPoint = Points [Points.Length-1] - (Points [Points.Length-1] - Points [Points.Length-2]).normalized * capSize;
pointList.Add (capPoint);
pointList.Add (Points [Points.Length - 1]);
var TempPoints = pointList.ToArray ();
if (UseMargins)
{
sizeX -= Margin.x;
sizeY -= Margin.y;
offsetX += Margin.x/2f;
offsetY += Margin.y/2f;
}
vbo.Clear();
Vector2 prevV1 = Vector2.zero;
Vector2 prevV2 = Vector2.zero;
for (int i = 1; i < TempPoints.Length; i++)
{
var prev = TempPoints[i - 1];
var cur = TempPoints[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)
SetVbo(vbo, new[] { prevV1, prevV2, v1, v2 }, uvs);
if(i==1)
uvs = new[]{ uvTopLeft,uvBottomLeft,uvBottomCenter,uvTopCenter };
else if(i==TempPoints.Length-1)
uvs = new[]{uvTopCenter,uvBottomCenter, uvBottomRight, uvTopRight };
SetVbo(vbo, new[] { v1, v2, v3, v4 }, uvs);
prevV1 = v3;
prevV2 = v4;
}
}
protected void SetVbo(List<UIVertex> vbo, Vector2[] vertices, Vector2[] uvs)
{
for (int i = 0; i < vertices.Length; i++)
{
var vert = UIVertex.simpleVert;
vert.color = color;
vert.position = vertices[i];
vert.uv0 = uvs [i];
vbo.Add(vert);
}
}
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
}
}
@AbdurrahmanKh
Copy link

it doesn’t work it just shows a rectangle

@eldonwilliams
Copy link

Thank you for this CGPala,

For anyone coming across this in the future, I've trial-and-error'ed my way to a solution that uses the new OnPopulateMesh(VertexHelper) method. It works for me, but it may not work for you.
https://gist.github.com/eldonwilliams/4d4d014416578e7a990834c512f75cec

If you're a whizz with render stuff please improve my code! I just hacked it together and would love a better solution :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment