159 lines
5.6 KiB
C#
159 lines
5.6 KiB
C#
|
/// 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 : UIPrimitiveBase
|
|||
|
{
|
|||
|
[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;
|
|||
|
|
|||
|
/// <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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Points to be drawn in the line.
|
|||
|
/// </summary>
|
|||
|
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<Vector2>();
|
|||
|
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
|
|||
|
}
|
|||
|
}
|
|||
|
}
|