Line.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. namespace LineUI
  5. {
  6. [RequireComponent(typeof(CanvasRenderer))]
  7. [RequireComponent(typeof(RectTransform))]
  8. public class Line : Graphic
  9. {
  10. [SerializeField] private bool loop = false;
  11. [SerializeField] private float thickness = 1f;
  12. [SerializeField] private int roundCount = 0;
  13. [SerializeField] private Vector2 quadrilateralSize = new Vector2(100, 100);
  14. [SerializeField] private Color quadColor = Color.red;
  15. [SerializeField] private List<Vector2> screenPositions = new List<Vector2>();
  16. //[SerializeField] private Color quadTextColor = Color.black;
  17. //[SerializeField] private int quadFontSize = 14;
  18. //private List<Vector2> quadsToDraw = new List<Vector2>();
  19. //private List<string> quadTextToDraw = new List<string>();
  20. //private List<GameObject> quadObjects = new List<GameObject>();
  21. //private Stack<GameObject> objectPool = new Stack<GameObject>();
  22. private const int ObjectPoolLimit = 4;
  23. public RectTransform RectTr => rectTransform;
  24. public float MyThickness
  25. {
  26. get => thickness;
  27. set
  28. {
  29. if (value >= 10)
  30. {
  31. thickness = value;
  32. }
  33. }
  34. }
  35. public void SetLine(List<Vector2> screenPositions)
  36. {
  37. this.screenPositions = screenPositions;
  38. SetVerticesDirty();
  39. }
  40. protected override void OnPopulateMesh(VertexHelper vh)
  41. {
  42. vh.Clear();
  43. //quadsToDraw.Clear();
  44. //quadTextToDraw.Clear();
  45. if (screenPositions.Count < 2)
  46. return;
  47. SetLineVertices(vh);
  48. SetLineTriangles(vh);
  49. SetQuadrilateralVertices(vh);
  50. }
  51. private void SetLineVertices(VertexHelper vh)
  52. {
  53. UIVertex vert = UIVertex.simpleVert;
  54. vert.color = color;
  55. List<Vector2> _screenPositions = new List<Vector2>(screenPositions);
  56. if (loop)
  57. {
  58. _screenPositions.Add(screenPositions[0]);
  59. _screenPositions.Add(screenPositions[1]);
  60. }
  61. float lastAngle = 0;
  62. for (int i = 1; i < _screenPositions.Count; i++)
  63. {
  64. Vector2 previousPos = _screenPositions[i - 1];
  65. Vector2 currentPos = _screenPositions[i];
  66. Vector2 dif = currentPos - previousPos;
  67. float angle = Vector2.SignedAngle(Vector2.right, dif);
  68. Vector2 offset = Quaternion.Euler(0, 0, angle) * Vector3.up * thickness;
  69. if (i > 1)
  70. {
  71. float anglePerRound = (angle - lastAngle) / roundCount;
  72. for (int j = 0; j <= roundCount; j++)
  73. {
  74. float ang = lastAngle + anglePerRound * j;
  75. Vector2 roundOffset = Quaternion.Euler(0, 0, ang) * Vector2.up * thickness;
  76. vert.position = previousPos - roundOffset;
  77. vh.AddVert(vert);
  78. vert.position = previousPos + roundOffset;
  79. vh.AddVert(vert);
  80. }
  81. }
  82. lastAngle = angle;
  83. vert.position = previousPos - offset;
  84. vh.AddVert(vert);
  85. vert.position = previousPos + offset;
  86. vh.AddVert(vert);
  87. vert.position = currentPos - offset;
  88. vh.AddVert(vert);
  89. vert.position = currentPos + offset;
  90. vh.AddVert(vert);
  91. }
  92. }
  93. private void SetQuadrilateralVertices(VertexHelper vh)
  94. {
  95. UIVertex vert = UIVertex.simpleVert;
  96. vert.color = quadColor;
  97. List<Vector2> _screenPositions = new List<Vector2>(screenPositions);
  98. if (loop)
  99. {
  100. _screenPositions.Add(screenPositions[0]);
  101. _screenPositions.Add(screenPositions[1]);
  102. }
  103. for (int i = 1; i < _screenPositions.Count; i++)
  104. {
  105. Vector2 previousPos = _screenPositions[i - 1];
  106. Vector2 currentPos = _screenPositions[i];
  107. if (i > 1)
  108. {
  109. Vector2 prevDir = (_screenPositions[i - 1] - _screenPositions[i - 2]).normalized;
  110. Vector2 currentDir = (currentPos - previousPos).normalized;
  111. int index = i == 4 ? 4 : i % 4;
  112. if (index == 4 || index == 2)
  113. {
  114. DrawSquareAtCorner(vh, previousPos, prevDir, currentDir, quadrilateralSize.x, quadrilateralSize.y, index);
  115. }
  116. else {
  117. DrawSquareAtCorner(vh, previousPos, prevDir, currentDir, quadrilateralSize.y, quadrilateralSize.x, index);
  118. }
  119. }
  120. }
  121. }
  122. private void DrawSquareAtCorner(VertexHelper vh, Vector2 corner, Vector2 prevDir, Vector2 currentDir, float width, float height, int index)
  123. {
  124. UIVertex vert = UIVertex.simpleVert;
  125. vert.color = quadColor;
  126. Vector2[] corners = new Vector2[4];
  127. corners[0] = corner;
  128. corners[1] = corner + prevDir * -width;
  129. corners[2] = corner + prevDir * -width + currentDir * height;
  130. corners[3] = corner + currentDir * height;
  131. foreach (Vector2 pos in corners)
  132. {
  133. vert.position = pos;
  134. vh.AddVert(vert);
  135. }
  136. int startIndex = vh.currentVertCount - 4;
  137. vh.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
  138. vh.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
  139. // Store the quad's center position and text for later use
  140. //Vector2 quadCenter = corner + (prevDir * -width + currentDir * height) / 2;
  141. //quadsToDraw.Add(quadCenter);
  142. //quadTextToDraw.Add(index.ToString());
  143. }
  144. private void SetLineTriangles(VertexHelper vh)
  145. {
  146. for (int i = 0; i < vh.currentVertCount - 2; i += 2)
  147. {
  148. int index = i;
  149. vh.AddTriangle(index, index + 1, index + 3);
  150. vh.AddTriangle(index + 3, index + 2, index);
  151. }
  152. }
  153. //private void LateUpdate()
  154. //{
  155. // foreach (var quadObj in quadObjects)
  156. // {
  157. // if (quadObj != null)
  158. // {
  159. // objectPool.Push(quadObj);
  160. // }
  161. // }
  162. // quadObjects.Clear();
  163. // for (int i = 0; i < quadsToDraw.Count; i++)
  164. // {
  165. // GameObject quadGO = GetQuadObject();
  166. // if (quadGO != null)
  167. // {
  168. // quadGO.SetActive(true);
  169. // quadGO.GetComponent<RectTransform>().anchoredPosition = quadsToDraw[i];
  170. // Text quadTextComponent = quadGO.GetComponent<Text>();
  171. // quadTextComponent.text = quadTextToDraw[i];
  172. // quadTextComponent.fontSize = quadFontSize;
  173. // quadTextComponent.color = quadTextColor;
  174. // quadTextComponent.alignment = TextAnchor.MiddleCenter;
  175. // }
  176. // }
  177. // quadsToDraw.Clear();
  178. // quadTextToDraw.Clear();
  179. //}
  180. //private GameObject GetQuadObject()
  181. //{
  182. // if (objectPool.Count > 0)
  183. // {
  184. // GameObject quadGO = objectPool.Pop();
  185. // if (quadGO != null)
  186. // {
  187. // quadObjects.Add(quadGO);
  188. // return quadGO;
  189. // }
  190. // }
  191. // if (quadObjects.Count < ObjectPoolLimit)
  192. // {
  193. // GameObject newQuadGO = new GameObject("QuadText", typeof(RectTransform), typeof(Text));
  194. // newQuadGO.transform.SetParent(this.transform);
  195. // Text quadTextComponent = newQuadGO.GetComponent<Text>();
  196. // quadTextComponent.alignment = TextAnchor.MiddleCenter;
  197. // quadTextComponent.rectTransform.sizeDelta = new Vector2(quadrilateralSize.x, quadrilateralSize.y);
  198. // quadObjects.Add(newQuadGO);
  199. // return newQuadGO;
  200. // }
  201. // return null;
  202. //}
  203. }
  204. }