Açıklama Yok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Spline.cs 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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. /// <summary>
  13. /// Spline contains control points used to define curve/outline for generating SpriteShape geometry.
  14. /// </summary>
  15. [Serializable]
  16. public class Spline
  17. {
  18. private static readonly string KErrorMessage = "Internal error: Point too close to neighbor";
  19. private static readonly float KEpsilon = 0.01f;
  20. [SerializeField]
  21. private bool m_IsOpenEnded;
  22. [SerializeField]
  23. private List<SplineControlPoint> m_ControlPoints = new List<SplineControlPoint>();
  24. /// <summary>
  25. /// Get/Set Spline's shape to open ended or closed.
  26. /// </summary>
  27. public bool isOpenEnded
  28. {
  29. get
  30. {
  31. if (GetPointCount() < 3)
  32. return true;
  33. return m_IsOpenEnded;
  34. }
  35. set { m_IsOpenEnded = value; }
  36. }
  37. private bool IsPositionValid(int index, int next, Vector3 point)
  38. {
  39. int pointCount = GetPointCount();
  40. if (isOpenEnded && (index == 0 || index == pointCount))
  41. return true;
  42. int prev = (index == 0) ? (pointCount - 1) : (index - 1);
  43. if (prev >= 0)
  44. {
  45. Vector3 diff = m_ControlPoints[prev].position - point;
  46. if (diff.magnitude < KEpsilon)
  47. return false;
  48. }
  49. next = (next >= pointCount) ? 0 : next;
  50. if (next < pointCount)
  51. {
  52. Vector3 diff = m_ControlPoints[next].position - point;
  53. if (diff.magnitude < KEpsilon)
  54. return false;
  55. }
  56. return true;
  57. }
  58. /// <summary>
  59. /// Clear all control points.
  60. /// </summary>
  61. public void Clear()
  62. {
  63. m_ControlPoints.Clear();
  64. }
  65. /// <summary>
  66. /// Get Spline's control point count.
  67. /// </summary>
  68. /// <returns>Count of control points.</returns>
  69. public int GetPointCount()
  70. {
  71. return m_ControlPoints.Count;
  72. }
  73. /// <summary>
  74. /// Insert control point at index.
  75. /// </summary>
  76. /// <param name="index">Index at which a control point will be inserted.</param>
  77. /// <param name="point">Position of the control point.</param>
  78. /// <exception cref="ArgumentException"></exception>
  79. public void InsertPointAt(int index, Vector3 point)
  80. {
  81. if (!IsPositionValid(index, index, point))
  82. throw new ArgumentException(KErrorMessage);
  83. m_ControlPoints.Insert(index, new SplineControlPoint { position = point, height = 1.0f, cornerMode = Corner.Automatic });
  84. }
  85. /// <summary>
  86. /// Remove a control point from the Spline at index.
  87. /// </summary>
  88. /// <param name="index">Index of the control point to be removed.</param>
  89. public void RemovePointAt(int index)
  90. {
  91. if (m_ControlPoints.Count > 2)
  92. m_ControlPoints.RemoveAt(index);
  93. }
  94. /// <summary>
  95. /// Get position of control point at index.
  96. /// </summary>
  97. /// <param name="index">Index of control point.</param>
  98. /// <returns></returns>
  99. public Vector3 GetPosition(int index)
  100. {
  101. return m_ControlPoints[index].position;
  102. }
  103. /// <summary>
  104. /// Set position of control point at index.
  105. /// </summary>
  106. /// <param name="index">Index of control point.</param>
  107. /// <param name="point">Position of control point.</param>
  108. /// <exception cref="ArgumentException"></exception>
  109. public void SetPosition(int index, Vector3 point)
  110. {
  111. if (!IsPositionValid(index, index + 1, point))
  112. throw new ArgumentException(KErrorMessage);
  113. SplineControlPoint newPoint = m_ControlPoints[index];
  114. newPoint.position = point;
  115. m_ControlPoints[index] = newPoint;
  116. }
  117. /// <summary>
  118. /// Get left tangent of control point at index.
  119. /// </summary>
  120. /// <param name="index">Index of control point.</param>
  121. /// <returns>Left tangent of control point.</returns>
  122. public Vector3 GetLeftTangent(int index)
  123. {
  124. ShapeTangentMode mode = GetTangentMode(index);
  125. if (mode == ShapeTangentMode.Linear)
  126. return Vector3.zero;
  127. return m_ControlPoints[index].leftTangent;
  128. }
  129. /// <summary>
  130. /// Set left tangent of control point at index.
  131. /// </summary>
  132. /// <param name="index">Index of control point.</param>
  133. /// <param name="tangent">Left tangent of control point.</param>
  134. public void SetLeftTangent(int index, Vector3 tangent)
  135. {
  136. ShapeTangentMode mode = GetTangentMode(index);
  137. if (mode == ShapeTangentMode.Linear)
  138. return;
  139. SplineControlPoint newPoint = m_ControlPoints[index];
  140. newPoint.leftTangent = tangent;
  141. m_ControlPoints[index] = newPoint;
  142. }
  143. /// <summary>
  144. /// Get right tangent of control point at index,
  145. /// </summary>
  146. /// <param name="index">Index of control point.</param>
  147. /// <returns>Right tangent of control point.</returns>
  148. public Vector3 GetRightTangent(int index)
  149. {
  150. ShapeTangentMode mode = GetTangentMode(index);
  151. if (mode == ShapeTangentMode.Linear)
  152. return Vector3.zero;
  153. return m_ControlPoints[index].rightTangent;
  154. }
  155. /// <summary>
  156. /// Set right tangent of control point at index.
  157. /// </summary>
  158. /// <param name="index">Index of control point.</param>
  159. /// <param name="tangent">Right tangent of control point.</param>
  160. public void SetRightTangent(int index, Vector3 tangent)
  161. {
  162. ShapeTangentMode mode = GetTangentMode(index);
  163. if (mode == ShapeTangentMode.Linear)
  164. return;
  165. SplineControlPoint newPoint = m_ControlPoints[index];
  166. newPoint.rightTangent = tangent;
  167. m_ControlPoints[index] = newPoint;
  168. }
  169. /// <summary>
  170. /// Get tangent mode of control point at index.
  171. /// </summary>
  172. /// <param name="index">Index of control point.</param>
  173. /// <returns>Tangent mode of control point</returns>
  174. public ShapeTangentMode GetTangentMode(int index)
  175. {
  176. return m_ControlPoints[index].mode;
  177. }
  178. /// <summary>
  179. /// Set the tangent mode of control point at index.
  180. /// </summary>
  181. /// <param name="index">Index of control point.</param>
  182. /// <param name="mode">Tangent mode.</param>
  183. public void SetTangentMode(int index, ShapeTangentMode mode)
  184. {
  185. SplineControlPoint newPoint = m_ControlPoints[index];
  186. newPoint.mode = mode;
  187. m_ControlPoints[index] = newPoint;
  188. }
  189. /// <summary>
  190. /// Get height of control point at index.
  191. /// </summary>
  192. /// <param name="index">Index of control point.</param>
  193. /// <returns>Height.</returns>
  194. public float GetHeight(int index)
  195. {
  196. return m_ControlPoints[index].height;
  197. }
  198. /// <summary>
  199. /// Set height of control point at index.
  200. /// </summary>
  201. /// <param name="index">Index of control point.</param>
  202. /// <param name="value">Height.</param>
  203. public void SetHeight(int index, float value)
  204. {
  205. m_ControlPoints[index].height = value;
  206. }
  207. /// <summary>
  208. /// Get Sprite index to be used for rendering edge starting at control point.
  209. /// </summary>
  210. /// <param name="index">Index of control point.</param>
  211. /// <returns>Sprite index.</returns>
  212. public int GetSpriteIndex(int index)
  213. {
  214. return m_ControlPoints[index].spriteIndex;
  215. }
  216. /// <summary>
  217. /// Set Sprite index to be used for rendering edge starting at control point.
  218. /// </summary>
  219. /// <param name="index">Index of control point.</param>
  220. /// <param name="value">Sprite index.</param>
  221. public void SetSpriteIndex(int index, int value)
  222. {
  223. m_ControlPoints[index].spriteIndex = value;
  224. }
  225. /// <summary>
  226. /// Test if a corner mode is enabled at control point.
  227. /// </summary>
  228. /// <param name="index">Index of control point.</param>
  229. /// <returns>True if a valid corner mode is set.</returns>
  230. public bool GetCorner(int index)
  231. {
  232. return GetCornerMode(index) != Corner.Disable;
  233. }
  234. /// <summary>
  235. /// Set corner mode to automatic or disabled.
  236. /// </summary>
  237. /// <param name="index">Index of control point.</param>
  238. /// <param name="value">Enable/disable corner mode</param>
  239. public void SetCorner(int index, bool value)
  240. {
  241. m_ControlPoints[index].corner = value;
  242. m_ControlPoints[index].cornerMode = value ? Corner.Automatic : Corner.Disable;
  243. }
  244. internal void SetCornerMode(int index, Corner value)
  245. {
  246. m_ControlPoints[index].corner = (value != Corner.Disable);
  247. m_ControlPoints[index].cornerMode = value;
  248. }
  249. internal Corner GetCornerMode(int index)
  250. {
  251. if (m_ControlPoints[index].cornerMode == Corner.Disable)
  252. {
  253. // For backward compatibility.
  254. if (m_ControlPoints[index].corner)
  255. {
  256. m_ControlPoints[index].cornerMode = Corner.Automatic;
  257. return Corner.Automatic;
  258. }
  259. }
  260. return m_ControlPoints[index].cornerMode;
  261. }
  262. /// <summary>
  263. /// Get hash code for this Spline to test for changes.
  264. /// </summary>
  265. /// <returns>Hash code as int.</returns>
  266. public override int GetHashCode()
  267. {
  268. unchecked
  269. {
  270. int hashCode = (int)2166136261;
  271. for (int i = 0; i < GetPointCount(); ++i)
  272. {
  273. hashCode = hashCode * 16777619 ^ m_ControlPoints[i].GetHashCode();
  274. }
  275. hashCode = hashCode * 16777619 ^ m_IsOpenEnded.GetHashCode();
  276. return hashCode;
  277. }
  278. }
  279. }
  280. }