GizmosH.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. using System;
  2. using UnityEngine;
  3. namespace Popcron
  4. {
  5. public class Gizmos
  6. {
  7. private static string _prefsKey = null;
  8. private static int? _bufferSize = null;
  9. private static bool? _enabled = null;
  10. private static float? _dashGap = null;
  11. private static bool? _cull = null;
  12. private static int? _pass = null;
  13. private static Vector3? _offset = null;
  14. private static Vector3[] buffer = new Vector3[BufferSize];
  15. /// <summary>
  16. /// By default, it will always render to scene view camera and the main camera.
  17. /// Subscribing to this allows you to whitelist your custom cameras.
  18. /// </summary>
  19. public static Func<Camera, bool> CameraFilter = cam => false;
  20. private static string PrefsKey
  21. {
  22. get
  23. {
  24. if (string.IsNullOrEmpty(_prefsKey))
  25. {
  26. _prefsKey = $"{SystemInfo.deviceUniqueIdentifier}.{Application.companyName}.{Application.productName}.{Constants.UniqueIdentifier}";
  27. }
  28. return _prefsKey;
  29. }
  30. }
  31. /// <summary>
  32. /// The size of the total gizmos buffer.
  33. /// Default is 4096.
  34. /// </summary>
  35. public static int BufferSize
  36. {
  37. get
  38. {
  39. if (_bufferSize == null)
  40. {
  41. _bufferSize = PlayerPrefs.GetInt($"{PrefsKey}.BufferSize", 4096);
  42. }
  43. return _bufferSize.Value;
  44. }
  45. set
  46. {
  47. value = Mathf.Clamp(value, 0, int.MaxValue);
  48. if (_bufferSize != value)
  49. {
  50. _bufferSize = value;
  51. PlayerPrefs.SetInt($"{PrefsKey}.BufferSize", value);
  52. //buffer size changed, so recreate the buffer array too
  53. buffer = new Vector3[value];
  54. }
  55. }
  56. }
  57. /// <summary>
  58. /// Toggles wether the gizmos could be drawn or not.
  59. /// </summary>
  60. public static bool Enabled
  61. {
  62. get
  63. {
  64. if (_enabled == null)
  65. {
  66. _enabled = PlayerPrefs.GetInt($"{PrefsKey}.Enabled", 1) == 1;
  67. }
  68. return _enabled.Value;
  69. }
  70. set
  71. {
  72. if (_enabled != value)
  73. {
  74. _enabled = value;
  75. PlayerPrefs.SetInt($"{PrefsKey}.Enabled", value ? 1 : 0);
  76. }
  77. }
  78. }
  79. /// <summary>
  80. /// The size of the gap when drawing dashed elements.
  81. /// Default gap size is 0.1
  82. /// </summary>
  83. public static float DashGap
  84. {
  85. get
  86. {
  87. if (_dashGap == null)
  88. {
  89. _dashGap = PlayerPrefs.GetFloat($"{PrefsKey}.DashGap", 0.1f);
  90. }
  91. return _dashGap.Value;
  92. }
  93. set
  94. {
  95. if (_dashGap != value)
  96. {
  97. _dashGap = value;
  98. PlayerPrefs.SetFloat($"{PrefsKey}.DashGap", value);
  99. }
  100. }
  101. }
  102. [Obsolete("This property is obsolete. Use FrustumCulling instead.", false)]
  103. public static bool Cull
  104. {
  105. get
  106. {
  107. return FrustumCulling;
  108. }
  109. set
  110. {
  111. FrustumCulling = value;
  112. }
  113. }
  114. [Obsolete("This property is obsolete. Subscribe to CameraFilter predicate instead and return true for your custom camera.", false)]
  115. public static Camera Camera
  116. {
  117. get => null;
  118. set
  119. {
  120. }
  121. }
  122. /// <summary>
  123. /// Should the camera not draw elements that are not visible?
  124. /// </summary>
  125. public static bool FrustumCulling
  126. {
  127. get
  128. {
  129. if (_cull == null)
  130. {
  131. _cull = PlayerPrefs.GetInt($"{PrefsKey}.FrustumCulling", 1) == 1;
  132. }
  133. return _cull.Value;
  134. }
  135. set
  136. {
  137. if (_cull != value)
  138. {
  139. _cull = value;
  140. PlayerPrefs.SetInt($"{PrefsKey}.FrustumCulling", value ? 1 : 0);
  141. }
  142. }
  143. }
  144. /// <summary>
  145. /// The material being used to render.
  146. /// </summary>
  147. public static Material Material
  148. {
  149. get => GizmosInstance.Material;
  150. set => GizmosInstance.Material = value;
  151. }
  152. /// <summary>
  153. /// Rendering pass to activate.
  154. /// </summary>
  155. public static int Pass
  156. {
  157. get
  158. {
  159. if (_pass == null)
  160. {
  161. _pass = PlayerPrefs.GetInt($"{PrefsKey}.Pass", 0);
  162. }
  163. return _pass.Value;
  164. }
  165. set
  166. {
  167. if (_pass != value)
  168. {
  169. _pass = value;
  170. PlayerPrefs.SetInt($"{PrefsKey}.Pass", value);
  171. }
  172. }
  173. }
  174. /// <summary>
  175. /// Global offset for all points. Default is (0, 0, 0).
  176. /// </summary>
  177. public static Vector3 Offset
  178. {
  179. get
  180. {
  181. const string Delim = ",";
  182. if (_offset == null)
  183. {
  184. string data = PlayerPrefs.GetString($"{PrefsKey}.Offset", 0 + Delim + 0 + Delim + 0);
  185. int indexOf = data.IndexOf(Delim);
  186. int lastIndexOf = data.LastIndexOf(Delim);
  187. if (indexOf + lastIndexOf > 0)
  188. {
  189. string[] arr = data.Split(Delim[0]);
  190. _offset = new Vector3(float.Parse(arr[0]), float.Parse(arr[1]), float.Parse(arr[2]));
  191. }
  192. else
  193. {
  194. return Vector3.zero;
  195. }
  196. }
  197. return _offset.Value;
  198. }
  199. set
  200. {
  201. const string Delim = ",";
  202. if (_offset != value)
  203. {
  204. _offset = value;
  205. PlayerPrefs.SetString($"{PrefsKey}.Offset", value.x + Delim + value.y + Delim + value.y);
  206. }
  207. }
  208. }
  209. /// <summary>
  210. /// Draws an element onto the screen.
  211. /// </summary>
  212. public static void Draw<T>(Color? color, bool dashed, params object[] args) where T : Drawer
  213. {
  214. if (!Enabled)
  215. {
  216. return;
  217. }
  218. Drawer drawer = Drawer.Get<T>();
  219. if (drawer != null)
  220. {
  221. int points = drawer.Draw(ref buffer, args);
  222. //copy from buffer and add to the queue
  223. Vector3[] array = new Vector3[points];
  224. Array.Copy(buffer, array, points);
  225. GizmosInstance.Submit(array, color, dashed);
  226. }
  227. }
  228. /// <summary>
  229. /// Draws an array of lines. Useful for things like paths.
  230. /// </summary>
  231. public static void Lines(Vector3[] lines, Color? color = null, bool dashed = false)
  232. {
  233. if (!Enabled)
  234. {
  235. return;
  236. }
  237. GizmosInstance.Submit(lines, color, dashed);
  238. }
  239. /// <summary>
  240. /// Draw line in world space.
  241. /// </summary>
  242. public static void Line(Vector3 a, Vector3 b, Color? color = null, bool dashed = false)
  243. {
  244. Draw<LineDrawer>(color, dashed, a, b);
  245. }
  246. /// <summary>
  247. /// Draw square in world space.
  248. /// </summary>
  249. public static void Square(Vector2 position, Vector2 size, Color? color = null, bool dashed = false)
  250. {
  251. Square(position, Quaternion.identity, size, color, dashed);
  252. }
  253. /// <summary>
  254. /// Draw square in world space with float diameter parameter.
  255. /// </summary>
  256. public static void Square(Vector2 position, float diameter, Color? color = null, bool dashed = false)
  257. {
  258. Square(position, Quaternion.identity, Vector2.one * diameter, color, dashed);
  259. }
  260. /// <summary>
  261. /// Draw square in world space with a rotation parameter.
  262. /// </summary>
  263. public static void Square(Vector2 position, Quaternion rotation, Vector2 size, Color? color = null, bool dashed = false)
  264. {
  265. Draw<SquareDrawer>(color, dashed, position, rotation, size);
  266. }
  267. /// <summary>
  268. /// Draws a cube in world space.
  269. /// </summary>
  270. public static void Cube(Vector3 position, Quaternion rotation, Vector3 size, Color? color = null, bool dashed = false)
  271. {
  272. Draw<CubeDrawer>(color, dashed, position, rotation, size);
  273. }
  274. /// <summary>
  275. /// Draws a rectangle in screen space.
  276. /// </summary>
  277. public static void Rect(Rect rect, Camera camera, Color? color = null, bool dashed = false)
  278. {
  279. rect.y = Screen.height - rect.y;
  280. Vector2 corner = camera.ScreenToWorldPoint(new Vector2(rect.x, rect.y - rect.height));
  281. Draw<SquareDrawer>(color, dashed, corner + rect.size * 0.5f, Quaternion.identity, rect.size);
  282. }
  283. /// <summary>
  284. /// Draws a representation of a bounding box.
  285. /// </summary>
  286. public static void Bounds(Bounds bounds, Color? color = null, bool dashed = false)
  287. {
  288. Draw<CubeDrawer>(color, dashed, bounds.center, Quaternion.identity, bounds.size);
  289. }
  290. /// <summary>
  291. /// Draws a cone similar to the one that spot lights draw.
  292. /// </summary>
  293. public static void Cone(Vector3 position, Quaternion rotation, float length, float angle, Color? color = null, bool dashed = false, int pointsCount = 16)
  294. {
  295. //draw the end of the cone
  296. float endAngle = Mathf.Tan(angle * 0.5f * Mathf.Deg2Rad) * length;
  297. Vector3 forward = rotation * Vector3.forward;
  298. Vector3 endPosition = position + forward * length;
  299. float offset = 0f;
  300. Draw<PolygonDrawer>(color, dashed, endPosition, pointsCount, endAngle, offset, rotation);
  301. //draw the 4 lines
  302. for (int i = 0; i < 4; i++)
  303. {
  304. float a = i * 90f * Mathf.Deg2Rad;
  305. Vector3 point = rotation * new Vector3(Mathf.Cos(a), Mathf.Sin(a)) * endAngle;
  306. Line(position, position + point + forward * length, color, dashed);
  307. }
  308. }
  309. /// <summary>
  310. /// Draws a sphere at position with specified radius.
  311. /// </summary>
  312. public static void Sphere(Vector3 position, float radius, Color? color = null, bool dashed = false, int pointsCount = 16)
  313. {
  314. float offset = 0f;
  315. Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(0f, 0f, 0f));
  316. Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(90f, 0f, 0f));
  317. Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(0f, 90f, 90f));
  318. }
  319. /// <summary>
  320. /// Draws a circle in world space and billboards towards the camera.
  321. /// </summary>
  322. public static void Circle(Vector3 position, float radius, Camera camera, Color? color = null, bool dashed = false, int pointsCount = 16)
  323. {
  324. float offset = 0f;
  325. Quaternion rotation = Quaternion.LookRotation(position - camera.transform.position);
  326. Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, rotation);
  327. }
  328. /// <summary>
  329. /// Draws a circle in world space with a specified rotation.
  330. /// </summary>
  331. public static void Circle(Vector3 position, float radius, Quaternion rotation, Color? color = null, bool dashed = false, int pointsCount = 16)
  332. {
  333. float offset = 0f;
  334. Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, rotation);
  335. }
  336. }
  337. }