DebugUI.Fields.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. using System;
  2. using System.Linq;
  3. using UnityEngine.Assertions;
  4. namespace UnityEngine.Rendering
  5. {
  6. public partial class DebugUI
  7. {
  8. /// <summary>
  9. /// Generic field - will be serialized in the editor if it's not read-only
  10. /// </summary>
  11. /// <typeparam name="T"></typeparam>
  12. public abstract class Field<T> : Widget, IValueField
  13. {
  14. /// <summary>
  15. /// Getter for this field.
  16. /// </summary>
  17. public Func<T> getter { get; set; }
  18. /// <summary>
  19. /// Setter for this field.
  20. /// </summary>
  21. public Action<T> setter { get; set; }
  22. // This should be an `event` but they don't play nice with object initializers in the
  23. // version of C# we use.
  24. /// <summary>
  25. /// Callback used when the value of the field changes.
  26. /// </summary>
  27. public Action<Field<T>, T> onValueChanged;
  28. /// <summary>
  29. /// Function used to validate the value when updating the field.
  30. /// </summary>
  31. /// <param name="value">Input value.</param>
  32. /// <returns>Validated value.</returns>
  33. object IValueField.ValidateValue(object value)
  34. {
  35. return ValidateValue((T)value);
  36. }
  37. /// <summary>
  38. /// Function used to validate the value when updating the field.
  39. /// </summary>
  40. /// <param name="value">Input value.</param>
  41. /// <returns>Validated value.</returns>
  42. public virtual T ValidateValue(T value)
  43. {
  44. return value;
  45. }
  46. /// <summary>
  47. /// Get the value of the field.
  48. /// </summary>
  49. /// <returns>Value of the field.</returns>
  50. object IValueField.GetValue()
  51. {
  52. return GetValue();
  53. }
  54. /// <summary>
  55. /// Get the value of the field.
  56. /// </summary>
  57. /// <returns>Value of the field.</returns>
  58. public T GetValue()
  59. {
  60. Assert.IsNotNull(getter);
  61. return getter();
  62. }
  63. /// <summary>
  64. /// Set the value of the field.
  65. /// </summary>
  66. /// <param name="value">Input value.</param>
  67. public void SetValue(object value)
  68. {
  69. SetValue((T)value);
  70. }
  71. /// <summary>
  72. /// Set the value of the field.
  73. /// </summary>
  74. /// <param name="value">Input value.</param>
  75. public void SetValue(T value)
  76. {
  77. Assert.IsNotNull(setter);
  78. var v = ValidateValue(value);
  79. if (!v.Equals(getter()))
  80. {
  81. setter(v);
  82. if (onValueChanged != null)
  83. onValueChanged(this, v);
  84. }
  85. }
  86. }
  87. /// <summary>
  88. /// Boolean field.
  89. /// </summary>
  90. public class BoolField : Field<bool> { }
  91. /// <summary>
  92. /// Boolean field with history.
  93. /// </summary>
  94. public class HistoryBoolField : BoolField
  95. {
  96. /// <summary>
  97. /// History getter for this field.
  98. /// </summary>
  99. public Func<bool>[] historyGetter { get; set; }
  100. /// <summary>
  101. /// Depth of the field's history.
  102. /// </summary>
  103. public int historyDepth => historyGetter?.Length ?? 0;
  104. /// <summary>
  105. /// Get the value of the field at a certain history index.
  106. /// </summary>
  107. /// <param name="historyIndex">Index of the history to query.</param>
  108. /// <returns>Value of the field at the provided history index.</returns>
  109. public bool GetHistoryValue(int historyIndex)
  110. {
  111. Assert.IsNotNull(historyGetter);
  112. Assert.IsTrue(historyIndex >= 0 && historyIndex < historyGetter.Length, "out of range historyIndex");
  113. Assert.IsNotNull(historyGetter[historyIndex]);
  114. return historyGetter[historyIndex]();
  115. }
  116. }
  117. /// <summary>
  118. /// Integer field.
  119. /// </summary>
  120. public class IntField : Field<int>
  121. {
  122. /// <summary>
  123. /// Minimum value function.
  124. /// </summary>
  125. public Func<int> min;
  126. /// <summary>
  127. /// Maximum value function.
  128. /// </summary>
  129. public Func<int> max;
  130. // Runtime-only
  131. /// <summary>
  132. /// Step increment.
  133. /// </summary>
  134. public int incStep = 1;
  135. /// <summary>
  136. /// Step increment multiplier.
  137. /// </summary>
  138. public int intStepMult = 10;
  139. /// <summary>
  140. /// Function used to validate the value when updating the field.
  141. /// </summary>
  142. /// <param name="value">Input value.</param>
  143. /// <returns>Validated value.</returns>
  144. public override int ValidateValue(int value)
  145. {
  146. if (min != null) value = Mathf.Max(value, min());
  147. if (max != null) value = Mathf.Min(value, max());
  148. return value;
  149. }
  150. }
  151. /// <summary>
  152. /// Unsigned integer field.
  153. /// </summary>
  154. public class UIntField : Field<uint>
  155. {
  156. /// <summary>
  157. /// Minimum value function.
  158. /// </summary>
  159. public Func<uint> min;
  160. /// <summary>
  161. /// Maximum value function.
  162. /// </summary>
  163. public Func<uint> max;
  164. // Runtime-only
  165. /// <summary>
  166. /// Step increment.
  167. /// </summary>
  168. public uint incStep = 1u;
  169. /// <summary>
  170. /// Step increment multiplier.
  171. /// </summary>
  172. public uint intStepMult = 10u;
  173. /// <summary>
  174. /// Function used to validate the value when updating the field.
  175. /// </summary>
  176. /// <param name="value">Input value.</param>
  177. /// <returns>Validated value.</returns>
  178. public override uint ValidateValue(uint value)
  179. {
  180. if (min != null) value = (uint)Mathf.Max((int)value, (int)min());
  181. if (max != null) value = (uint)Mathf.Min((int)value, (int)max());
  182. return value;
  183. }
  184. }
  185. /// <summary>
  186. /// Float field.
  187. /// </summary>
  188. public class FloatField : Field<float>
  189. {
  190. /// <summary>
  191. /// Minimum value function.
  192. /// </summary>
  193. public Func<float> min;
  194. /// <summary>
  195. /// Maximum value function.
  196. /// </summary>
  197. public Func<float> max;
  198. // Runtime-only
  199. /// <summary>
  200. /// Step increment.
  201. /// </summary>
  202. public float incStep = 0.1f;
  203. /// <summary>
  204. /// Step increment multiplier.
  205. /// </summary>
  206. public float incStepMult = 10f;
  207. /// <summary>
  208. /// Number of decimals.
  209. /// </summary>
  210. public int decimals = 3;
  211. /// <summary>
  212. /// Function used to validate the value when updating the field.
  213. /// </summary>
  214. /// <param name="value">Input value.</param>
  215. /// <returns>Validated value.</returns>
  216. public override float ValidateValue(float value)
  217. {
  218. if (min != null) value = Mathf.Max(value, min());
  219. if (max != null) value = Mathf.Min(value, max());
  220. return value;
  221. }
  222. }
  223. /// <summary>
  224. /// Enumerator field.
  225. /// </summary>
  226. public class EnumField : Field<int>
  227. {
  228. /// <summary>
  229. /// List of names of the enumerator entries.
  230. /// </summary>
  231. public GUIContent[] enumNames;
  232. /// <summary>
  233. /// List of values of the enumerator entries.
  234. /// </summary>
  235. public int[] enumValues;
  236. internal int[] quickSeparators;
  237. internal int[] indexes;
  238. /// <summary>
  239. /// Get the enumeration value index.
  240. /// </summary>
  241. public Func<int> getIndex { get; set; }
  242. /// <summary>
  243. /// Set the enumeration value index.
  244. /// </summary>
  245. public Action<int> setIndex { get; set; }
  246. /// <summary>
  247. /// Current enumeration value index.
  248. /// </summary>
  249. public int currentIndex { get { return getIndex(); } set { setIndex(value); } }
  250. /// <summary>
  251. /// Generates enumerator values and names automatically based on the provided type.
  252. /// </summary>
  253. public Type autoEnum
  254. {
  255. set
  256. {
  257. enumNames = Enum.GetNames(value).Select(x => new GUIContent(x)).ToArray();
  258. // Linq.Cast<T> on a typeless Array breaks the JIT on PS4/Mono so we have to do it manually
  259. //enumValues = Enum.GetValues(value).Cast<int>().ToArray();
  260. var values = Enum.GetValues(value);
  261. enumValues = new int[values.Length];
  262. for (int i = 0; i < values.Length; i++)
  263. enumValues[i] = (int)values.GetValue(i);
  264. InitIndexes();
  265. InitQuickSeparators();
  266. }
  267. }
  268. internal void InitQuickSeparators()
  269. {
  270. var enumNamesPrefix = enumNames.Select(x =>
  271. {
  272. string[] splitted = x.text.Split('/');
  273. if (splitted.Length == 1)
  274. return "";
  275. else
  276. return splitted[0];
  277. });
  278. quickSeparators = new int[enumNamesPrefix.Distinct().Count()];
  279. string lastPrefix = null;
  280. for (int i = 0, wholeNameIndex = 0; i < quickSeparators.Length; ++i)
  281. {
  282. var currentTestedPrefix = enumNamesPrefix.ElementAt(wholeNameIndex);
  283. while (lastPrefix == currentTestedPrefix)
  284. {
  285. currentTestedPrefix = enumNamesPrefix.ElementAt(++wholeNameIndex);
  286. }
  287. lastPrefix = currentTestedPrefix;
  288. quickSeparators[i] = wholeNameIndex++;
  289. }
  290. }
  291. internal void InitIndexes()
  292. {
  293. indexes = new int[enumNames.Length];
  294. for (int i = 0; i < enumNames.Length; i++)
  295. {
  296. indexes[i] = i;
  297. }
  298. }
  299. }
  300. /// <summary>
  301. /// Enumerator field with history.
  302. /// </summary>
  303. public class HistoryEnumField : EnumField
  304. {
  305. /// <summary>
  306. /// History getter for this field.
  307. /// </summary>
  308. public Func<int>[] historyIndexGetter { get; set; }
  309. /// <summary>
  310. /// Depth of the field's history.
  311. /// </summary>
  312. public int historyDepth => historyIndexGetter?.Length ?? 0;
  313. /// <summary>
  314. /// Get the value of the field at a certain history index.
  315. /// </summary>
  316. /// <param name="historyIndex">Index of the history to query.</param>
  317. /// <returns>Value of the field at the provided history index.</returns>
  318. public int GetHistoryValue(int historyIndex)
  319. {
  320. Assert.IsNotNull(historyIndexGetter);
  321. Assert.IsTrue(historyIndex >= 0 && historyIndex < historyIndexGetter.Length, "out of range historyIndex");
  322. Assert.IsNotNull(historyIndexGetter[historyIndex]);
  323. return historyIndexGetter[historyIndex]();
  324. }
  325. }
  326. /// <summary>
  327. /// Bitfield enumeration field.
  328. /// </summary>
  329. public class BitField : Field<Enum>
  330. {
  331. /// <summary>
  332. /// List of names of the enumerator entries.
  333. /// </summary>
  334. public GUIContent[] enumNames { get; private set; }
  335. /// <summary>
  336. /// List of values of the enumerator entries.
  337. /// </summary>
  338. public int[] enumValues { get; private set; }
  339. internal Type m_EnumType;
  340. /// <summary>
  341. /// Generates bitfield values and names automatically based on the provided type.
  342. /// </summary>
  343. public Type enumType
  344. {
  345. set
  346. {
  347. enumNames = Enum.GetNames(value).Select(x => new GUIContent(x)).ToArray();
  348. // Linq.Cast<T> on a typeless Array breaks the JIT on PS4/Mono so we have to do it manually
  349. //enumValues = Enum.GetValues(value).Cast<int>().ToArray();
  350. var values = Enum.GetValues(value);
  351. enumValues = new int[values.Length];
  352. for (int i = 0; i < values.Length; i++)
  353. enumValues[i] = (int)values.GetValue(i);
  354. m_EnumType = value;
  355. }
  356. get { return m_EnumType; }
  357. }
  358. }
  359. /// <summary>
  360. /// Color field.
  361. /// </summary>
  362. public class ColorField : Field<Color>
  363. {
  364. /// <summary>
  365. /// HDR color.
  366. /// </summary>
  367. public bool hdr = false;
  368. /// <summary>
  369. /// Show alpha of the color field.
  370. /// </summary>
  371. public bool showAlpha = true;
  372. // Editor-only
  373. /// <summary>
  374. /// Show the color picker.
  375. /// </summary>
  376. public bool showPicker = true;
  377. // Runtime-only
  378. /// <summary>
  379. /// Step increment.
  380. /// </summary>
  381. public float incStep = 0.025f;
  382. /// <summary>
  383. /// Step increment multiplier.
  384. /// </summary>
  385. public float incStepMult = 5f;
  386. /// <summary>
  387. /// Number of decimals.
  388. /// </summary>
  389. public int decimals = 3;
  390. /// <summary>
  391. /// Function used to validate the value when updating the field.
  392. /// </summary>
  393. /// <param name="value">Input value.</param>
  394. /// <returns>Validated value.</returns>
  395. public override Color ValidateValue(Color value)
  396. {
  397. if (!hdr)
  398. {
  399. value.r = Mathf.Clamp01(value.r);
  400. value.g = Mathf.Clamp01(value.g);
  401. value.b = Mathf.Clamp01(value.b);
  402. value.a = Mathf.Clamp01(value.a);
  403. }
  404. return value;
  405. }
  406. }
  407. /// <summary>
  408. /// Vector2 field.
  409. /// </summary>
  410. public class Vector2Field : Field<Vector2>
  411. {
  412. // Runtime-only
  413. /// <summary>
  414. /// Step increment.
  415. /// </summary>
  416. public float incStep = 0.025f;
  417. /// <summary>
  418. /// Step increment multiplier.
  419. /// </summary>
  420. public float incStepMult = 10f;
  421. /// <summary>
  422. /// Number of decimals.
  423. /// </summary>
  424. public int decimals = 3;
  425. }
  426. /// <summary>
  427. /// Vector3 field.
  428. /// </summary>
  429. public class Vector3Field : Field<Vector3>
  430. {
  431. // Runtime-only
  432. /// <summary>
  433. /// Step increment.
  434. /// </summary>
  435. public float incStep = 0.025f;
  436. /// <summary>
  437. /// Step increment multiplier.
  438. /// </summary>
  439. public float incStepMult = 10f;
  440. /// <summary>
  441. /// Number of decimals.
  442. /// </summary>
  443. public int decimals = 3;
  444. }
  445. /// <summary>
  446. /// Vector4 field.
  447. /// </summary>
  448. public class Vector4Field : Field<Vector4>
  449. {
  450. // Runtime-only
  451. /// <summary>
  452. /// Step increment.
  453. /// </summary>
  454. public float incStep = 0.025f;
  455. /// <summary>
  456. /// Step increment multiplier.
  457. /// </summary>
  458. public float incStepMult = 10f;
  459. /// <summary>
  460. /// Number of decimals.
  461. /// </summary>
  462. public int decimals = 3;
  463. }
  464. }
  465. }