using UnityEngine; using UnityEngine.Serialization; using System; namespace Dreamteck.Splines{ [System.Serializable] //A control point used by the SplineClass public struct SplinePoint { public enum Type {SmoothMirrored, Broken, SmoothFree}; public Type type { get { return _type; } set { isDirty = _type != value; _type = value; if (value == Type.SmoothMirrored) { SmoothMirrorTangent2(); } } } /// /// Getting the value of isDirty will set the point not dirty /// [NonSerialized] public bool isDirty; [FormerlySerializedAs("type")] [SerializeField] [HideInInspector] private Type _type; [HideInInspector] [FormerlySerializedAs("_position")] public Vector3 position; [HideInInspector] [FormerlySerializedAs("_color")] public Color color; [HideInInspector] [FormerlySerializedAs("_normal")] public Vector3 normal; [HideInInspector] [FormerlySerializedAs("_size")] public float size; [HideInInspector] [FormerlySerializedAs("_tangent")] public Vector3 tangent; [HideInInspector] [FormerlySerializedAs("_tangent2")] public Vector3 tangent2; public static SplinePoint Lerp(SplinePoint a, SplinePoint b, float t) { SplinePoint result = a; if (a.type == Type.Broken || b.type == Type.Broken) result.type = Type.Broken; else if (a.type == Type.SmoothFree || b.type == Type.SmoothFree) result.type = Type.SmoothFree; else result.type = Type.SmoothMirrored; result.position = Vector3.Lerp(a.position, b.position, t); GetInterpolatedTangents(a, b, t, ref result); result.color = Color.Lerp(a.color, b.color, t); result.size = Mathf.Lerp(a.size, b.size, t); result.normal = Vector3.Slerp(a.normal, b.normal, t); return result; } private static void GetInterpolatedTangents(SplinePoint a, SplinePoint b, float t, ref SplinePoint target) { Vector3 P0_1 = (1f - t) * a.position + t * a.tangent2; Vector3 P1_2 = (1f - t) * a.tangent2 + t * b.tangent; Vector3 P2_3 = (1f - t) * b.tangent + t * b.position; Vector3 P01_12 = (1 - t) * P0_1 + t * P1_2; Vector3 P12_23 = (1 - t) * P1_2 + t * P2_3; target.tangent = P01_12; target.tangent2 = P12_23; } public override bool Equals(object obj) { if(obj is SplinePoint) { return EqualsFast((SplinePoint)obj); } return false; } private bool EqualsFast(SplinePoint obj) { SplinePoint other = (SplinePoint)obj; if (position != other.position) return false; if (tangent != other.tangent) return false; if (tangent2 != other.tangent2) return false; if (normal != other.normal) return false; if (_type != other._type) return false; if (size != other.size) return false; if (color != other.color) return false; return true; } public static bool operator == (SplinePoint p1, SplinePoint p2) { return p1.EqualsFast(p2); } public static bool operator != (SplinePoint p1, SplinePoint p2) { return !p1.EqualsFast(p2); } public void SetPosition(Vector3 pos) { tangent -= position - pos; tangent2 -= position - pos; position = pos; } public void SetTangentPosition(Vector3 pos) { tangent = pos; switch (_type) { case Type.SmoothMirrored: SmoothMirrorTangent2(); break; case Type.SmoothFree: SmoothFreeTangent2(); break; } } public void SetTangent2Position(Vector3 pos) { tangent2 = pos; switch (_type) { case Type.SmoothMirrored: SmoothMirrorTangent(); break; case Type.SmoothFree: SmoothFreeTangent(); break; } } public SplinePoint(Vector3 p) { position = p; tangent = p; tangent2 = p; color = Color.white; normal = Vector3.up; size = 1f; _type = Type.SmoothMirrored; isDirty = false; SmoothMirrorTangent2(); } public SplinePoint(Vector3 p, Vector3 t){ position = p; tangent = t; tangent2 = p + (p - t); color = Color.white; normal = Vector3.up; size = 1f; _type = Type.SmoothMirrored; isDirty = false; SmoothMirrorTangent2(); } public SplinePoint(Vector3 pos, Vector3 tan, Vector3 nor, float s, Color col){ position = pos; tangent = tan; tangent2 = pos + (pos - tan); normal = nor; size = s; color = col; _type = Type.SmoothMirrored; isDirty = false; SmoothMirrorTangent2(); } public SplinePoint(Vector3 pos, Vector3 tan, Vector3 tan2, Vector3 nor, float s, Color col) { position = pos; tangent = tan; tangent2 = tan2; normal = nor; size = s; color = col; _type = Type.Broken; isDirty = false; switch (_type) { case Type.SmoothMirrored: SmoothMirrorTangent2(); break; case Type.SmoothFree: SmoothFreeTangent2(); break; } } public SplinePoint(SplinePoint source) { position = source.position; tangent = source.tangent; tangent2 = source.tangent2; color = source.color; normal = source.normal; size = source.size; _type = source.type; isDirty = false; switch (_type) { case Type.SmoothMirrored: SmoothMirrorTangent2(); break; case Type.SmoothFree: SmoothFreeTangent2(); break; } } public void Flatten(LinearAlgebraUtility.Axis axis, float flatValue = 0f) { position = LinearAlgebraUtility.FlattenVector(position, axis, flatValue); tangent = LinearAlgebraUtility.FlattenVector(tangent, axis, flatValue); tangent2 = LinearAlgebraUtility.FlattenVector(tangent2, axis, flatValue); switch (axis) { case LinearAlgebraUtility.Axis.X: normal = Vector3.right; break; case LinearAlgebraUtility.Axis.Y: normal = Vector3.up; break; case LinearAlgebraUtility.Axis.Z: normal = Vector3.forward; break; } } public void SetPositionX(float value) { if(position.x != value) { isDirty = true; } position.x = value; } public void SetPositionY(float value) { if(position.y != value) { isDirty = true; } position.y = value; } public void SetPositionZ(float value) { if(position.z != value) { isDirty = true; } position.z = value; } public void SetTangentX(float value) { if(tangent.x != value) { isDirty = true; } tangent.x = value; } public void SetTangentY(float value) { if (tangent.y != value) { isDirty = true; } tangent.y = value; } public void SetTangentZ(float value) { if(tangent.z != value) { isDirty = true; } tangent.z = value; } public void SetTangent2X(float value) { if (tangent2.x != value) { isDirty = true; } tangent2.x = value; } public void SetTangent2Y(float value) { if (tangent2.y != value) { isDirty = true; } tangent2.y = value; } public void SetTangent2Z(float value) { if (tangent2.z != value) { isDirty = true; } tangent2.z = value; } public void SetNormalX(float value) { if (normal.x != value) { isDirty = true; } normal.x = value; } public void SetNormalY(float value) { if (normal.y != value) { isDirty = true; } normal.y = value; } public void SetNormalZ(float value) { if(normal.z != value) { isDirty = true; } normal.z = value; } public void SetColorR(float value) { if (color.r != value) { isDirty = true; } color.r = value; } public void SetColorG(float value) { if (color.g != value) { isDirty = true; } color.g = value; } public void SetColorB(float value) { if(color.b != value) { isDirty = true; } color.b = value; } public void SetColorA(float value) { if (color.a != value) { isDirty = true; } color.a = value; } private void SmoothMirrorTangent2() { tangent2 = position + (position - tangent); isDirty = true; } private void SmoothMirrorTangent() { tangent = position + (position - tangent2); isDirty = true; } private void SmoothFreeTangent2() { tangent2 = position + (position - tangent).normalized * (tangent2 - position).magnitude; isDirty = true; } private void SmoothFreeTangent() { tangent = position + (position - tangent2).normalized * (tangent - position).magnitude; isDirty = true; } public override int GetHashCode() { unchecked { int hash = 17; hash *= hash * 23 + _type.GetHashCode(); hash = hash * 23 + position.GetHashCode(); hash = hash * 23 + normal.GetHashCode(); hash = hash * 23 + tangent.GetHashCode(); hash = hash * 23 + tangent2.GetHashCode(); hash = hash * 23 + color.GetHashCode(); hash = hash * 23 + size.GetHashCode(); return hash; } } } }