using UnityEngine;
using System.Collections.Generic;
namespace MoreMountains.Tools
{
///
/// Add this class to a line renderer and it'll add control points that let you turn your line into a bezier curve
///
[ExecuteAlways]
[RequireComponent(typeof(LineRenderer))]
[AddComponentMenu("More Mountains/Tools/Sprites/MMBezierLineRenderer")]
public class MMBezierLineRenderer : MonoBehaviour
{
/// a list of handles to control your line. Usually 4, but you can have more.
public Transform[] AdjustmentHandles;
/// the amount of segments of the line renderer (more segments, less visible straight lines)
public int NumberOfSegments = 50;
/// the sorting layer for this line renderer
public string SortingLayerName = "Default";
/// the amount of curves we're working with
[MMReadOnly]
public int NumberOfCurves = 0;
protected int _sortingLayerID;
protected LineRenderer _lineRenderer;
protected Vector3 _point;
protected Vector3 _p;
protected bool _initialized = false;
///
/// On Awake we initialize our line renderer
///
protected virtual void Awake()
{
Initialization();
}
///
/// Grabs the sorting layer, computes the amount of curves
///
protected virtual void Initialization()
{
if (_initialized)
{
return;
}
_sortingLayerID = SortingLayer.NameToID(SortingLayerName);
NumberOfCurves = (int)AdjustmentHandles.Length / 3;
_lineRenderer = GetComponent();
if (_lineRenderer != null)
{
_lineRenderer.sortingLayerID = _sortingLayerID;
}
_initialized = true;
}
///
/// On Update we draw our curve
///
protected virtual void LateUpdate()
{
DrawCurve();
}
///
/// For each point, determines the bezier position and feeds it to the line renderer
///
protected virtual void DrawCurve()
{
for (int i = 0; i < NumberOfCurves; i++)
{
for (int j = 1; j <= NumberOfSegments; j++)
{
float t = (j - 1) / (float)(NumberOfSegments - 1);
int pointIndex = i * 3;
_point = BezierPoint(t, AdjustmentHandles[pointIndex].position, AdjustmentHandles[pointIndex + 1].position, AdjustmentHandles[pointIndex + 2].position, AdjustmentHandles[pointIndex + 3].position);
_lineRenderer.positionCount = (i * NumberOfSegments) + j;
_lineRenderer.SetPosition((i * NumberOfSegments) + (j - 1), _point);
}
}
}
///
/// Computes the coordinates of a point on the bezier curve controlled by p0, p1, p2 and p3
///
///
///
///
///
///
///
protected virtual Vector3 BezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
_p = uuu * p0;
_p += 3 * uu * t * p1;
_p += 3 * u * tt * p2;
_p += ttt * p3;
return _p;
}
}
}