mirror of
https://github.com/RHeavenStudioPlus/HeavenStudioPlus.git
synced 2024-12-04 23:37:27 +00:00
206 lines
5.2 KiB
C#
206 lines
5.2 KiB
C#
|
using UnityEngine;
|
|||
|
|
|||
|
namespace BezierSolution
|
|||
|
{
|
|||
|
[AddComponentMenu( "Bezier Solution/Bezier Line Renderer" )]
|
|||
|
[HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )]
|
|||
|
[RequireComponent( typeof( LineRenderer ) )]
|
|||
|
[ExecuteInEditMode]
|
|||
|
public class BezierLineRenderer : MonoBehaviour
|
|||
|
{
|
|||
|
#pragma warning disable 0649
|
|||
|
[SerializeField]
|
|||
|
private BezierSpline m_spline;
|
|||
|
public BezierSpline spline
|
|||
|
{
|
|||
|
get { return m_spline; }
|
|||
|
set
|
|||
|
{
|
|||
|
if( m_spline != value )
|
|||
|
{
|
|||
|
if( m_spline )
|
|||
|
m_spline.onSplineChanged -= OnSplineChanged;
|
|||
|
|
|||
|
m_spline = value;
|
|||
|
|
|||
|
if( m_spline && isActiveAndEnabled )
|
|||
|
{
|
|||
|
m_spline.onSplineChanged -= OnSplineChanged;
|
|||
|
m_spline.onSplineChanged += OnSplineChanged;
|
|||
|
|
|||
|
OnSplineChanged( m_spline, DirtyFlags.All );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[SerializeField]
|
|||
|
[MinMaxRange( 0f, 1f )]
|
|||
|
private Vector2 m_splineSampleRange = new Vector2( 0f, 1f );
|
|||
|
public Vector2 SplineSampleRange
|
|||
|
{
|
|||
|
get { return m_splineSampleRange; }
|
|||
|
set
|
|||
|
{
|
|||
|
value.x = Mathf.Clamp01( value.x );
|
|||
|
value.y = Mathf.Clamp01( value.y );
|
|||
|
|
|||
|
if( m_splineSampleRange != value )
|
|||
|
{
|
|||
|
m_splineSampleRange = value;
|
|||
|
|
|||
|
if( isActiveAndEnabled )
|
|||
|
OnSplineChanged( m_spline, DirtyFlags.All );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[Header( "Line Options" )]
|
|||
|
[SerializeField]
|
|||
|
[Range( 0, 30 )]
|
|||
|
private int m_smoothness = 5;
|
|||
|
public int smoothness
|
|||
|
{
|
|||
|
get { return m_smoothness; }
|
|||
|
set
|
|||
|
{
|
|||
|
if( m_smoothness != value )
|
|||
|
{
|
|||
|
m_smoothness = value;
|
|||
|
|
|||
|
if( isActiveAndEnabled )
|
|||
|
OnSplineChanged( m_spline, DirtyFlags.All );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if UNITY_EDITOR
|
|||
|
[Header( "Other Settings" )]
|
|||
|
[SerializeField]
|
|||
|
private bool executeInEditMode = false;
|
|||
|
|
|||
|
[SerializeField, HideInInspector]
|
|||
|
private BezierSpline prevSpline;
|
|||
|
#endif
|
|||
|
#pragma warning restore 0649
|
|||
|
|
|||
|
private LineRenderer lineRenderer;
|
|||
|
private Vector3[] lineRendererPoints;
|
|||
|
#if UNITY_EDITOR
|
|||
|
private bool lineRendererUseWorldSpace = true;
|
|||
|
#endif
|
|||
|
|
|||
|
private void OnEnable()
|
|||
|
{
|
|||
|
if( m_spline )
|
|||
|
{
|
|||
|
m_spline.onSplineChanged -= OnSplineChanged;
|
|||
|
m_spline.onSplineChanged += OnSplineChanged;
|
|||
|
|
|||
|
OnSplineChanged( m_spline, DirtyFlags.All );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void OnDisable()
|
|||
|
{
|
|||
|
if( m_spline )
|
|||
|
m_spline.onSplineChanged -= OnSplineChanged;
|
|||
|
}
|
|||
|
|
|||
|
#if UNITY_EDITOR
|
|||
|
private void Update()
|
|||
|
{
|
|||
|
if( lineRenderer && lineRenderer.useWorldSpace != lineRendererUseWorldSpace )
|
|||
|
{
|
|||
|
lineRendererUseWorldSpace = !lineRendererUseWorldSpace;
|
|||
|
|
|||
|
if( isActiveAndEnabled )
|
|||
|
OnSplineChanged( m_spline, DirtyFlags.All );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void OnValidate()
|
|||
|
{
|
|||
|
BezierSpline _spline = m_spline;
|
|||
|
m_spline = prevSpline;
|
|||
|
spline = prevSpline = _spline;
|
|||
|
|
|||
|
if( isActiveAndEnabled )
|
|||
|
OnSplineChanged( m_spline, DirtyFlags.All );
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
private void OnSplineChanged( BezierSpline spline, DirtyFlags dirtyFlags )
|
|||
|
{
|
|||
|
#if UNITY_EDITOR
|
|||
|
if( !executeInEditMode && !UnityEditor.EditorApplication.isPlaying )
|
|||
|
return;
|
|||
|
#endif
|
|||
|
|
|||
|
if( ( dirtyFlags & DirtyFlags.SplineShapeChanged ) == DirtyFlags.SplineShapeChanged )
|
|||
|
Refresh( m_smoothness );
|
|||
|
}
|
|||
|
|
|||
|
public void Refresh( int smoothness )
|
|||
|
{
|
|||
|
if( !m_spline || m_spline.Count < 2 )
|
|||
|
return;
|
|||
|
|
|||
|
if( !lineRenderer )
|
|||
|
lineRenderer = GetComponent<LineRenderer>();
|
|||
|
|
|||
|
smoothness = Mathf.Clamp( smoothness, 1, 30 );
|
|||
|
|
|||
|
int numberOfPoints = ( m_spline.Count - 1 ) * smoothness;
|
|||
|
if( !m_spline.loop )
|
|||
|
numberOfPoints++; // spline.GetPoint( 1f )
|
|||
|
else
|
|||
|
numberOfPoints += smoothness; // Final point is connected to the first point via lineRenderer.loop, so no "numberOfPoints++" here
|
|||
|
|
|||
|
if( lineRendererPoints == null || lineRendererPoints.Length != numberOfPoints )
|
|||
|
lineRendererPoints = new Vector3[numberOfPoints];
|
|||
|
|
|||
|
if( m_splineSampleRange.x <= 0f && m_splineSampleRange.y >= 1f )
|
|||
|
{
|
|||
|
int pointIndex = 0;
|
|||
|
float smoothnessStep = 1f / smoothness;
|
|||
|
for( int i = 0; i < m_spline.Count - 1; i++ )
|
|||
|
{
|
|||
|
BezierSpline.Segment segment = new BezierSpline.Segment( m_spline[i], m_spline[i + 1], 0f );
|
|||
|
for( int j = 0; j < smoothness; j++, pointIndex++ )
|
|||
|
lineRendererPoints[pointIndex] = segment.GetPoint( j * smoothnessStep );
|
|||
|
}
|
|||
|
|
|||
|
if( !m_spline.loop )
|
|||
|
lineRendererPoints[numberOfPoints - 1] = m_spline.GetPoint( 1f );
|
|||
|
else
|
|||
|
{
|
|||
|
BezierSpline.Segment segment = new BezierSpline.Segment( m_spline[m_spline.Count - 1], m_spline[0], 0f );
|
|||
|
for( int j = 0; j < smoothness; j++, pointIndex++ )
|
|||
|
lineRendererPoints[pointIndex] = segment.GetPoint( j * smoothnessStep );
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
float smoothnessStep = ( m_splineSampleRange.y - m_splineSampleRange.x ) / ( numberOfPoints - 1 );
|
|||
|
for( int i = 0; i < numberOfPoints; i++ )
|
|||
|
lineRendererPoints[i] = spline.GetPoint( m_splineSampleRange.x + i * smoothnessStep );
|
|||
|
}
|
|||
|
|
|||
|
#if UNITY_EDITOR
|
|||
|
lineRendererUseWorldSpace = lineRenderer.useWorldSpace;
|
|||
|
#endif
|
|||
|
if( !lineRenderer.useWorldSpace )
|
|||
|
{
|
|||
|
Vector3 initialPoint = m_spline.GetPoint( 0f );
|
|||
|
for( int i = 0; i < numberOfPoints; i++ )
|
|||
|
lineRendererPoints[i] -= initialPoint;
|
|||
|
}
|
|||
|
|
|||
|
lineRenderer.positionCount = lineRendererPoints.Length;
|
|||
|
lineRenderer.SetPositions( lineRendererPoints );
|
|||
|
lineRenderer.loop = m_spline.loop && m_splineSampleRange.x <= 0f && m_splineSampleRange.y >= 1f;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|