Added a new Line Renderer mode (Catenary)

pull/413/head
Simon Jackson 2017-08-04 20:01:02 +01:00
parent a1b2b38a0f
commit 11ee80411f
4 changed files with 254 additions and 10 deletions

View File

@ -133,7 +133,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
m_IsActive: 1
--- !u!114 &114012036402784198
MonoBehaviour:
m_ObjectHideFlags: 1

View File

@ -30,6 +30,7 @@ namespace UnityEngine.UI.Extensions
Quick,
Basic,
Improved,
Catenary,
}
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[] startUvs, middleUvs, endUvs, fullUvs;
[SerializeField]
[SerializeField, Tooltip("Points to draw lines between\n Can be improved using the Resolution Option")]
internal Vector2[] m_points;
[SerializeField]
[SerializeField, Tooltip("Thickness of the line")]
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;
[SerializeField]
[SerializeField, Tooltip("Do the points identify a single line or split pairs of lines")]
internal bool lineList;
[SerializeField]
[SerializeField, Tooltip("Add end caps to each line\nMultiple caps when used with Line List")]
internal bool lineCaps;
[SerializeField]
[SerializeField, Tooltip("Resolution of the Bezier curve, different to line Resolution")]
internal int bezierSegmentsPerCurve = 10;
public float LineThickness
@ -80,8 +81,10 @@ namespace UnityEngine.UI.Extensions
set { lineCaps = value; SetAllDirty(); }
}
[Tooltip("The type of Join used between lines, Square/Mitre or Curved/Bevel")]
public JoinType LineJoins = JoinType.Bevel;
[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
@ -120,7 +123,7 @@ namespace UnityEngine.UI.Extensions
GeneratedUVs();
Vector2[] pointsToDraw = m_points;
//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();
@ -142,6 +145,13 @@ namespace UnityEngine.UI.Extensions
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)
{

View File

@ -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;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2444f085ab49ff24b888b175f46b55c7
timeCreated: 1501871616
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: