EllipseMesh.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using UnityEngine;
  2. namespace FairyGUI
  3. {
  4. /// <summary>
  5. ///
  6. /// </summary>
  7. public class EllipseMesh : IMeshFactory, IHitTest
  8. {
  9. /// <summary>
  10. ///
  11. /// </summary>
  12. public Rect? drawRect;
  13. /// <summary>
  14. ///
  15. /// </summary>
  16. public float lineWidth;
  17. /// <summary>
  18. ///
  19. /// </summary>
  20. public Color32 lineColor;
  21. /// <summary>
  22. ///
  23. /// </summary>
  24. public Color32? centerColor;
  25. /// <summary>
  26. ///
  27. /// </summary>
  28. public Color32? fillColor;
  29. /// <summary>
  30. ///
  31. /// </summary>
  32. public float startDegree;
  33. /// <summary>
  34. ///
  35. /// </summary>
  36. public float endDegreee;
  37. static int[] SECTOR_CENTER_TRIANGLES = new int[] {
  38. 0, 4, 1,
  39. 0, 3, 4,
  40. 0, 2, 3,
  41. 0, 8, 5,
  42. 0, 7, 8,
  43. 0, 6, 7,
  44. 6, 5, 2,
  45. 2, 1, 6
  46. };
  47. public EllipseMesh()
  48. {
  49. lineColor = Color.black;
  50. startDegree = 0;
  51. endDegreee = 360;
  52. }
  53. public void OnPopulateMesh(VertexBuffer vb)
  54. {
  55. Rect rect = drawRect != null ? (Rect)drawRect : vb.contentRect;
  56. Color32 color = fillColor != null ? (Color32)fillColor : vb.vertexColor;
  57. float sectionStart = Mathf.Clamp(startDegree, 0, 360);
  58. float sectionEnd = Mathf.Clamp(endDegreee, 0, 360);
  59. bool clipped = sectionStart > 0 || sectionEnd < 360;
  60. sectionStart = sectionStart * Mathf.Deg2Rad;
  61. sectionEnd = sectionEnd * Mathf.Deg2Rad;
  62. Color32 centerColor2 = centerColor == null ? color : (Color32)centerColor;
  63. float radiusX = rect.width / 2;
  64. float radiusY = rect.height / 2;
  65. int sides = Mathf.CeilToInt(Mathf.PI * (radiusX + radiusY) / 4);
  66. sides = Mathf.Clamp(sides, 40, 800);
  67. float angleDelta = 2 * Mathf.PI / sides;
  68. float angle = 0;
  69. float lineAngle = 0;
  70. if (lineWidth > 0 && clipped)
  71. {
  72. lineAngle = lineWidth / Mathf.Max(radiusX, radiusY);
  73. sectionStart += lineAngle;
  74. sectionEnd -= lineAngle;
  75. }
  76. int vpos = vb.currentVertCount;
  77. float centerX = rect.x + radiusX;
  78. float centerY = rect.y + radiusY;
  79. vb.AddVert(new Vector3(centerX, centerY, 0), centerColor2);
  80. for (int i = 0; i < sides; i++)
  81. {
  82. if (angle < sectionStart)
  83. angle = sectionStart;
  84. else if (angle > sectionEnd)
  85. angle = sectionEnd;
  86. Vector3 vec = new Vector3(Mathf.Cos(angle) * (radiusX - lineWidth) + centerX, Mathf.Sin(angle) * (radiusY - lineWidth) + centerY, 0);
  87. vb.AddVert(vec, color);
  88. if (lineWidth > 0)
  89. {
  90. vb.AddVert(vec, lineColor);
  91. vb.AddVert(new Vector3(Mathf.Cos(angle) * radiusX + centerX, Mathf.Sin(angle) * radiusY + centerY, 0), lineColor);
  92. }
  93. angle += angleDelta;
  94. }
  95. if (lineWidth > 0)
  96. {
  97. int cnt = sides * 3;
  98. for (int i = 0; i < cnt; i += 3)
  99. {
  100. if (i != cnt - 3)
  101. {
  102. vb.AddTriangle(0, i + 1, i + 4);
  103. vb.AddTriangle(i + 5, i + 2, i + 3);
  104. vb.AddTriangle(i + 3, i + 6, i + 5);
  105. }
  106. else if (!clipped)
  107. {
  108. vb.AddTriangle(0, i + 1, 1);
  109. vb.AddTriangle(2, i + 2, i + 3);
  110. vb.AddTriangle(i + 3, 3, 2);
  111. }
  112. else
  113. {
  114. vb.AddTriangle(0, i + 1, i + 1);
  115. vb.AddTriangle(i + 2, i + 2, i + 3);
  116. vb.AddTriangle(i + 3, i + 3, i + 2);
  117. }
  118. }
  119. }
  120. else
  121. {
  122. for (int i = 0; i < sides; i++)
  123. {
  124. if (i != sides - 1)
  125. vb.AddTriangle(0, i + 1, i + 2);
  126. else if (!clipped)
  127. vb.AddTriangle(0, i + 1, 1);
  128. else
  129. vb.AddTriangle(0, i + 1, i + 1);
  130. }
  131. }
  132. if (lineWidth > 0 && clipped)
  133. {
  134. //扇形内边缘的线条
  135. vb.AddVert(new Vector3(radiusX, radiusY, 0), lineColor);
  136. float centerRadius = lineWidth * 0.5f;
  137. sectionStart -= lineAngle;
  138. angle = sectionStart + lineAngle * 0.5f + Mathf.PI * 0.5f;
  139. vb.AddVert(new Vector3(Mathf.Cos(angle) * centerRadius + radiusX, Mathf.Sin(angle) * centerRadius + radiusY, 0), lineColor);
  140. angle -= Mathf.PI;
  141. vb.AddVert(new Vector3(Mathf.Cos(angle) * centerRadius + radiusX, Mathf.Sin(angle) * centerRadius + radiusY, 0), lineColor);
  142. vb.AddVert(new Vector3(Mathf.Cos(sectionStart) * radiusX + radiusX, Mathf.Sin(sectionStart) * radiusY + radiusY, 0), lineColor);
  143. vb.AddVert(vb.GetPosition(vpos + 3), lineColor);
  144. sectionEnd += lineAngle;
  145. angle = sectionEnd - lineAngle * 0.5f + Mathf.PI * 0.5f;
  146. vb.AddVert(new Vector3(Mathf.Cos(angle) * centerRadius + radiusX, Mathf.Sin(angle) * centerRadius + radiusY, 0), lineColor);
  147. angle -= Mathf.PI;
  148. vb.AddVert(new Vector3(Mathf.Cos(angle) * centerRadius + radiusX, Mathf.Sin(angle) * centerRadius + radiusY, 0), lineColor);
  149. vb.AddVert(vb.GetPosition(vpos + sides * 3), lineColor);
  150. vb.AddVert(new Vector3(Mathf.Cos(sectionEnd) * radiusX + radiusX, Mathf.Sin(sectionEnd) * radiusY + radiusY, 0), lineColor);
  151. vb.AddTriangles(SECTOR_CENTER_TRIANGLES, sides * 3 + 1);
  152. }
  153. }
  154. public bool HitTest(Rect contentRect, Vector2 point)
  155. {
  156. if (!contentRect.Contains(point))
  157. return false;
  158. float radiusX = contentRect.width * 0.5f;
  159. float raduisY = contentRect.height * 0.5f;
  160. float xx = point.x - radiusX - contentRect.x;
  161. float yy = point.y - raduisY - contentRect.y;
  162. if (Mathf.Pow(xx / radiusX, 2) + Mathf.Pow(yy / raduisY, 2) < 1)
  163. {
  164. if (startDegree != 0 || endDegreee != 360)
  165. {
  166. float deg = Mathf.Atan2(yy, xx) * Mathf.Rad2Deg;
  167. if (deg < 0)
  168. deg += 360;
  169. return deg >= startDegree && deg <= endDegreee;
  170. }
  171. else
  172. return true;
  173. }
  174. return false;
  175. }
  176. }
  177. }