Search Unity

[Script] Preview main component in hierarchy and active state toggle

Discussion in 'Immediate Mode GUI (IMGUI)' started by Rodolfo-Rubens, May 6, 2017.

  1. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,197
    Hey guys,
    I made a simple script that shows the icon of the first component (after transform of course) of the gameobject in hierarchy and also show a toggle to toggle the active state of the object.


    It can also show custom component icons, you just need to put them in Assets/Editor/Icons.


    Also, it has some "smart" icon showing that shows differently depending if the object has components or not and if it has childs or not, if it's a prefab or not too:


    Plus:
    - Mass deactivate/activate gameobject and its children by holding alt and clicking on its toggle.
    ps.: The children will inherit the toggled object's active state, IT WILL NOT TOGGLE THE CHILD ACTIVE STATE.
    - Choose to only show specific component types and etc.
    - If custom component type was added to the specific component types and there is no icon for it, it will show a gameobject icon

    Here is the code:
    Code (csharp):
    1.  
    2. // Main Component Icon, Active State Toggling and "Smart Empty Object Icon Display"
    3. using UnityEditor;
    4. using UnityEngine;
    5. using System;
    6. using System.Collections.Generic;
    7.  
    8. [InitializeOnLoad]
    9. class MainComponentIcon
    10. {
    11.     // only show these types if showAllTypes is false
    12.     static Type[] componentTypes = new Type[]
    13.     {
    14.         typeof(Light),
    15.         typeof(BoxCollider),
    16.         typeof(Camera),
    17.         typeof(ParticleSystem),
    18.         typeof(TrailRenderer),
    19.         typeof(MeshRenderer),
    20.         typeof(MeshFilter),
    21.         typeof(SpriteRenderer),
    22.         typeof(AudioSource),
    23.         typeof(Canvas),
    24.         typeof(CanvasGroup),
    25.         typeof(UnityEngine.UI.Image),
    26.         typeof(UnityEngine.UI.Button),
    27.         typeof(UnityEngine.UI.Text),
    28.  
    29.         // must add the custom types here if showAllTypes is false
    30.         typeof(GameController),
    31.         typeof(PlayerController),
    32.         typeof(SpellScript)
    33.     };
    34.     static bool showActiveToggle = true;
    35.     static bool showIndentedActiveToggle = false;
    36.     static bool showAllTypes = true;
    37.     static bool useFallbackIconForExcludedComponents = false;
    38.     static bool prefabOverOthers = true; // don't show any component icon if the gameobject is a prefab, show the prefab icon instead
    39.     static bool alwaysShowCustom = false; // will show all custom, even if they don't have custom images (will show the little script page icon)
    40.     static bool alwaysShowPrefabContainer = true;
    41.     static IdleObjectsView showEmptyPrefabIconInIdleObjects = IdleObjectsView.TransformIcon; // // gameobjects with no child or components
    42.     static FallbackIcon fallbackIcon = FallbackIcon.GameObjectOrTransformsOrPrefab;
    43.  
    44.     // UI exceptions
    45.     static bool canvasOverPrefab = true;
    46.  
    47.     static List<GameObject> allChildGOsForToggle;
    48.     static bool toggleActiveAllChildInheritToggleObject = true; // Attention: if hold alt and clickin on object toggle, it will set all childs active state to the same of the clicked object
    49.  
    50.     static MainComponentIcon()
    51.     {
    52.         // Init
    53.         EditorApplication.hierarchyWindowItemOnGUI += HierarchyItemCB;
    54.     }
    55.  
    56.     static void HierarchyItemCB(int instanceID, Rect selectionRect)
    57.     {
    58.         GameObject obj = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
    59.  
    60.         if (obj)
    61.         {
    62.             Rect r = new Rect(selectionRect);
    63.             if (showActiveToggle)
    64.             {
    65.                 // Toggle active button
    66.                 r.x = showIndentedActiveToggle ? selectionRect.x - 28 : 2;
    67.                 r.width = 18;
    68.                 r.height = 16;
    69.  
    70.                 EditorGUI.BeginChangeCheck();
    71.  
    72.                 var toggleValue = GUI.Toggle(r, obj.activeSelf, "");
    73.  
    74.                 if (toggleActiveAllChildInheritToggleObject && Event.current.alt)
    75.                 {
    76.                     if (EditorGUI.EndChangeCheck())
    77.                     {
    78.                         if (allChildGOsForToggle == null) allChildGOsForToggle = new List<GameObject>();
    79.                         allChildGOsForToggle.Clear();
    80.                         allChildGOsForToggle.Add(obj);
    81.                         FetchAllChildGameObjects(obj.transform);
    82.                         Undo.RecordObjects(allChildGOsForToggle.ToArray(), "Toggle GameObject Active");
    83.                         allChildGOsForToggle.ForEach(child => child.SetActive(toggleValue));
    84.                     }
    85.                 }
    86.                 else if (EditorGUI.EndChangeCheck())
    87.                 {
    88.                     obj.SetActive(toggleValue);
    89.                     Undo.RecordObject(obj, "Toggle " + obj.name + " Active");
    90.                 }
    91.             }
    92.  
    93.             // Icon
    94.             r.x = EditorGUIUtility.currentViewWidth - 38;
    95.             r.width = 18;
    96.             r.height = 18;
    97.             var backupColor = GUI.color;
    98.             if (!obj.activeSelf) GUI.color = new Color(GUI.color.r, GUI.color.g, GUI.color.b, 0.5f);
    99.             var components = obj.GetComponents<Component>();
    100.             if (components != null)
    101.             {
    102.                 // FIRST COMPONENT IS ALWAYS TRANSFORM OR RECT TRASNFORM
    103.                 if (components.Length > 1)
    104.                 {
    105.                     // HAS COMPONENTS
    106.                     Type type = components[1].GetType();
    107.                     Texture image = EditorGUIUtility.ObjectContent(null, type).image;
    108.                     bool isInComponentTypesList = Array.Exists(componentTypes, x => x == type);
    109.  
    110.                     if (image == null)
    111.                     {
    112.                         // put your custom components icons in Assets/Editor/Icons, name it the same name of your class and change the extension below as accordingly
    113.                         image = AssetDatabase.LoadAssetAtPath("Assets/Editor/Icons/" + type.ToString() + ".psd", typeof(Texture)) as Texture;
    114.                     }
    115.  
    116.                     if (canvasOverPrefab && type == typeof(Canvas))
    117.                     {
    118.                         GUI.Label(r, EditorGUIUtility.IconContent("Canvas Icon"));
    119.                     }
    120.                     else if (prefabOverOthers && CanShowAsPrefab(obj))
    121.                     {
    122.                         ShowFallbackIcon(obj, r);
    123.                     }
    124.                     else if (!image && alwaysShowCustom)
    125.                     {
    126.                         GUI.Label(r, EditorGUIUtility.IconContent("cs Script Icon"));
    127.                     }
    128.                     else if (showAllTypes || isInComponentTypesList)
    129.                     {
    130.                         if (image)
    131.                         {
    132.                             GUI.Label(r, image);
    133.                         }
    134.                         else
    135.                         {
    136.                             ShowFallbackIcon(obj, r);
    137.                         }
    138.                     }
    139.                     else if (image && useFallbackIconForExcludedComponents || alwaysShowPrefabContainer && CanShowAsPrefab(obj))
    140.                     {
    141.                         ShowFallbackIcon(obj, r);
    142.                     }
    143.                 }
    144.                 else
    145.                 {
    146.                     // IDLE OBJECTS
    147.                     if (obj.transform.childCount == 0)
    148.                     {
    149.                         if (CanShowAsPrefab(obj))
    150.                             GUI.Label(r, EditorGUIUtility.IconContent("PrefabNormal Icon"));
    151.                         else if (showEmptyPrefabIconInIdleObjects == IdleObjectsView.WhitePrefabIcon) // no child nor components
    152.                             GUI.Label(r, EditorGUIUtility.IconContent("Prefab Icon"));
    153.                         else if (showEmptyPrefabIconInIdleObjects == IdleObjectsView.TransformIcon) // no child nor components
    154.                         {
    155.                             if (obj.GetComponent<RectTransform>())
    156.                                 GUI.Label(r, EditorGUIUtility.IconContent("RectTransform Icon"));
    157.                             else
    158.                                 GUI.Label(r, EditorGUIUtility.IconContent("Transform Icon"));
    159.                         }
    160.                     }
    161.                     // NO COMPONENTS BUT HAS CHILDREN
    162.                     else if (obj.transform.childCount > 0)
    163.                     {
    164.                         if (CanShowAsPrefab(obj))
    165.                             GUI.Label(r, EditorGUIUtility.IconContent("PrefabNormal Icon"));
    166.                         else
    167.                             GUI.Label(r, EditorGUIUtility.IconContent("Prefab Icon"));
    168.  
    169.                         GUI.Label(r, EditorGUIUtility.IconContent("Transform Icon"));
    170.                     }
    171.  
    172.                 }
    173.             }
    174.  
    175.             GUI.color = backupColor;
    176.         }
    177.     }
    178.  
    179.     static void ShowFallbackIcon(GameObject obj, Rect r)
    180.     {
    181.         switch (fallbackIcon)
    182.         {
    183.             case FallbackIcon.TransformOrRect:
    184.  
    185.                 if (obj.GetComponent<RectTransform>())
    186.                     GUI.Label(r, EditorGUIUtility.IconContent("RectTransform Icon"));
    187.                 else
    188.                     GUI.Label(r, EditorGUIUtility.IconContent("Transform Icon"));
    189.                 break;
    190.  
    191.             case FallbackIcon.GameObjectOrPrefab:
    192.                 if (CanShowAsPrefab(obj))
    193.                     GUI.Label(r, EditorGUIUtility.IconContent("PrefabNormal Icon"));
    194.                 else
    195.                     GUI.Label(r, EditorGUIUtility.IconContent("GameObject Icon"));
    196.                 break;
    197.  
    198.             case FallbackIcon.GameObjectOrTransformsOrPrefab:
    199.                 if (CanShowAsPrefab(obj))
    200.                     GUI.Label(r, EditorGUIUtility.IconContent("PrefabNormal Icon"));
    201.                 else
    202.                 {
    203.                     if (obj.GetComponents<Component>().Length > 1)
    204.                     {
    205.                         GUI.Label(r, EditorGUIUtility.IconContent("GameObject Icon"));
    206.                     }
    207.                     else
    208.                     {
    209.                         GUI.Label(r, EditorGUIUtility.IconContent("Transform Icon"));
    210.                     }
    211.                 }
    212.                 break;
    213.         }
    214.     }
    215.  
    216.     static bool IsPartOfPrefab(GameObject prefab)
    217.     {
    218.         return PrefabUtility.GetPrefabParent(prefab) != null;
    219.     }
    220.  
    221.     static bool IsPrefabParent(GameObject prefab)
    222.     {
    223.         return PrefabUtility.FindPrefabRoot(prefab) == prefab;
    224.     }
    225.  
    226.     static bool CanShowAsPrefab(GameObject prefab)
    227.     {
    228.         if (IsPrefabParent(prefab) &&
    229.             IsPartOfPrefab(prefab) &&
    230.             PrefabUtility.GetPrefabType(prefab) == PrefabType.PrefabInstance ||
    231.             PrefabUtility.GetPrefabType(prefab) == PrefabType.ModelPrefabInstance)
    232.         {
    233.             return true;
    234.         }
    235.  
    236.         return false;
    237.     }
    238.  
    239.     public static void FetchAllChildGameObjects(Transform transform)
    240.     {
    241.         if (allChildGOsForToggle == null) allChildGOsForToggle = new List<GameObject>();
    242.         foreach (Transform t in transform)
    243.         {
    244.             if (!allChildGOsForToggle.Contains(t.gameObject)) allChildGOsForToggle.Add(t.gameObject);
    245.             FetchAllChildGameObjects(t);
    246.         }
    247.     }
    248.  
    249.     //static bool
    250. }
    251.  
    252. enum FallbackIcon
    253. {
    254.     None,
    255.     GameObjectOrTransformsOrPrefab,
    256.     GameObjectOrPrefab,
    257.     TransformOrRect
    258. }
    259.  
    260. enum IdleObjectsView
    261. {
    262.     None,
    263.     TransformIcon,
    264.     WhitePrefabIcon
    265. }
    266.  

    Thanks:
    http://answers.unity3d.com/questions/431952/how-to-show-an-icon-in-hierarchy-view.html
    http://answers.unity3d.com/questions/661783/custom-inspector-access-built-in-component-icons.html
    http://answers.unity3d.com/questions/218429/how-to-know-if-a-gameobject-is-a-prefab.html
    https://gist.github.com/MattRix/c1f7840ae2419d8eb2ec0695448d4321
     
    Last edited: May 7, 2017
    my_little_kafka likes this.