module-navigation-tool/Editor/Toolbar/Tools/ToolBuildTargetPicker.cs

144 lines
5 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
using JetBrains.Annotations;
using UnityEditor;
using UnityEngine;
using UTools = UnityEditor.Tools;
namespace Module.NavigationTool.Editor.Toolbar
{
[UsedImplicitly]
internal sealed class ToolBuildTargetPicker : AbstractToolbarDrawer
{
public override bool Visible => ToolbarBuildSettings.IsBuildEnabled;
public override bool Enabled => !Application.isPlaying;
public override EToolbarPlacement Placement => EToolbarPlacement.Left;
public override int Priority => (int)EToolbarPriority.Low;
private static bool IS_DIRTY = true;
private static int[] HASHES = new int[0];
private static BuildTargetGroup[] GROUPS = new BuildTargetGroup[0];
private static BuildTarget[] TARGETS = new BuildTarget[0];
private static GUIContent[] TARGET_LIST = new GUIContent[0];
private static int SELECTED_INDEX = -1;
private static void Initialize()
{
if (!IS_DIRTY)
return;
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);
PopulateBuildTargetList();
SELECTED_INDEX = Array.IndexOf(HASHES, GetHashCode(group, target));
IS_DIRTY = false;
}
public override void Update()
{
Initialize();
}
protected override void Draw(Rect rect)
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);
GUIContent content = SELECTED_INDEX != -1 ? GetButtonContent(group) : GUIContent.none;
if (GUI.Button(rect, content, styles.buttonNoPadding))
{
// Note: Do not discard the parameters: userData and options, since they throw an error in 2019, if there are two of them
EditorUtility.DisplayCustomMenu(rect, TARGET_LIST, SELECTED_INDEX, (userData, options, selected) =>
{
if (selected != -1 && selected != SELECTED_INDEX)
SetBuildTargetTo(selected);
}, null);
}
}
public override float CalculateWidth()
{
return 40.0f;
}
private static void SetBuildTargetTo(int index)
{
if (index < 0)
return;
BuildTargetGroup group = GROUPS[index];
BuildTarget target = TARGETS[index];
if (!EditorUserBuildSettings.SwitchActiveBuildTarget(@group, target))
return;
IS_DIRTY = true;
SELECTED_INDEX = index;
}
private static void PopulateBuildTargetList()
{
var hashes = new List<int>();
var groups = new List<BuildTargetGroup>();
var targets = new List<BuildTarget>();
var contentList = new List<GUIContent>();
Type type = typeof(BuildTarget);
Array values = Enum.GetValues(type);
for (var i = 0; i < values.Length; i++)
{
var target = (BuildTarget)values.GetValue(i);
BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);
if (target < 0 || !BuildPipeline.IsBuildTargetSupported(group, target))
continue;
if (!IsValid(type, target))
continue;
hashes.Add(GetHashCode(group, target));
groups.Add(group);
targets.Add(target);
contentList.Add(new GUIContent(ObjectNames.NicifyVariableName(target.ToString())));
}
HASHES = hashes.ToArray();
GROUPS = groups.ToArray();
TARGETS = targets.ToArray();
TARGET_LIST = contentList.ToArray();
}
private static bool IsValid(Type type, BuildTarget target)
{
MemberInfo[] members = type.GetMember(target.ToString(), BindingFlags.Public | BindingFlags.Static);
if (members.Length == 0)
return false;
for (var j = 0; j < members.Length; j++)
{
if (members[j].GetCustomAttribute<ObsoleteAttribute>() == null)
return true;
}
return false;
}
private static GUIContent GetButtonContent(BuildTargetGroup group)
{
var name = $"BuildSettings.{group}.Small";
if (group == BuildTargetGroup.WSA)
name = "BuildSettings.Metro.Small";
return EditorGUIUtility.IconContent(name);
}
private static int GetHashCode(BuildTargetGroup group, BuildTarget target)
{
return ((int)group << 16) + (int)target;
}
}
}