DepthSliceDropdown.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using System;
  2. using UnityEngine;
  3. #if UNITY_2019_1_OR_NEWER
  4. using System.Collections.Generic;
  5. using System.Reflection;
  6. using UnityEditor.IMGUI.Controls;
  7. namespace UnityEditor.Performance.ProfileAnalyzer
  8. {
  9. public class DepthSliceDropdown : AdvancedDropdown
  10. {
  11. class DepthSliceDropdownItem : AdvancedDropdownItem
  12. {
  13. public int depthSlice;
  14. public int depthSliceLeft;
  15. public int depthSliceRight;
  16. public DepthSliceDropdownItem(int depthSlice)
  17. : base(DepthSliceUI.DepthFilterToString(depthSlice))
  18. {
  19. this.depthSlice = depthSlice;
  20. depthSliceLeft = depthSlice;
  21. depthSliceRight = depthSlice;
  22. }
  23. public DepthSliceDropdownItem(int depthSliceLeft, int depthSliceRight, bool leftIsMain)
  24. : base(DepthSliceUI.DepthFilterToString(depthSliceLeft, depthSliceRight, leftIsMain))
  25. {
  26. depthSlice = Math.Max(depthSliceLeft, depthSliceRight);
  27. this.depthSliceLeft = depthSliceLeft;
  28. this.depthSliceRight = depthSliceRight;
  29. }
  30. }
  31. Action<int, int, int> m_Callback = null;
  32. int m_DepthSliceCount;
  33. int m_DepthSliceCountRight;
  34. int m_CurrentDepthSliceA;
  35. int m_CurrentDepthSliceB;
  36. int m_DepthDiff;
  37. static FieldInfo m_DataSourceFieldInfo;
  38. static Type m_DataSourceTypeInfo;
  39. static PropertyInfo m_SelectedIdsFieldInfo;
  40. public DepthSliceDropdown(int depthSliceCount, int currentDepthSliceA, int currentDepthSliceB, Action<int, int, int> callback, int depthDiff, int depthSliceCountRight = ProfileAnalyzer.kDepthAll) : base(new AdvancedDropdownState())
  41. {
  42. m_DepthSliceCount = depthSliceCount;
  43. m_DepthSliceCountRight = depthSliceCountRight;
  44. m_CurrentDepthSliceA = currentDepthSliceA;
  45. m_CurrentDepthSliceB = currentDepthSliceB;
  46. m_Callback = callback;
  47. m_DepthDiff = depthDiff;
  48. if (m_DataSourceFieldInfo == null || m_DataSourceFieldInfo == null || m_SelectedIdsFieldInfo == null)
  49. {
  50. Assembly assem = typeof(AdvancedDropdown).Assembly;
  51. var advancedDropdownTypeInfo = typeof(AdvancedDropdown);
  52. m_DataSourceTypeInfo = assem.GetType("UnityEditor.IMGUI.Controls.CallbackDataSource");
  53. m_DataSourceFieldInfo = advancedDropdownTypeInfo.GetField("m_DataSource", BindingFlags.NonPublic | BindingFlags.Instance);
  54. m_SelectedIdsFieldInfo = m_DataSourceTypeInfo.GetProperty("selectedIDs", BindingFlags.Public | BindingFlags.Instance);
  55. }
  56. }
  57. protected override AdvancedDropdownItem BuildRoot()
  58. {
  59. var root = new AdvancedDropdownItem("Depth Slice");
  60. var allItem = new DepthSliceDropdownItem(ProfileAnalyzer.kDepthAll);
  61. root.AddChild(allItem);
  62. if (m_CurrentDepthSliceA == ProfileAnalyzer.kDepthAll && m_CurrentDepthSliceB == ProfileAnalyzer.kDepthAll)
  63. (m_SelectedIdsFieldInfo.GetValue(m_DataSourceFieldInfo.GetValue(this)) as List<int>).Add(allItem.id);
  64. var count = m_DepthSliceCountRight == ProfileAnalyzer.kDepthAll ? m_DepthSliceCount :
  65. Math.Max(m_DepthSliceCount + Math.Max(0, m_DepthDiff), m_DepthSliceCountRight - Math.Min(0, m_DepthDiff));
  66. var leftIsMain = m_DepthDiff < 0;
  67. var mainThreshold = leftIsMain ? m_DepthSliceCount : m_DepthSliceCountRight;
  68. var secondaryMinThreshold = Math.Abs(m_DepthDiff);
  69. var secondaryMaxThreshold = (leftIsMain ? m_DepthSliceCountRight : m_DepthSliceCount) + secondaryMinThreshold;
  70. var startIndex = 1;
  71. for (int i = startIndex; i <= count; i++)
  72. {
  73. var selected = false;
  74. AdvancedDropdownItem child;
  75. if (m_DepthSliceCountRight != ProfileAnalyzer.kDepthAll)
  76. {
  77. var left = Mathf.Clamp(i - Math.Max(0, m_DepthDiff), 1, m_DepthSliceCount);
  78. var right = Mathf.Clamp(i - Math.Max(0, -m_DepthDiff), 1, m_DepthSliceCountRight);
  79. if (m_DepthSliceCount <= 0)
  80. left = -1;
  81. else if (m_DepthSliceCountRight <= 0)
  82. right = -1;
  83. else
  84. {
  85. // Separators only make sense if there is data on both sides
  86. // did we pass the threshold of the main's max depth and started clamping it down?
  87. if (i == mainThreshold + 1
  88. // ... or the threshold of the secondary's negative depth when adjusted for the depth diff, and stoped clamping it up?
  89. || (secondaryMinThreshold != 0 && i == secondaryMinThreshold + 1)
  90. // ... or the threshold of the secondary's max depth when adjusted for the depth diff, and started clamping it down?
  91. || (i == secondaryMaxThreshold + 1))
  92. root.AddSeparator();
  93. }
  94. child = new DepthSliceDropdownItem(left, right, leftIsMain);
  95. selected = m_CurrentDepthSliceA == left && m_CurrentDepthSliceB == right;
  96. }
  97. else
  98. {
  99. child = new DepthSliceDropdownItem(i);
  100. selected = m_CurrentDepthSliceA == i;
  101. }
  102. root.AddChild(child);
  103. if (selected)
  104. (m_SelectedIdsFieldInfo.GetValue(m_DataSourceFieldInfo.GetValue(this)) as List<int>).Add(child.id);
  105. }
  106. return root;
  107. }
  108. protected override void ItemSelected(AdvancedDropdownItem item)
  109. {
  110. base.ItemSelected(item);
  111. if (m_Callback != null)
  112. {
  113. var sliceItem = (item as DepthSliceDropdownItem);
  114. m_Callback(sliceItem.depthSlice, sliceItem.depthSliceLeft, sliceItem.depthSliceRight);
  115. }
  116. }
  117. }
  118. }
  119. #endif