2
0

UICircle.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /// Credit zge, jeremie sellam
  2. /// Sourced from - http://forum.unity3d.com/threads/draw-circles-or-primitives-on-the-new-ui-canvas.272488/#post-2293224
  3. /// Updated from - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/issues/65/a-better-uicircle
  4. /// Update 10.9.2017 (tswalker, https://bitbucket.org/tswalker/)
  5. ///
  6. /// * Modified component to utilize vertex stream instead of quads
  7. /// * Improved accuracy of geometry fill to prevent edge "sliding" and redundant tris
  8. /// * Added progress capability to allow component to be used as an indicator
  9. /// * Added methods for use during runtime and event system(s) with other components
  10. /// * Change some terminology of members to reflect other component property changes
  11. /// * Added padding capability
  12. /// * Only utilizes UV0 set for sprite/texture mapping (maps UV to geometry 0,1 boundary)
  13. /// * Sample usage in scene "UICircleProgress"
  14. /// Note: moving the pivot around from center to an edge can cause strange things
  15. /// as well as having the RectTransform be smaller than the Thickness and/or Padding.
  16. /// When making an initial layout for the component, it would be best to test multiple
  17. /// aspect ratios and resolutions to ensure consistent behaviour.
  18. using System.Collections.Generic;
  19. namespace UnityEngine.UI.Extensions
  20. {
  21. [AddComponentMenu("UI/Extensions/Primitives/UI Circle")]
  22. public class UICircle : UIPrimitiveBase
  23. {
  24. [Tooltip("The Arc Invert property will invert the construction of the Arc.")]
  25. public bool ArcInvert = true;
  26. [Tooltip("The Arc property is a percentage of the entire circumference of the circle.")]
  27. [Range(0, 1)]
  28. public float Arc = 1;
  29. [Tooltip("The Arc Steps property defines the number of segments that the Arc will be divided into.")]
  30. [Range(0, 1000)]
  31. public int ArcSteps = 100;
  32. [Tooltip("The Arc Rotation property permits adjusting the geometry orientation around the Z axis.")]
  33. [Range(0, 360)]
  34. public int ArcRotation = 0;
  35. [Tooltip("The Progress property allows the primitive to be used as a progression indicator.")]
  36. [Range(0, 1)]
  37. public float Progress = 0;
  38. private float _progress = 0;
  39. public Color ProgressColor = new Color(255, 255, 255, 255);
  40. public bool Fill = true; //solid circle
  41. public float Thickness = 5;
  42. public int Padding = 0;
  43. private List<int> indices = new List<int>(); //ordered list of vertices per tri
  44. private List<UIVertex> vertices = new List<UIVertex>();
  45. private Vector2 uvCenter = new Vector2(0.5f, 0.5f);
  46. protected override void OnPopulateMesh(VertexHelper vh)
  47. {
  48. int _inversion = ArcInvert ? -1 : 1;
  49. float Diameter = (rectTransform.rect.width < rectTransform.rect.height ? rectTransform.rect.width : rectTransform.rect.height) - Padding; //correct for padding and always fit RectTransform
  50. float outerDiameter = -rectTransform.pivot.x * Diameter;
  51. float innerDiameter = -rectTransform.pivot.x * Diameter + Thickness;
  52. vh.Clear();
  53. indices.Clear();
  54. vertices.Clear();
  55. int i = 0;
  56. int j = 1;
  57. int k = 0;
  58. float stepDegree = (Arc * 360f) / ArcSteps;
  59. _progress = ArcSteps * Progress;
  60. float rad = _inversion * Mathf.Deg2Rad * ArcRotation;
  61. float X = Mathf.Cos(rad);
  62. float Y = Mathf.Sin(rad);
  63. var vertex = UIVertex.simpleVert;
  64. vertex.color = _progress > 0 ? ProgressColor : color;
  65. //initial vertex
  66. vertex.position = new Vector2(outerDiameter * X, outerDiameter * Y);
  67. vertex.uv0 = new Vector2(vertex.position.x / Diameter + 0.5f, vertex.position.y / Diameter + 0.5f);
  68. vertices.Add(vertex);
  69. var iV = new Vector2(innerDiameter * X, innerDiameter * Y);
  70. if (Fill) iV = Vector2.zero; //center vertex to pivot
  71. vertex.position = iV;
  72. vertex.uv0 = Fill ? uvCenter : new Vector2(vertex.position.x / Diameter + 0.5f, vertex.position.y / Diameter + 0.5f);
  73. vertices.Add(vertex);
  74. for (int counter = 1; counter <= ArcSteps; counter++)
  75. {
  76. rad = _inversion * Mathf.Deg2Rad * (counter * stepDegree + ArcRotation);
  77. X = Mathf.Cos(rad);
  78. Y = Mathf.Sin(rad);
  79. vertex.color = counter > _progress ? color : ProgressColor;
  80. vertex.position = new Vector2(outerDiameter * X, outerDiameter * Y);
  81. vertex.uv0 = new Vector2(vertex.position.x / Diameter + 0.5f, vertex.position.y / Diameter + 0.5f);
  82. vertices.Add(vertex);
  83. //add additional vertex if required and generate indices for tris in clockwise order
  84. if (!Fill)
  85. {
  86. vertex.position = new Vector2(innerDiameter * X, innerDiameter * Y);
  87. vertex.uv0 = new Vector2(vertex.position.x / Diameter + 0.5f, vertex.position.y / Diameter + 0.5f);
  88. vertices.Add(vertex);
  89. k = j;
  90. indices.Add(i);
  91. indices.Add(j + 1);
  92. indices.Add(j);
  93. j++;
  94. i = j;
  95. j++;
  96. indices.Add(i);
  97. indices.Add(j);
  98. indices.Add(k);
  99. }
  100. else
  101. {
  102. indices.Add(i);
  103. indices.Add(j + 1);
  104. //Fills (solid circle) with progress require an additional vertex to
  105. // prevent the base circle from becoming a gradient from center to edge
  106. if (counter > _progress)
  107. {
  108. indices.Add(ArcSteps + 2);
  109. }
  110. else
  111. {
  112. indices.Add(1);
  113. }
  114. j++;
  115. i = j;
  116. }
  117. }
  118. //this vertex is added to the end of the list to simplify index ordering on geometry fill
  119. if (Fill)
  120. {
  121. vertex.position = iV;
  122. vertex.color = color;
  123. vertex.uv0 = uvCenter;
  124. vertices.Add(vertex);
  125. }
  126. vh.AddUIVertexStream(vertices, indices);
  127. }
  128. //the following methods may be used during run-time
  129. //to update the properties of the component
  130. public void SetProgress(float progress)
  131. {
  132. Progress = progress;
  133. SetVerticesDirty();
  134. }
  135. public void SetArcSteps(int steps)
  136. {
  137. ArcSteps = steps;
  138. SetVerticesDirty();
  139. }
  140. public void SetInvertArc(bool invert)
  141. {
  142. ArcInvert = invert;
  143. SetVerticesDirty();
  144. }
  145. public void SetArcRotation(int rotation)
  146. {
  147. ArcRotation = rotation;
  148. SetVerticesDirty();
  149. }
  150. public void SetFill(bool fill)
  151. {
  152. Fill = fill;
  153. SetVerticesDirty();
  154. }
  155. public void SetBaseColor(Color color)
  156. {
  157. this.color = color;
  158. SetVerticesDirty();
  159. }
  160. public void UpdateBaseAlpha(float value)
  161. {
  162. var _color = this.color;
  163. _color.a = value;
  164. this.color = _color;
  165. SetVerticesDirty();
  166. }
  167. public void SetProgressColor(Color color)
  168. {
  169. ProgressColor = color;
  170. SetVerticesDirty();
  171. }
  172. public void UpdateProgressAlpha(float value)
  173. {
  174. ProgressColor.a = value;
  175. SetVerticesDirty();
  176. }
  177. public void SetPadding(int padding)
  178. {
  179. Padding = padding;
  180. SetVerticesDirty();
  181. }
  182. public void SetThickness(int thickness)
  183. {
  184. Thickness = thickness;
  185. SetVerticesDirty();
  186. }
  187. }
  188. }