Без опису
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.U2D;
  5. using ExtrasClipperLib;
  6. #if UNITY_EDITOR
  7. using UnityEditor;
  8. #endif
  9. namespace SpriteShapeExtras
  10. {
  11. public enum ColliderCornerType
  12. {
  13. Square,
  14. Round,
  15. Sharp
  16. }
  17. [ExecuteAlways]
  18. public class LegacyCollider : MonoBehaviour
  19. {
  20. [SerializeField]
  21. ColliderCornerType m_ColliderCornerType = ColliderCornerType.Square;
  22. [SerializeField]
  23. float m_ColliderOffset = 1.0f;
  24. [SerializeField]
  25. bool m_UpdateCollider = false;
  26. const float s_ClipperScale = 100000.0f;
  27. int m_HashCode = 0;
  28. // Start is called before the first frame update
  29. void Start()
  30. {
  31. }
  32. private static int NextIndex(int index, int pointCount)
  33. {
  34. return Mod(index + 1, pointCount);
  35. }
  36. private static int PreviousIndex(int index, int pointCount)
  37. {
  38. return Mod(index - 1, pointCount);
  39. }
  40. private static int Mod(int x, int m)
  41. {
  42. int r = x % m;
  43. return r < 0 ? r + m : r;
  44. }
  45. // Update is called once per frame
  46. void Update()
  47. {
  48. if (m_UpdateCollider)
  49. Bake(gameObject, false);
  50. }
  51. static void SampleCurve(float colliderDetail, Vector3 startPoint, Vector3 startTangent, Vector3 endPoint, Vector3 endTangent, ref List<IntPoint> path)
  52. {
  53. if (startTangent.sqrMagnitude > 0f || endTangent.sqrMagnitude > 0f)
  54. {
  55. for (int j = 0; j <= colliderDetail; ++j)
  56. {
  57. float t = j / (float)colliderDetail;
  58. Vector3 newPoint = BezierUtility.BezierPoint(startPoint, startTangent + startPoint, endTangent + endPoint, endPoint, t) * s_ClipperScale;
  59. path.Add(new IntPoint((System.Int64)newPoint.x, (System.Int64)newPoint.y));
  60. }
  61. }
  62. else
  63. {
  64. Vector3 newPoint = startPoint * s_ClipperScale;
  65. path.Add(new IntPoint((System.Int64)newPoint.x, (System.Int64)newPoint.y));
  66. newPoint = endPoint * s_ClipperScale;
  67. path.Add(new IntPoint((System.Int64)newPoint.x, (System.Int64)newPoint.y));
  68. }
  69. }
  70. public static void Bake(GameObject go, bool forced)
  71. {
  72. var sc = go.GetComponent<SpriteShapeController>();
  73. var lc = go.GetComponent<LegacyCollider>();
  74. if (sc != null)
  75. {
  76. List<IntPoint> path = new List<IntPoint>();
  77. int splinePointCount = sc.spline.GetPointCount();
  78. int pathPointCount = splinePointCount;
  79. ColliderCornerType cct = ColliderCornerType.Square;
  80. float co = 1.0f;
  81. if (lc != null)
  82. {
  83. int hashCode = sc.spline.GetHashCode() + lc.m_ColliderCornerType.GetHashCode() + lc.m_ColliderOffset.GetHashCode();
  84. if (lc.m_HashCode == hashCode && !forced)
  85. return;
  86. lc.m_HashCode = hashCode;
  87. cct = lc.m_ColliderCornerType;
  88. co = lc.m_ColliderOffset;
  89. }
  90. if (sc.spline.isOpenEnded)
  91. pathPointCount--;
  92. for (int i = 0; i < pathPointCount; ++i)
  93. {
  94. int nextIndex = NextIndex(i, splinePointCount);
  95. SampleCurve(sc.colliderDetail, sc.spline.GetPosition(i), sc.spline.GetRightTangent(i), sc.spline.GetPosition(nextIndex), sc.spline.GetLeftTangent(nextIndex), ref path);
  96. }
  97. if (co != 0f)
  98. {
  99. List<List<IntPoint>> solution = new List<List<IntPoint>>();
  100. ClipperOffset clipOffset = new ClipperOffset();
  101. EndType endType = EndType.etClosedPolygon;
  102. if (sc.spline.isOpenEnded)
  103. {
  104. endType = EndType.etOpenSquare;
  105. if (cct == ColliderCornerType.Round)
  106. endType = EndType.etOpenRound;
  107. }
  108. clipOffset.ArcTolerance = 200f / sc.colliderDetail;
  109. clipOffset.AddPath(path, (ExtrasClipperLib.JoinType)cct, endType);
  110. clipOffset.Execute(ref solution, s_ClipperScale * co);
  111. if (solution.Count > 0)
  112. path = solution[0];
  113. }
  114. List<Vector2> pathPoints = new List<Vector2>(path.Count);
  115. for (int i = 0; i < path.Count; ++i)
  116. {
  117. IntPoint ip = path[i];
  118. pathPoints.Add(new Vector2(ip.X / s_ClipperScale, ip.Y / s_ClipperScale));
  119. }
  120. var pc = go.GetComponent<PolygonCollider2D>();
  121. if (pc)
  122. {
  123. pc.pathCount = 0;
  124. pc.SetPath(0, pathPoints.ToArray());
  125. }
  126. var ec = go.GetComponent<EdgeCollider2D>();
  127. if (ec)
  128. {
  129. if (co > 0f || co < 0f && !sc.spline.isOpenEnded)
  130. pathPoints.Add(pathPoints[0]);
  131. ec.points = pathPoints.ToArray();
  132. }
  133. }
  134. }
  135. #if UNITY_EDITOR
  136. [MenuItem("SpriteShape/Generate Legacy Collider", false, 358)]
  137. public static void BakeLegacyCollider()
  138. {
  139. if (Selection.activeGameObject != null)
  140. LegacyCollider.Bake(Selection.activeGameObject, true);
  141. }
  142. #endif
  143. }
  144. }