Added a new Line Renderer mode (Catenary)
parent
a1b2b38a0f
commit
11ee80411f
|
@ -133,7 +133,7 @@ GameObject:
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 0
|
m_IsActive: 1
|
||||||
--- !u!114 &114012036402784198
|
--- !u!114 &114012036402784198
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 1
|
m_ObjectHideFlags: 1
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
Quick,
|
Quick,
|
||||||
Basic,
|
Basic,
|
||||||
Improved,
|
Improved,
|
||||||
}
|
Catenary,
|
||||||
|
}
|
||||||
|
|
||||||
private const float MIN_MITER_JOIN = 15 * Mathf.Deg2Rad;
|
private const float MIN_MITER_JOIN = 15 * Mathf.Deg2Rad;
|
||||||
|
|
||||||
|
@ -42,18 +43,18 @@ namespace UnityEngine.UI.Extensions
|
||||||
private static Vector2 UV_TOP_LEFT, UV_BOTTOM_LEFT, UV_TOP_CENTER_LEFT, UV_TOP_CENTER_RIGHT, UV_BOTTOM_CENTER_LEFT, UV_BOTTOM_CENTER_RIGHT, UV_TOP_RIGHT, UV_BOTTOM_RIGHT;
|
private static Vector2 UV_TOP_LEFT, UV_BOTTOM_LEFT, UV_TOP_CENTER_LEFT, UV_TOP_CENTER_RIGHT, UV_BOTTOM_CENTER_LEFT, UV_BOTTOM_CENTER_RIGHT, UV_TOP_RIGHT, UV_BOTTOM_RIGHT;
|
||||||
private static Vector2[] startUvs, middleUvs, endUvs, fullUvs;
|
private static Vector2[] startUvs, middleUvs, endUvs, fullUvs;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField, Tooltip("Points to draw lines between\n Can be improved using the Resolution Option")]
|
||||||
internal Vector2[] m_points;
|
internal Vector2[] m_points;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField, Tooltip("Thickness of the line")]
|
||||||
internal float lineThickness = 2;
|
internal float lineThickness = 2;
|
||||||
[SerializeField]
|
[SerializeField, Tooltip("Use the relative bounds of the Rect Transform (0,0 -> 0,1) or screen space coordinates")]
|
||||||
internal bool relativeSize;
|
internal bool relativeSize;
|
||||||
[SerializeField]
|
[SerializeField, Tooltip("Do the points identify a single line or split pairs of lines")]
|
||||||
internal bool lineList;
|
internal bool lineList;
|
||||||
[SerializeField]
|
[SerializeField, Tooltip("Add end caps to each line\nMultiple caps when used with Line List")]
|
||||||
internal bool lineCaps;
|
internal bool lineCaps;
|
||||||
[SerializeField]
|
[SerializeField, Tooltip("Resolution of the Bezier curve, different to line Resolution")]
|
||||||
internal int bezierSegmentsPerCurve = 10;
|
internal int bezierSegmentsPerCurve = 10;
|
||||||
|
|
||||||
public float LineThickness
|
public float LineThickness
|
||||||
|
@ -80,9 +81,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
set { lineCaps = value; SetAllDirty(); }
|
set { lineCaps = value; SetAllDirty(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Tooltip("The type of Join used between lines, Square/Mitre or Curved/Bevel")]
|
||||||
public JoinType LineJoins = JoinType.Bevel;
|
public JoinType LineJoins = JoinType.Bevel;
|
||||||
|
|
||||||
public BezierType BezierMode = BezierType.None;
|
[Tooltip("Bezier method to apply to line, see docs for options\nCan't be used in conjunction with Resolution as Bezier already changes the resolution")]
|
||||||
|
public BezierType BezierMode = BezierType.None;
|
||||||
|
|
||||||
public int BezierSegmentsPerCurve
|
public int BezierSegmentsPerCurve
|
||||||
{
|
{
|
||||||
|
@ -120,7 +123,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
GeneratedUVs();
|
GeneratedUVs();
|
||||||
Vector2[] pointsToDraw = m_points;
|
Vector2[] pointsToDraw = m_points;
|
||||||
//If Bezier is desired, pick the implementation
|
//If Bezier is desired, pick the implementation
|
||||||
if (BezierMode != BezierType.None && m_points.Length > 3)
|
if (BezierMode != BezierType.None && BezierMode != BezierType.Catenary && m_points.Length > 3)
|
||||||
{
|
{
|
||||||
BezierPath bezierPath = new BezierPath();
|
BezierPath bezierPath = new BezierPath();
|
||||||
|
|
||||||
|
@ -142,6 +145,13 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
pointsToDraw = drawingPoints.ToArray();
|
pointsToDraw = drawingPoints.ToArray();
|
||||||
}
|
}
|
||||||
|
if (BezierMode == BezierType.Catenary && m_points.Length == 2)
|
||||||
|
{
|
||||||
|
CableCurve cable = new CableCurve(pointsToDraw);
|
||||||
|
cable.slack = Resoloution;
|
||||||
|
cable.steps = BezierSegmentsPerCurve;
|
||||||
|
pointsToDraw = cable.Points();
|
||||||
|
}
|
||||||
|
|
||||||
if (ImproveResolution != ResolutionMode.None)
|
if (ImproveResolution != ResolutionMode.None)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
/// Credit Farfarer
|
||||||
|
/// Sourced from - https://gist.github.com/Farfarer/a765cd07920d48a8713a0c1924db6d70
|
||||||
|
/// Updated for UI / 2D - SimonDarksideJ
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
[System.Serializable]
|
||||||
|
public class CableCurve
|
||||||
|
{
|
||||||
|
[SerializeField]
|
||||||
|
Vector2 m_start;
|
||||||
|
[SerializeField]
|
||||||
|
Vector2 m_end;
|
||||||
|
[SerializeField]
|
||||||
|
float m_slack;
|
||||||
|
[SerializeField]
|
||||||
|
int m_steps;
|
||||||
|
[SerializeField]
|
||||||
|
bool m_regen;
|
||||||
|
|
||||||
|
static Vector2[] emptyCurve = new Vector2[] { new Vector2(0.0f, 0.0f), new Vector2(0.0f, 0.0f) };
|
||||||
|
[SerializeField]
|
||||||
|
Vector2[] points;
|
||||||
|
|
||||||
|
public bool regenPoints
|
||||||
|
{
|
||||||
|
get { return m_regen; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_regen = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 start
|
||||||
|
{
|
||||||
|
get { return m_start; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != m_start)
|
||||||
|
m_regen = true;
|
||||||
|
m_start = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 end
|
||||||
|
{
|
||||||
|
get { return m_end; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != m_end)
|
||||||
|
m_regen = true;
|
||||||
|
m_end = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public float slack
|
||||||
|
{
|
||||||
|
get { return m_slack; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != m_slack)
|
||||||
|
m_regen = true;
|
||||||
|
m_slack = Mathf.Max(0.0f, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int steps
|
||||||
|
{
|
||||||
|
get { return m_steps; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != m_steps)
|
||||||
|
m_regen = true;
|
||||||
|
m_steps = Mathf.Max(2, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 midPoint
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Vector2 mid = Vector2.zero;
|
||||||
|
if (m_steps == 2)
|
||||||
|
{
|
||||||
|
return (points[0] + points[1]) * 0.5f;
|
||||||
|
}
|
||||||
|
else if (m_steps > 2)
|
||||||
|
{
|
||||||
|
int m = m_steps / 2;
|
||||||
|
if ((m_steps % 2) == 0)
|
||||||
|
{
|
||||||
|
mid = (points[m] + points[m + 1]) * 0.5f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mid = points[m];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CableCurve()
|
||||||
|
{
|
||||||
|
points = emptyCurve;
|
||||||
|
m_start = Vector2.up;
|
||||||
|
m_end = Vector2.up + Vector2.right;
|
||||||
|
m_slack = 0.5f;
|
||||||
|
m_steps = 20;
|
||||||
|
m_regen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CableCurve(Vector2[] inputPoints)
|
||||||
|
{
|
||||||
|
points = inputPoints;
|
||||||
|
m_start = inputPoints[0];
|
||||||
|
m_end = inputPoints[1];
|
||||||
|
m_slack = 0.5f;
|
||||||
|
m_steps = 20;
|
||||||
|
m_regen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CableCurve(CableCurve v)
|
||||||
|
{
|
||||||
|
points = v.Points();
|
||||||
|
m_start = v.start;
|
||||||
|
m_end = v.end;
|
||||||
|
m_slack = v.slack;
|
||||||
|
m_steps = v.steps;
|
||||||
|
m_regen = v.regenPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2[] Points()
|
||||||
|
{
|
||||||
|
if (!m_regen)
|
||||||
|
return points;
|
||||||
|
|
||||||
|
if (m_steps < 2)
|
||||||
|
return emptyCurve;
|
||||||
|
|
||||||
|
float lineDist = Vector2.Distance(m_end, m_start);
|
||||||
|
float lineDistH = Vector2.Distance(new Vector2(m_end.x, m_start.y), m_start);
|
||||||
|
float l = lineDist + Mathf.Max(0.0001f, m_slack);
|
||||||
|
float r = 0.0f;
|
||||||
|
float s = m_start.y;
|
||||||
|
float u = lineDistH;
|
||||||
|
float v = end.y;
|
||||||
|
|
||||||
|
if ((u - r) == 0.0f)
|
||||||
|
return emptyCurve;
|
||||||
|
|
||||||
|
float ztarget = Mathf.Sqrt(Mathf.Pow(l, 2.0f) - Mathf.Pow(v - s, 2.0f)) / (u - r);
|
||||||
|
|
||||||
|
int loops = 30;
|
||||||
|
int iterationCount = 0;
|
||||||
|
int maxIterations = loops * 10; // For safety.
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
float z = 0.0f;
|
||||||
|
float ztest = 0.0f;
|
||||||
|
float zstep = 100.0f;
|
||||||
|
float ztesttarget = 0.0f;
|
||||||
|
for (int i = 0; i < loops; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
iterationCount++;
|
||||||
|
ztest = z + zstep;
|
||||||
|
ztesttarget = (float)Math.Sinh(ztest) / ztest;
|
||||||
|
|
||||||
|
if (float.IsInfinity(ztesttarget))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ztesttarget == ztarget)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
z = ztest;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (ztesttarget > ztarget)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
z = ztest;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iterationCount > maxIterations)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
|
||||||
|
zstep *= 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float a = (u - r) / 2.0f / z;
|
||||||
|
float p = (r + u - a * Mathf.Log((l + v - s) / (l - v + s))) / 2.0f;
|
||||||
|
float q = (v + s - l * (float)Math.Cosh(z) / (float)Math.Sinh(z)) / 2.0f;
|
||||||
|
|
||||||
|
points = new Vector2[m_steps];
|
||||||
|
float stepsf = m_steps - 1;
|
||||||
|
float stepf;
|
||||||
|
for (int i = 0; i < m_steps; i++)
|
||||||
|
{
|
||||||
|
stepf = i / stepsf;
|
||||||
|
Vector2 pos = Vector2.zero;
|
||||||
|
pos.x = Mathf.Lerp(start.x, end.x, stepf);
|
||||||
|
pos.y = a * (float)Math.Cosh(((stepf * lineDistH) - p) / a) + q;
|
||||||
|
points[i] = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_regen = false;
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2444f085ab49ff24b888b175f46b55c7
|
||||||
|
timeCreated: 1501871616
|
||||||
|
licenseType: Free
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue