Spline.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. using System;
  2. using System.Collections.Generic;
  3. namespace UnityEngine.U2D
  4. {
  5. // Spline Internal Meta Data.
  6. internal struct SplinePointMetaData
  7. {
  8. public float height;
  9. public uint spriteIndex;
  10. public int cornerMode;
  11. };
  12. [Serializable]
  13. public class Spline
  14. {
  15. private static readonly string KErrorMessage = "Internal error: Point too close to neighbor";
  16. private static readonly float KEpsilon = 0.01f;
  17. [SerializeField]
  18. private bool m_IsOpenEnded;
  19. [SerializeField]
  20. private List<SplineControlPoint> m_ControlPoints = new List<SplineControlPoint>();
  21. public bool isOpenEnded
  22. {
  23. get
  24. {
  25. if (GetPointCount() < 3)
  26. return true;
  27. return m_IsOpenEnded;
  28. }
  29. set { m_IsOpenEnded = value; }
  30. }
  31. private bool IsPositionValid(int index, int next, Vector3 point)
  32. {
  33. int prev = (index == 0) ? (m_ControlPoints.Count - 1) : (index - 1);
  34. next = (next >= m_ControlPoints.Count) ? 0 : next;
  35. if (prev >= 0)
  36. {
  37. Vector3 diff = m_ControlPoints[prev].position - point;
  38. if (diff.magnitude < KEpsilon)
  39. return false;
  40. }
  41. if (next < m_ControlPoints.Count)
  42. {
  43. Vector3 diff = m_ControlPoints[next].position - point;
  44. if (diff.magnitude < KEpsilon)
  45. return false;
  46. }
  47. return true;
  48. }
  49. public void Clear()
  50. {
  51. m_ControlPoints.Clear();
  52. }
  53. public int GetPointCount()
  54. {
  55. return m_ControlPoints.Count;
  56. }
  57. public void InsertPointAt(int index, Vector3 point)
  58. {
  59. if (!IsPositionValid(index, index, point))
  60. throw new ArgumentException(KErrorMessage);
  61. m_ControlPoints.Insert(index, new SplineControlPoint { position = point, height = 1.0f, cornerMode = Corner.Automatic });
  62. }
  63. public void RemovePointAt(int index)
  64. {
  65. if (m_ControlPoints.Count > 2)
  66. m_ControlPoints.RemoveAt(index);
  67. }
  68. public Vector3 GetPosition(int index)
  69. {
  70. return m_ControlPoints[index].position;
  71. }
  72. public void SetPosition(int index, Vector3 point)
  73. {
  74. if (!IsPositionValid(index, index + 1, point))
  75. throw new ArgumentException(KErrorMessage);
  76. SplineControlPoint newPoint = m_ControlPoints[index];
  77. newPoint.position = point;
  78. m_ControlPoints[index] = newPoint;
  79. }
  80. public Vector3 GetLeftTangent(int index)
  81. {
  82. ShapeTangentMode mode = GetTangentMode(index);
  83. if (mode == ShapeTangentMode.Linear)
  84. return Vector3.zero;
  85. return m_ControlPoints[index].leftTangent;
  86. }
  87. public void SetLeftTangent(int index, Vector3 tangent)
  88. {
  89. ShapeTangentMode mode = GetTangentMode(index);
  90. if (mode == ShapeTangentMode.Linear)
  91. return;
  92. SplineControlPoint newPoint = m_ControlPoints[index];
  93. newPoint.leftTangent = tangent;
  94. m_ControlPoints[index] = newPoint;
  95. }
  96. public Vector3 GetRightTangent(int index)
  97. {
  98. ShapeTangentMode mode = GetTangentMode(index);
  99. if (mode == ShapeTangentMode.Linear)
  100. return Vector3.zero;
  101. return m_ControlPoints[index].rightTangent;
  102. }
  103. public void SetRightTangent(int index, Vector3 tangent)
  104. {
  105. ShapeTangentMode mode = GetTangentMode(index);
  106. if (mode == ShapeTangentMode.Linear)
  107. return;
  108. SplineControlPoint newPoint = m_ControlPoints[index];
  109. newPoint.rightTangent = tangent;
  110. m_ControlPoints[index] = newPoint;
  111. }
  112. public ShapeTangentMode GetTangentMode(int index)
  113. {
  114. return m_ControlPoints[index].mode;
  115. }
  116. public void SetTangentMode(int index, ShapeTangentMode mode)
  117. {
  118. SplineControlPoint newPoint = m_ControlPoints[index];
  119. newPoint.mode = mode;
  120. m_ControlPoints[index] = newPoint;
  121. }
  122. public float GetHeight(int index)
  123. {
  124. return m_ControlPoints[index].height;
  125. }
  126. public void SetHeight(int index, float value)
  127. {
  128. m_ControlPoints[index].height = value;
  129. }
  130. public int GetSpriteIndex(int index)
  131. {
  132. return m_ControlPoints[index].spriteIndex;
  133. }
  134. public void SetSpriteIndex(int index, int value)
  135. {
  136. m_ControlPoints[index].spriteIndex = value;
  137. }
  138. public bool GetCorner(int index)
  139. {
  140. return GetCornerMode(index) != Corner.Disable;
  141. }
  142. public void SetCorner(int index, bool value)
  143. {
  144. m_ControlPoints[index].corner = value;
  145. m_ControlPoints[index].cornerMode = value ? Corner.Automatic : Corner.Disable;
  146. }
  147. public override int GetHashCode()
  148. {
  149. unchecked
  150. {
  151. int hashCode = (int)2166136261;
  152. for (int i = 0; i < GetPointCount(); ++i)
  153. {
  154. hashCode = hashCode * 16777619 ^ m_ControlPoints[i].GetHashCode();
  155. }
  156. hashCode = hashCode * 16777619 ^ m_IsOpenEnded.GetHashCode();
  157. return hashCode;
  158. }
  159. }
  160. internal void SetCornerMode(int index, Corner value)
  161. {
  162. m_ControlPoints[index].corner = (value != Corner.Disable);
  163. m_ControlPoints[index].cornerMode = value;
  164. }
  165. internal Corner GetCornerMode(int index)
  166. {
  167. if (m_ControlPoints[index].cornerMode == Corner.Disable)
  168. {
  169. // For backward compatibility.
  170. if (m_ControlPoints[index].corner)
  171. {
  172. m_ControlPoints[index].cornerMode = Corner.Automatic;
  173. return Corner.Automatic;
  174. }
  175. }
  176. return m_ControlPoints[index].cornerMode;
  177. }
  178. }
  179. }