using System.Collections.Generic;
using Unity.Mathematics;
namespace UnityEngine.Splines
{
///
/// A Component that holds a object.
///
#if UNITY_2021_2_OR_NEWER
[Icon(k_IconPath)]
#endif
[AddComponentMenu("Splines/Spline")]
public sealed class SplineContainer : MonoBehaviour, ISplineProvider
{
const string k_IconPath = "Packages/com.unity.splines/Editor/Resources/Icons/SplineComponent.png";
readonly Spline[] m_SplineArray = new Spline[1];
[SerializeField]
Spline m_Spline = new Spline();
IEnumerable ISplineProvider.Splines
{
get
{
m_SplineArray[0] = Spline;
return m_SplineArray;
}
}
bool IsScaled => transform.lossyScale != Vector3.one;
///
/// The instantiated object attached to this component.
///
public Spline Spline
{
get => m_Spline;
set => m_Spline = value;
}
///
/// Compute interpolated position, direction and upDirection at ratio t. Calling this method to get the
/// 3 vectors is faster than calling independently EvaluateSplinePosition, EvaluateSplineTangent and EvaluateSplineUpVector
/// for the same time t as it reduces some redundant computation.
///
/// A value between 0 and 1 representing the ratio along the curve.
/// Output variable for the float3 position at t.
/// Output variable for the float3 tangent at t.
/// Output variable for the float3 up direction at t.
/// Boolean value, true if a valid set of output variables as been computed.
public bool Evaluate(float t, out float3 position, out float3 tangent, out float3 upVector)
{
if (Spline == null)
{
position = float3.zero;
tangent = new float3(0, 0, 1);
upVector = new float3(0, 1, 0);
return false;
}
if (IsScaled)
{
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
return SplineUtility.Evaluate(nativeSpline, t, out position, out tangent, out upVector);
}
var evaluationStatus = SplineUtility.Evaluate(Spline, t, out position, out tangent, out upVector);
if (evaluationStatus)
{
position = transform.TransformPoint(position);
tangent = transform.TransformVector(tangent);
upVector = transform.TransformDirection(upVector);
}
return evaluationStatus;
}
///
/// Evaluate a tangent vector on a curve at a specific t in world space.
///
/// A value between 0 and 1 representing a percentage of the curve.
/// A tangent vector.
public float3 EvaluatePosition(float t)
{
if(Spline == null)
return float.PositiveInfinity;
if(IsScaled)
{
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
return SplineUtility.EvaluatePosition(nativeSpline, t);
}
return transform.TransformPoint(SplineUtility.EvaluatePosition(Spline, t));
}
///
/// Evaluate a tangent vector at a specific t in world space.
///
/// A value between 0 and 1 representing a percentage of entire spline
/// A tangent vector
public float3 EvaluateTangent(float t)
{
if (Spline == null)
return 0;
if(IsScaled)
{
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
return SplineUtility.EvaluateTangent(nativeSpline, t);
}
return transform.TransformVector(SplineUtility.EvaluateTangent(Spline, t));
}
///
/// Evaluate an up vector direction at a specific t
///
/// A value between 0 and 1 representing a percentage of entire spline
/// An up direction.
public float3 EvaluateUpVector(float t)
{
if (Spline == null)
return float.PositiveInfinity;
if(IsScaled)
{
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
return SplineUtility.EvaluateUpVector(nativeSpline, t);
}
//Using TransformDirection as up direction is Not sensible to scale
return transform.TransformDirection(SplineUtility.EvaluateUpVector(Spline, t));
}
///
/// Evaluate an acceleration vector at a specific t
///
/// A value between 0 and 1 representing a percentage of entire spline
/// An acceleration vector.
public float3 EvaluateAcceleration(float t)
{
if (Spline == null)
return float.PositiveInfinity;
if(IsScaled)
{
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
return SplineUtility.EvaluateAcceleration(nativeSpline, t);
}
return transform.TransformVector(SplineUtility.EvaluateAcceleration(Spline, t));
}
///
/// Calculate the length of in world space.
///
/// The length of in world space
public float CalculateLength()
{
if(Spline == null)
return 0;
return SplineUtility.CalculateLength(Spline, transform.localToWorldMatrix);
}
}
}