Skip to content
This repository was archived by the owner on Feb 11, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 115 additions & 46 deletions Editor/Dropdowns/TypeSelectDropdown.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Assembly = System.Reflection.Assembly;
using UAssembly = UnityEditor.Compilation.Assembly;

namespace Sabresaurus.Sidekick
{
Expand All @@ -30,80 +33,146 @@ public TypeSelectDropdown(AdvancedDropdownState state, Action<Type> onTypeSelect
onTypeSelected = onTypeSelectedCallback;
}

private static string GetGroupName(Assembly assembly)
private enum Location
{
Assets,
Packages,
Precompiled,
Dynamic
}

private struct Group
{
public readonly Location Location;
public readonly string Context;

public Group(Location location, string context = null)
{
Location = location;
Context = context;
}

public class Comparer : IEqualityComparer<Group>
{
public bool Equals(Group x, Group y)
{
return x.Location == y.Location && x.Context == y.Context;
}

public int GetHashCode(Group obj)
{
unchecked
{
return ((int)obj.Location * 397) ^ (obj.Context != null ? obj.Context.GetHashCode() : 0);
}
}
}
}

private static Group GetGroup(Assembly assembly, Dictionary<string, UAssembly> nameToAssembly)
{
if (assembly.IsDynamic)
return new Group(Location.Dynamic);

string assemblyName = assembly.GetName().Name;

if (assemblyName == "UnityEngine" || assemblyName.StartsWith("UnityEngine.") ||
assemblyName == "UnityEditor" || assemblyName.StartsWith("UnityEditor.") ||
assemblyName == "Unity" || assemblyName.StartsWith("Unity.") ||
assemblyName == "ExCSS.Unity" ||
assemblyName.StartsWith("JetBrains.Rider.Unity") ||
assemblyName == "nunit.framework")
// Compiled
if (nameToAssembly.TryGetValue(assemblyName, out UAssembly uAssembly))
{
return "Unity";
// Package Group
if (uAssembly.sourceFiles.Length > 0)
{
string firstFile = uAssembly.sourceFiles[0];
if (firstFile.StartsWith("Packages"))
{
const int startIndex = 9; // "Packages/".Length

// Special case to reduce substrings
const string unityPackagePrefix = "com.unity";
if (firstFile.IndexOf(unityPackagePrefix, startIndex, unityPackagePrefix.Length, StringComparison.Ordinal) == startIndex)
return new Group(Location.Packages, "Unity");

return new Group(Location.Packages, GetPackageOwner(firstFile, startIndex));
}
}

return new Group(Location.Assets);
}

if (assemblyName == "System" || assemblyName.StartsWith("System.") ||
assemblyName == "netstandard" ||
assemblyName == "mscorlib" ||
assemblyName.StartsWith("Mono."))
// Precompiled
string location = assembly.Location;
if (!string.IsNullOrEmpty(location))
{
return "System";
location = location.Replace('\\', '/');
int packageCacheIndex = location.IndexOf("/Library/PackageCache/", StringComparison.Ordinal);
if (packageCacheIndex >= 0)
{
int startIndex = packageCacheIndex + 22; // + "/Library/PackageCache/".Length
return new Group(Location.Packages, GetPackageOwner(location, startIndex));
}

if (location.Contains("/Data/MonoBleedingEdge/"))
return new Group(Location.Precompiled, "System");

if (location.Contains("/Library/ScriptAssemblies"))
return new Group(Location.Assets);

return new Group(Location.Precompiled, "Unity");
}

return null;
return new Group(Location.Dynamic);

string GetPackageOwner(string path, int startIndex)
{
int startPackageOwner = path.IndexOf('.', startIndex) + 1;
int endPackageOwner = path.IndexOf('.', startPackageOwner);
string packageOwner = path.Substring(startPackageOwner, endPackageOwner - startPackageOwner);
return ObjectNames.NicifyVariableName(packageOwner);
}
}

protected override AdvancedDropdownItem BuildRoot()
{
AdvancedDropdownItem root = new AdvancedDropdownItem("Assemblies");

Dictionary<string, AdvancedDropdownItem> groupDropdowns = new Dictionary<string, AdvancedDropdownItem>();
List<AdvancedDropdownItem> ungroupedAssemblyDropdowns = new List<AdvancedDropdownItem>();
Dictionary<Group, AdvancedDropdownItem> groupDropdowns = new Dictionary<Group, AdvancedDropdownItem>(new Group.Comparer());

var allAssemblies = AppDomain.CurrentDomain.GetAssemblies().OrderBy(assembly => assembly.FullName);
// Populate Unity-compiled assemblies.
// This includes assemblies in the Assets and Packages directories that are not plugins.
UAssembly[] assemblies = CompilationPipeline.GetAssemblies();
Dictionary<string, UAssembly> nameToAssembly = new Dictionary<string, UAssembly>();
foreach (UAssembly assembly in assemblies)
nameToAssembly.Add(assembly.name, assembly);

// Append root locations
foreach (Location location in Enum.GetValues(typeof(Location)))
{
var locationRoot = new AdvancedDropdownItem(location.ToString());
root.AddChild(locationRoot);
groupDropdowns.Add(new Group(location), locationRoot);
}

foreach (Assembly assembly in allAssemblies)
{
var groupName = GetGroupName(assembly);
string assemblyName = assembly.GetName().Name;

var assemblyDropdownItem = new AdvancedDropdownItem(assemblyName);
var group = GetGroup(assembly, nameToAssembly);

if (groupName != null)
if (!groupDropdowns.TryGetValue(group, out AdvancedDropdownItem groupRoot))
{
if (!groupDropdowns.ContainsKey(groupName))
{
groupDropdowns[groupName] = new AdvancedDropdownItem(groupName);
}

groupDropdowns[groupName].AddChild(assemblyDropdownItem);
}
else
{
ungroupedAssemblyDropdowns.Add(assemblyDropdownItem);
groupDropdowns.Add(group, groupRoot = new AdvancedDropdownItem(group.Context));
groupDropdowns[new Group(group.Location)].AddChild(groupRoot);
}

Type[] types = assembly.GetTypes();
string assemblyName = assembly.GetName().Name;
var assemblyDropdownItem = new AdvancedDropdownItem(assemblyName);
groupRoot.AddChild(assemblyDropdownItem);

Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
assemblyDropdownItem.AddChild(new TypeDropdownItem(type));
}
}

foreach (var advancedDropdownItem in groupDropdowns)
{
root.AddChild(advancedDropdownItem.Value);
}

root.AddSeparator();

foreach (var ungroupedAssemblyDropdown in ungroupedAssemblyDropdowns)
{
root.AddChild(ungroupedAssemblyDropdown);
}

return root;
}

Expand Down
1 change: 1 addition & 0 deletions Editor/Panes/PropertyPane.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public void DrawProperties(Type componentType, object component, string searchTe
bool isObsoleteWithError = AttributeHelper.IsObsoleteWithError(attributes);

if(getMethod != null
&& component != null
&& !isObsoleteWithError
&& !(componentType == typeof(MeshFilter) && property.Name == "mesh") )
{
Expand Down