Search Unity

  1. Calling all beginners! Join the FPS Beginners Mods Challenge until December 13.
    Dismiss Notice
  2. It's Cyber Week at the Asset Store!
    Dismiss Notice

Expand/Collapse all components in a Gameobject. (Refresh issue)

Discussion in 'Editor & General Support' started by Adrien-Gannerie, Feb 16, 2018.

  1. Adrien-Gannerie

    Adrien-Gannerie

    Joined:
    Feb 18, 2015
    Posts:
    6
    Hi,

    I'm trying to create a tools which expand/collapse all components on a gameobject with a button in the context menu.

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using UnityEditorInternal;
    4.  
    5. public static class ComponentTools
    6. {
    7.     [MenuItem("CONTEXT/Component/Collapse All")]
    8.     public static void CollapseAll(MenuCommand command)
    9.     {
    10.         GameObject gameObject = (command.context as Component).gameObject;
    11.         Component[] components = gameObject.GetComponents<Component>();
    12.         foreach (Component component in components)
    13.         {    
    14.             InternalEditorUtility.SetIsInspectorExpanded(component, false);
    15.         }
    16.         // Refresh inspector.
    17.     }
    18.  
    19.     [MenuItem("CONTEXT/Component/Expand All")]
    20.     public static void ExpandAll(MenuCommand command)
    21.     {
    22.         GameObject gameObject = (command.context as Component).gameObject;
    23.         Component[] components = gameObject.GetComponents<Component>();
    24.         foreach (Component component in components)
    25.         {
    26.             InternalEditorUtility.SetIsInspectorExpanded(component, true);
    27.         }
    28.         // Resfresh inspector.
    29.     }
    30. }
    That code works but i need to reselect the gameobject to refresh the inspector window.

    What is the right method to refresh/repaint/redraw the inspector window without reselecting the gameobject ?


    Thanks for your help.

    Best regards.

    Adrien Gannerie
     
    Last edited: Feb 16, 2018
  2. Adrien-Gannerie

    Adrien-Gannerie

    Joined:
    Feb 18, 2015
    Posts:
    6
  3. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    3,568
  4. Adrien-Gannerie

    Adrien-Gannerie

    Joined:
    Feb 18, 2015
    Posts:
    6
    Thank you very much for your help and sorry to bother you by private message.

    If I understood correctly your answer I must find the editor of each component and force a repaint?

    Best regards.
     
  5. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    3,568
    Yes give that a try and see how it goes.
     
  6. Adrien-Gannerie

    Adrien-Gannerie

    Joined:
    Feb 18, 2015
    Posts:
    6
    Thanks for your help. I tried this but this change nothing.

    Code (CSharp):
    1.  
    2. using UnityEditor;
    3. using UnityEngine;
    4. using UnityEditorInternal;
    5.  
    6. public static class ComponentTools
    7. {
    8.     [MenuItem("CONTEXT/Component/Collapse All")]
    9.     public static void CollapseAll(MenuCommand command)
    10.     {
    11.         GameObject gameObject = (command.context as Component).gameObject;
    12.         Component[] components = gameObject.GetComponents<Component>();
    13.         foreach (Component component in components)
    14.         {      
    15.             InternalEditorUtility.SetIsInspectorExpanded(component, false);
    16.             Editor editor = null;
    17.             Editor.CreateCachedEditor(component, null, ref editor);
    18.             editor.Repaint();
    19.         }
    20.     }
    21.  
    22.     [MenuItem("CONTEXT/Component/Expand All")]
    23.     public static void ExpandAll(MenuCommand command)
    24.     {
    25.         GameObject gameObject = (command.context as Component).gameObject;
    26.         Component[] components = gameObject.GetComponents<Component>();
    27.         foreach (Component component in components)
    28.         {
    29.             InternalEditorUtility.SetIsInspectorExpanded(component, true);
    30.             Editor editor = null;
    31.             Editor.CreateCachedEditor(component, null, ref editor);
    32.             editor.Repaint();
    33.         }
    34.     }
    35. }
    36.  
    Have you a other idea ?

    Best regards.
     
  7. shawn

    shawn

    Unity Technologies

    Joined:
    Aug 4, 2007
    Posts:
    551
    You could try InternalEditorUtility.RepaintAllViews(). It's undocumented, but will repaint everything. Unfortunately, there's no public API to repaint specifically inspector windows.
     
    nirvanajie likes this.
  8. FireMutant

    FireMutant

    Joined:
    Sep 2, 2013
    Posts:
    39
    I don't know if this has any bad side effects, but I found a solution to make the editor refresh from an example that uses a shortcut-key to lock/unlock the inspector. I modified the code below with what is working for me. There is a slight delay (1-2 seconds) before the refresh, but it does refresh and show all the components expanded/collapsed, and now that I've used it for a couple of days, this should absolutely be a standard feature in the inspector AND hierarchy! ;-)


    Code (CSharp):
    1.  
    2. using UnityEditor;
    3. using UnityEngine;
    4. using UnityEditorInternal;
    5.  
    6. public static class ComponentTools
    7. {
    8.     [MenuItem("CONTEXT/Component/Collapse All")]
    9.     public static void CollapseAll(MenuCommand command)
    10.     {
    11.         GameObject gameObject = (command.context as Component).gameObject;
    12.         Component[] components = gameObject.GetComponents<Component>();
    13.         foreach (Component component in components)
    14.         {    
    15.             InternalEditorUtility.SetIsInspectorExpanded(component, false);
    16.         }
    17.         ActiveEditorTracker.sharedTracker.ForceRebuild();
    18.     }
    19.  
    20.     [MenuItem("CONTEXT/Component/Expand All")]
    21.     public static void ExpandAll(MenuCommand command)
    22.     {
    23.         GameObject gameObject = (command.context as Component).gameObject;
    24.         Component[] components = gameObject.GetComponents<Component>();
    25.         foreach (Component component in components)
    26.         {
    27.             InternalEditorUtility.SetIsInspectorExpanded(component, true);
    28.         }
    29.         ActiveEditorTracker.sharedTracker.ForceRebuild();
    30.     }
    31. }
    32.  
     
    prakash_twg, Xarbrough, Th0re and 2 others like this.
  9. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,293
    Hey this script is super handy!
    I noticed though it doesn't collapse material components, do know why that would be? I'm thinking it might be because they aren't really regular components as such and just displayed to simplify things for the user.
    Might be a little tricky but does anyone know how to add them?
     
  10. villevli

    villevli

    Joined:
    Jan 19, 2016
    Posts:
    62
    This also collapses materials.
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using UnityEditorInternal;
    4.  
    5. public static class ComponentTools
    6. {
    7.     [MenuItem("CONTEXT/Component/Collapse All")]
    8.     private static void CollapseAll(MenuCommand command)
    9.     {
    10.         SetAllInspectorsExpanded((command.context as Component).gameObject, false);
    11.     }
    12.  
    13.     [MenuItem("CONTEXT/Component/Expand All")]
    14.     private static void ExpandAll(MenuCommand command)
    15.     {
    16.         SetAllInspectorsExpanded((command.context as Component).gameObject, true);
    17.     }
    18.  
    19.     public static void SetAllInspectorsExpanded(GameObject go, bool expanded)
    20.     {
    21.         Component[] components = go.GetComponents<Component>();
    22.         foreach (Component component in components)
    23.         {
    24.             if (component is Renderer)
    25.             {
    26.                 var mats = ((Renderer)component).sharedMaterials;
    27.                 for (int i = 0; i < mats.Length; ++i)
    28.                 {
    29.                     InternalEditorUtility.SetIsInspectorExpanded(mats[i], expanded);
    30.                 }
    31.             }
    32.             InternalEditorUtility.SetIsInspectorExpanded(component, expanded);
    33.         }
    34.         ActiveEditorTracker.sharedTracker.ForceRebuild();
    35.     }
    36. }
    37.  
     
  11. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,293
  12. IsntCo

    IsntCo

    Joined:
    Apr 12, 2014
    Posts:
    141
    Nice script! I was looking for something like this.
    It seems like it doesn't refresh though?
    So after you Collapse All, you have to reselect the object to see the changes?
     
  13. FireMutant

    FireMutant

    Joined:
    Sep 2, 2013
    Posts:
    39
    Appminis,

    It should refresh automatically (Unity 2017.4.10f1), however, if you have more than 1 inspector window open, it may be expanding/collapsing the other inspector window(s). I don't know why it does not do all of the open inspector windows, or the selected inspector window, but it does not. I have not been able to find a work-around or how to determine which inspector window is considered the "Active" one to the sharedTracker.
     
  14. giantkilleroverunity3d

    giantkilleroverunity3d

    Joined:
    Feb 28, 2014
    Posts:
    85
    I put this ComponentTools.cs in my 2018.3.8f1 editor folder and it does not appear in menu after Unity restart. I had to put it under and exitsting Tools menu itme then it showed up. But then I received:
    NullReferenceException: Object reference not set to an instance of an object
    ComponentTools.CollapseAll (UnityEditor.MenuCommand command) (at Assets/Editor/ComponentTools.cs:10)

    with a heirarchy item selected.
     
    Last edited: Jun 12, 2019