using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.VFX; using UnityEditor; using GameplayIngredients.StateMachines; using UnityEngine.Playables; using System.Linq; using System.Reflection; using GameplayIngredients.Comments; namespace GameplayIngredients.Editor { [InitializeOnLoad] public static class AdvancedHierarchyView { const string kMenuPath = "Edit/Advanced Hierarchy View %."; public const int kMenuPriority = 230; [MenuItem(kMenuPath, priority = kMenuPriority, validate = false)] static void Toggle() { if (Active) Active = false; else Active = true; } [MenuItem(kMenuPath, priority = kMenuPriority, validate = true)] static bool ToggleCheck() { Menu.SetChecked(kMenuPath, Active); return SceneView.sceneViews.Count > 0; } static readonly string kPreferenceName = "GameplayIngredients.HierarchyHints"; public static bool Active { get { return EditorPrefs.GetBool(kPreferenceName, false); } set { EditorPrefs.SetBool(kPreferenceName, value); UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); } } static AdvancedHierarchyView() { EditorApplication.hierarchyWindowItemOnGUI -= HierarchyOnGUI; EditorApplication.hierarchyWindowItemOnGUI += HierarchyOnGUI; InitializeTypes(); } static void InitializeTypes() { RegisterComponentType( typeof(MonoBehaviour), "cs Script Icon"); RegisterComponentType( typeof(Camera), "Camera Icon"); RegisterComponentType( typeof(MeshRenderer), "MeshRenderer Icon"); RegisterComponentType( typeof(SkinnedMeshRenderer), "SkinnedMeshRenderer Icon"); RegisterComponentType( typeof(BoxCollider), "BoxCollider Icon"); RegisterComponentType( typeof(SphereCollider), "SphereCollider Icon"); RegisterComponentType( typeof(CapsuleCollider), "CapsuleCollider Icon"); RegisterComponentType( typeof(MeshCollider), "MeshCollider Icon"); RegisterComponentType( typeof(AudioSource), "AudioSource Icon"); RegisterComponentType( typeof(Animation), "Animation Icon"); RegisterComponentType( typeof(Animator), "Animator Icon"); RegisterComponentType( typeof(PlayableDirector), "PlayableDirector Icon"); RegisterComponentType( typeof(Light), "Light Icon"); RegisterComponentType( typeof(LightProbeGroup), "LightProbeGroup Icon"); RegisterComponentType( typeof(LightProbeProxyVolume), "LightProbeProxyVolume Icon"); RegisterComponentType( typeof(ReflectionProbe), "ReflectionProbe Icon"); RegisterComponentType( typeof(VisualEffect), "VisualEffect Icon"); RegisterComponentType( typeof(ParticleSystem), "ParticleSystem Icon"); RegisterComponentType( typeof(Canvas), "Canvas Icon"); RegisterComponentType( typeof(Image), "Image Icon"); RegisterComponentType( typeof(Text), "Text Icon"); RegisterComponentType( typeof(Button), "Button Icon"); RegisterComponentType( typeof(Folder), "Folder Icon"); RegisterComponentType( typeof(SceneComment), "Packages/net.peeweek.gameplay-ingredients/Icons/Misc/ic-comment.png"); foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { var types = assembly.GetTypes(); foreach(var type in types) { if(type.IsSubclassOf(typeof(MonoBehaviour)) && !type.IsAbstract) { var attrib = type.GetCustomAttribute(); if(attrib != null) { RegisterComponentType(type, attrib.icon); } } } } catch { Debug.LogWarning("Could not load types from assembly:" + assembly.FullName); } } } public static void RegisterComponentType(Type t, string iconName) { if (s_Definitions == null) s_Definitions = new Dictionary(); if (!s_Definitions.ContainsKey(t)) s_Definitions.Add(t, iconName); } public static IEnumerable allTypes { get { return s_Definitions.Keys; } } static Dictionary s_Definitions = new Dictionary(); static void HierarchyOnGUI(int instanceID, Rect selectionRect) { if (!Active) return; var fullRect = selectionRect; fullRect.xMin = 32; fullRect.xMax = EditorGUIUtility.currentViewWidth; GameObject o = EditorUtility.InstanceIDToObject(instanceID) as GameObject; if (o == null) return; var c = GUI.color; bool isFolder = o.GetComponent() != null; bool isComment = o.GetComponent() != null; if(isFolder || isComment) { fullRect.xMin += 28 + 14 * GetObjectDepth(o.transform); fullRect.width = 16; EditorGUI.DrawRect(fullRect, EditorGUIUtility.isProSkin? Styles.proBackground : Styles.personalBackground); if (isFolder) DrawIcon(fullRect, Contents.GetContent(typeof(Folder)), o.GetComponent().Color); else DrawIcon(fullRect, Contents.GetContent(typeof(SceneComment)), Color.white); } else { if (o.isStatic && AdvancedHierarchyPreferences.showStatic) { GUI.Label(fullRect, " S"); EditorGUI.DrawRect(fullRect, Colors.dimGray); } foreach (var type in s_Definitions.Keys) { if(AdvancedHierarchyPreferences.IsVisible(type) && o.GetComponents(type).Length > 0) selectionRect = DrawIcon(selectionRect, Contents.GetContent(type), Color.white); } } GUI.color = c; } static int GetObjectDepth(Transform t, int depth=0) { if (t.parent == null) return depth; else return GetObjectDepth(t.parent, depth + 1); } static Rect DrawIcon(Rect rect, GUIContent content, Color color, int size = 16) { GUI.color = color; GUI.Label(rect, content, Styles.icon); rect.width = rect.width - size; return rect; } static class Contents { static Dictionary s_Icons = new Dictionary(); public static void AddIcon(Type type, string IconName) { GUIContent icon; Texture texture = AssetDatabase.LoadAssetAtPath(IconName); if (texture == null) icon = EditorGUIUtility.IconContent(IconName); else icon = new GUIContent(texture); s_Icons.Add(type, icon); } public static GUIContent GetContent(Type t) { if (!s_Icons.ContainsKey(t) && s_Definitions.ContainsKey(t)) AddIcon(t,s_Definitions[t]); return s_Icons[t]; } } static class Colors { public static Color orange = new Color(1.0f, 0.7f, 0.1f); public static Color red = new Color(1.0f, 0.4f, 0.3f); public static Color yellow = new Color(0.8f, 1.0f, 0.1f); public static Color green = new Color(0.2f, 1.0f, 0.1f); public static Color blue = new Color(0.5f, 0.8f, 1.0f); public static Color violet = new Color(0.8f, 0.5f, 1.0f); public static Color purple = new Color(1.0f, 0.5f, 0.8f); public static Color dimGray = new Color(0.4f, 0.4f, 0.4f, 0.2f); } static class Styles { public static GUIStyle rightLabel; public static GUIStyle icon; public static Color proBackground = new Color(0.25f, 0.25f, 0.25f, 1.0f); public static Color personalBackground = new Color(0.75f, 0.75f, 0.75f, 1.0f); static Styles() { rightLabel = new GUIStyle(EditorStyles.label); rightLabel.alignment = TextAnchor.MiddleRight; rightLabel.normal.textColor = Color.white; rightLabel.onNormal.textColor = Color.white; rightLabel.active.textColor = Color.white; rightLabel.onActive.textColor = Color.white; icon = new GUIStyle(rightLabel); icon.padding = new RectOffset(); icon.margin = new RectOffset(); } } } }