源战役客户端
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

187 righe
6.4 KiB

  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. using UnityEngine.Sprites;
  5. [AddComponentMenu("UI/Circle Image")]
  6. public class CircleImage : BaseImage {
  7. // Use this for initialization
  8. void Awake () {
  9. innerVertices = new List<Vector3>();
  10. outterVertices = new List<Vector3>();
  11. }
  12. // Update is called once per frame
  13. void Update () {
  14. this.thickness = (float)Mathf.Clamp(this.thickness, 0, rectTransform.rect.width / 2);
  15. }
  16. [Tooltip("圆形或扇形填充比例")]
  17. [Range(0, 1)]
  18. public float fillPercent = 1f;
  19. [Tooltip("是否填充圆形")]
  20. public bool fill = true;
  21. [Tooltip("圆环宽度")]
  22. public float thickness = 5;
  23. [Tooltip("圆形")]
  24. [Range(3, 100)]
  25. public int segements = 20;
  26. private List<Vector3> innerVertices;
  27. private List<Vector3> outterVertices;
  28. protected override void OnPopulateMesh(VertexHelper vh)
  29. {
  30. vh.Clear();
  31. innerVertices.Clear();
  32. outterVertices.Clear();
  33. float degreeDelta = (float)(2 * Mathf.PI / segements);
  34. int curSegements = (int)(segements * fillPercent);
  35. float tw = rectTransform.rect.width;
  36. float th = rectTransform.rect.height;
  37. float outerRadius = rectTransform.pivot.x * tw;
  38. float innerRadius = rectTransform.pivot.x * tw - thickness;
  39. Vector4 uv = overrideSprite != null ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero;
  40. float uvCenterX = (uv.x + uv.z) * 0.5f;
  41. float uvCenterY = (uv.y + uv.w) * 0.5f;
  42. float uvScaleX = (uv.z - uv.x) / tw;
  43. float uvScaleY = (uv.w - uv.y) / th;
  44. float curDegree = 0;
  45. UIVertex uiVertex;
  46. int verticeCount;
  47. int triangleCount;
  48. Vector2 curVertice;
  49. if (fill) //圆形
  50. {
  51. curVertice = Vector2.zero;
  52. verticeCount = curSegements + 1;
  53. uiVertex = new UIVertex();
  54. uiVertex.color = color;
  55. uiVertex.position = curVertice;
  56. uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY);
  57. vh.AddVert(uiVertex);
  58. for (int i = 1; i < verticeCount; i++)
  59. {
  60. float cosA = Mathf.Cos(curDegree);
  61. float sinA = Mathf.Sin(curDegree);
  62. curVertice = new Vector2(cosA * outerRadius, sinA * outerRadius);
  63. curDegree += degreeDelta;
  64. uiVertex = new UIVertex();
  65. uiVertex.color = color;
  66. uiVertex.position = curVertice;
  67. uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY);
  68. vh.AddVert(uiVertex);
  69. outterVertices.Add(curVertice);
  70. }
  71. triangleCount = curSegements*3;
  72. for (int i = 0, vIdx = 1; i < triangleCount - 3; i += 3, vIdx++)
  73. {
  74. vh.AddTriangle(vIdx, 0, vIdx+1);
  75. }
  76. if (fillPercent == 1)
  77. {
  78. //首尾顶点相连
  79. vh.AddTriangle(verticeCount - 1, 0, 1);
  80. }
  81. }
  82. else//圆环
  83. {
  84. verticeCount = curSegements*2;
  85. for (int i = 0; i < verticeCount; i += 2)
  86. {
  87. float cosA = Mathf.Cos(curDegree);
  88. float sinA = Mathf.Sin(curDegree);
  89. curDegree += degreeDelta;
  90. curVertice = new Vector3(cosA * innerRadius, sinA * innerRadius);
  91. uiVertex = new UIVertex();
  92. uiVertex.color = color;
  93. uiVertex.position = curVertice;
  94. uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY);
  95. vh.AddVert(uiVertex);
  96. innerVertices.Add(curVertice);
  97. curVertice = new Vector3(cosA * outerRadius, sinA * outerRadius);
  98. uiVertex = new UIVertex();
  99. uiVertex.color = color;
  100. uiVertex.position = curVertice;
  101. uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY);
  102. vh.AddVert(uiVertex);
  103. outterVertices.Add(curVertice);
  104. }
  105. triangleCount = curSegements*3*2;
  106. for (int i = 0, vIdx = 0; i < triangleCount - 6; i += 6, vIdx += 2)
  107. {
  108. vh.AddTriangle(vIdx+1, vIdx, vIdx+3);
  109. vh.AddTriangle(vIdx, vIdx + 2, vIdx + 3);
  110. }
  111. if (fillPercent == 1)
  112. {
  113. //首尾顶点相连
  114. vh.AddTriangle(verticeCount - 1, verticeCount - 2, 1);
  115. vh.AddTriangle(verticeCount - 2, 0, 1);
  116. }
  117. }
  118. }
  119. public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
  120. {
  121. Sprite sprite = overrideSprite;
  122. if (sprite == null)
  123. return true;
  124. Vector2 local;
  125. RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local);
  126. return Contains(local, outterVertices, innerVertices);
  127. }
  128. private bool Contains(Vector2 p, List<Vector3> outterVertices, List<Vector3> innerVertices)
  129. {
  130. var crossNumber = 0;
  131. RayCrossing(p, innerVertices, ref crossNumber);//检测内环
  132. RayCrossing(p, outterVertices, ref crossNumber);//检测外环
  133. return (crossNumber & 1) == 1;
  134. }
  135. /// <summary>
  136. /// 使用RayCrossing算法判断点击点是否在封闭多边形里
  137. /// </summary>
  138. /// <param name="p"></param>
  139. /// <param name="vertices"></param>
  140. /// <param name="crossNumber"></param>
  141. private void RayCrossing(Vector2 p, List<Vector3> vertices, ref int crossNumber)
  142. {
  143. for (int i = 0, count = vertices.Count; i < count; i++)
  144. {
  145. var v1 = vertices[i];
  146. var v2 = vertices[(i + 1) % count];
  147. //点击点水平线必须与两顶点线段相交
  148. if (((v1.y <= p.y) && (v2.y > p.y))
  149. || ((v1.y > p.y) && (v2.y <= p.y)))
  150. {
  151. //只考虑点击点右侧方向,点击点水平线与线段相交,且交点x > 点击点x,则crossNumber+1
  152. if (p.x < v1.x + (p.y - v1.y) / (v2.y - v1.y) * (v2.x - v1.x))
  153. {
  154. crossNumber += 1;
  155. }
  156. }
  157. }
  158. }
  159. }