You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
6.0 KiB
C#

1 year ago
using System;
using UnityEngine;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor.IMGUI.Controls;
namespace UnityEditor.Performance.ProfileAnalyzer
{
class DepthSliceDropdown : AdvancedDropdown
{
class DepthSliceDropdownItem : AdvancedDropdownItem
{
public int depthSlice;
public int depthSliceLeft;
public int depthSliceRight;
public DepthSliceDropdownItem(int depthSlice)
: base(DepthSliceUI.DepthFilterToString(depthSlice))
{
this.depthSlice = depthSlice;
depthSliceLeft = depthSlice;
depthSliceRight = depthSlice;
}
public DepthSliceDropdownItem(int depthSliceLeft, int depthSliceRight, bool leftIsMain)
: base(DepthSliceUI.DepthFilterToString(depthSliceLeft, depthSliceRight, leftIsMain))
{
depthSlice = Math.Max(depthSliceLeft, depthSliceRight);
this.depthSliceLeft = depthSliceLeft;
this.depthSliceRight = depthSliceRight;
}
}
Action<int, int, int> m_Callback = null;
int m_DepthSliceCount;
int m_DepthSliceCountRight;
int m_CurrentDepthSliceA;
int m_CurrentDepthSliceB;
int m_DepthDiff;
static FieldInfo m_DataSourceFieldInfo;
static Type m_DataSourceTypeInfo;
static PropertyInfo m_SelectedIdsFieldInfo;
public DepthSliceDropdown(int depthSliceCount, int currentDepthSliceA, int currentDepthSliceB, Action<int, int, int> callback, int depthDiff, int depthSliceCountRight = ProfileAnalyzer.kDepthAll) : base(new AdvancedDropdownState())
{
m_DepthSliceCount = depthSliceCount;
m_DepthSliceCountRight = depthSliceCountRight;
m_CurrentDepthSliceA = currentDepthSliceA;
m_CurrentDepthSliceB = currentDepthSliceB;
m_Callback = callback;
m_DepthDiff = depthDiff;
if (m_DataSourceFieldInfo == null || m_DataSourceFieldInfo == null || m_SelectedIdsFieldInfo == null)
{
Assembly assem = typeof(AdvancedDropdown).Assembly;
var advancedDropdownTypeInfo = typeof(AdvancedDropdown);
m_DataSourceTypeInfo = assem.GetType("UnityEditor.IMGUI.Controls.CallbackDataSource");
m_DataSourceFieldInfo = advancedDropdownTypeInfo.GetField("m_DataSource", BindingFlags.NonPublic | BindingFlags.Instance);
m_SelectedIdsFieldInfo = m_DataSourceTypeInfo.GetProperty("selectedIDs", BindingFlags.Public | BindingFlags.Instance);
}
}
protected override AdvancedDropdownItem BuildRoot()
{
var root = new AdvancedDropdownItem("Depth Slice");
var allItem = new DepthSliceDropdownItem(ProfileAnalyzer.kDepthAll);
root.AddChild(allItem);
if (m_CurrentDepthSliceA == ProfileAnalyzer.kDepthAll && m_CurrentDepthSliceB == ProfileAnalyzer.kDepthAll)
(m_SelectedIdsFieldInfo.GetValue(m_DataSourceFieldInfo.GetValue(this)) as List<int>).Add(allItem.id);
var count = m_DepthSliceCountRight == ProfileAnalyzer.kDepthAll ? m_DepthSliceCount :
Math.Max(m_DepthSliceCount + Math.Max(0, m_DepthDiff), m_DepthSliceCountRight - Math.Min(0, m_DepthDiff));
var leftIsMain = m_DepthDiff < 0;
var mainThreshold = leftIsMain ? m_DepthSliceCount : m_DepthSliceCountRight;
var secondaryMinThreshold = Math.Abs(m_DepthDiff);
var secondaryMaxThreshold = (leftIsMain ? m_DepthSliceCountRight : m_DepthSliceCount) + secondaryMinThreshold;
var startIndex = 1;
for (int i = startIndex; i <= count; i++)
{
var selected = false;
AdvancedDropdownItem child;
if (m_DepthSliceCountRight != ProfileAnalyzer.kDepthAll)
{
var left = Mathf.Clamp(i - Math.Max(0, m_DepthDiff), 1, m_DepthSliceCount);
var right = Mathf.Clamp(i - Math.Max(0, -m_DepthDiff), 1, m_DepthSliceCountRight);
if (m_DepthSliceCount <= 0)
left = -1;
else if (m_DepthSliceCountRight <= 0)
right = -1;
else
{
// Separators only make sense if there is data on both sides
// did we pass the threshold of the main's max depth and started clamping it down?
if (i == mainThreshold + 1
// ... or the threshold of the secondary's negative depth when adjusted for the depth diff, and stoped clamping it up?
|| (secondaryMinThreshold != 0 && i == secondaryMinThreshold + 1)
// ... or the threshold of the secondary's max depth when adjusted for the depth diff, and started clamping it down?
|| (i == secondaryMaxThreshold + 1))
root.AddSeparator();
}
child = new DepthSliceDropdownItem(left, right, leftIsMain);
selected = m_CurrentDepthSliceA == left && m_CurrentDepthSliceB == right;
}
else
{
child = new DepthSliceDropdownItem(i);
selected = m_CurrentDepthSliceA == i;
}
root.AddChild(child);
if (selected)
(m_SelectedIdsFieldInfo.GetValue(m_DataSourceFieldInfo.GetValue(this)) as List<int>).Add(child.id);
}
return root;
}
protected override void ItemSelected(AdvancedDropdownItem item)
{
base.ItemSelected(item);
if (m_Callback != null)
{
var sliceItem = (item as DepthSliceDropdownItem);
m_Callback(sliceItem.depthSlice, sliceItem.depthSliceLeft, sliceItem.depthSliceRight);
}
}
}
}