Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Hiding ReorderableList Items With Boolean Toggle

Discussion in 'Scripting' started by JustThisGuy, Jan 11, 2022.

  1. JustThisGuy

    JustThisGuy

    Joined:
    Mar 12, 2014
    Posts:
    7
    Hi all!

    I'm trying to hide certain ReorderableList items based on the state of a boolean toggle. What I'm currently getting is a blank item instead of no item at all. No items hidden:
    2022-01-11 15_47_47-Items - Initial State.png

    Hiding Item 1 (toggle clicked):
    2022-01-11 15_51_48-Items - Item 1 Hidden.png

    Here's the code:

    Items.cs
    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenu(fileName = "Items", menuName = "Items")]
    6. public class Items : ScriptableObject
    7. {
    8.   public List<Item> itemList = new List<Item>();
    9. }
    10.  
    11. [Serializable]
    12. public class Item
    13. {
    14.   public bool isHidden = false;
    15.   public string description;
    16. }
    Editor/ItemsEditorWindow.cs
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5. using UnityEditorInternal;
    6.  
    7. public class ItemsEditorWindow : EditorWindow
    8. {
    9.   private SerializedObject itemsSerializedObject;
    10.   private SerializedProperty itemList;
    11.   private ReorderableList reorderableItemList;
    12.  
    13.   [MenuItem("Tools/Items Editor Window")]
    14.   private static void OpenWindow()
    15.   {
    16.     GetWindow<ItemsEditorWindow>("Items");
    17.   }
    18.  
    19.   private void OnEnable()
    20.   {
    21.     string[] itemsGUIDS = AssetDatabase.FindAssets("t:Items");
    22.  
    23.     if (itemsGUIDS.Length == 0) return;
    24.  
    25.     string path = AssetDatabase.GUIDToAssetPath(itemsGUIDS[0]);
    26.     var itemList = AssetDatabase.LoadAssetAtPath<Items>(path);
    27.  
    28.     this.itemsSerializedObject = new SerializedObject(itemList);
    29.  
    30.     InitializeItemList();
    31.   }
    32.  
    33.   private void InitializeItemList()
    34.   {
    35.     this.itemList = this.itemsSerializedObject.FindProperty("itemList");
    36.  
    37.     this.reorderableItemList =
    38.       new ReorderableList(
    39.         this.itemsSerializedObject,
    40.         this.itemList,
    41.         draggable: true,
    42.         displayHeader: true,
    43.         displayAddButton: true,
    44.         displayRemoveButton: true
    45.       );
    46.  
    47.     this.reorderableItemList.drawElementCallback = DrawTaskListItem;
    48.   }
    49.  
    50.   public void OnGUI()
    51.   {
    52.     this.itemsSerializedObject.Update();
    53.  
    54.     this.reorderableItemList.DoLayoutList();
    55.  
    56.     this.itemsSerializedObject.ApplyModifiedProperties();
    57.   }
    58.  
    59.   private void DrawTaskListItem(Rect rect, int index, bool isActive, bool isFocused)
    60.   {
    61.     SerializedProperty item = this.reorderableItemList.serializedProperty.GetArrayElementAtIndex(index);
    62.  
    63.     SerializedProperty isHidden = item.FindPropertyRelative("isHidden");
    64.     SerializedProperty description = item.FindPropertyRelative("description");
    65.  
    66.     if (isHidden.boolValue) return;
    67.  
    68.     float x = rect.x;
    69.     float y = rect.y;
    70.  
    71.     y += EditorGUIUtility.standardVerticalSpacing;
    72.  
    73.     EditorGUI.PropertyField(
    74.       new Rect(x, y, 17f, EditorGUIUtility.singleLineHeight),
    75.       isHidden,
    76.       GUIContent.none
    77.     );
    78.  
    79.     x += 17f;
    80.  
    81.     EditorGUI.PropertyField(
    82.       new Rect(x, y, 100f, EditorGUIUtility.singleLineHeight),
    83.       description,
    84.       GUIContent.none
    85.     );
    86.   }
    87. }
    The code that attempts to do the hiding is
    if (isHidden.boolValue) return;
    in
    DrawTaskListItem
    . Since this doesn't work, I was wondering if someone can tell me the correct way to do this. Thanks!
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    You'll need to adjust the rect based on the amount of elements preceding the current one that are considered hidden.
     
  3. JustThisGuy

    JustThisGuy

    Joined:
    Mar 12, 2014
    Posts:
    7
    Can you clarify which rect you're talking about?
     
  4. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    The drawing rect in DrawTaskItemList. You need to adjust the rect.y by the number of previous entries that are hidden multiplied by the height of a line, so it draws in the right place.

    You might also need to adjust the total size of the rect being drawn somehow, so there isn't extra a bunch of extra space at the bottom, but I'm not sure how that works with a ReorderableLis as I've never used it personally. Hell, there could be some sort of callback built in to determine if it should draw an entry at all that you could use instead.
     
  5. JustThisGuy

    JustThisGuy

    Joined:
    Mar 12, 2014
    Posts:
    7
    I tried changing the value of rect.y, but no matter what I change it to, it has no effect. Unfortunately, it appears that ReorderableList is undocumented, and I have not been able to find a callback that prevents the drawing of an item.
     
  6. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    That's odd. It should definitely have an effect. Post your code?
     
  7. JustThisGuy

    JustThisGuy

    Joined:
    Mar 12, 2014
    Posts:
    7
    Code (CSharp):
    1. private void DrawTaskListItem(Rect rect, int index, bool isActive, bool isFocused)
    2.   {
    3.     SerializedProperty item = this.reorderableItemList.serializedProperty.GetArrayElementAtIndex(index);
    4.  
    5.     SerializedProperty isHidden = item.FindPropertyRelative("isHidden");
    6.     SerializedProperty description = item.FindPropertyRelative("description");
    7.  
    8.     if (isHidden.boolValue) rect.y = 0;
    9.     if (isHidden.boolValue) return;
    10.  
    11.     float x = rect.x;
    12.     float y = rect.y;
    13.  
    14.     y += EditorGUIUtility.standardVerticalSpacing;
    15.  
    16.     EditorGUI.PropertyField(
    17.       new Rect(x, y, 17f, EditorGUIUtility.singleLineHeight),
    18.       isHidden,
    19.       GUIContent.none
    20.     );
    21.  
    22.     x += 17f;
    23.  
    24.     EditorGUI.PropertyField(
    25.       new Rect(x, y, 100f, EditorGUIUtility.singleLineHeight),
    26.       description,
    27.       GUIContent.none
    28.     );
    29.   }
    The
    if (isHidden.boolValue) rect.y = 0;
    line is the only thing that changed.
     
  8. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    That's not quite what I meant. You need to adjust the rect of the entries that are being drawn to account for the previous entries that aren't being drawn and move their rect up.
     
  9. JustThisGuy

    JustThisGuy

    Joined:
    Mar 12, 2014
    Posts:
    7
    Rather than try to hide the ReorderableList items, I ended up moving the items to another list to "hide" them, and moving them back to "show" them. It's not the solution I was hoping for, but it works. More information here: https://stackoverflow.com/questions...t-items-with-boolean-toggle/70838789#70838789