Search code examples
c#unity-game-engineunity-editorunity3d-editor

Hiding ReorderableList Items With Boolean Toggle


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:

No items hidden

Hiding Item 1 (toggle clicked):

enter image description here

Here's the code:

Items.cs

using System;
using System.Collections.Generic;
using UnityEngine;
 
[CreateAssetMenu(fileName = "Items", menuName = "Items")]
public class Items : ScriptableObject
{
  public List<Item> itemList = new List<Item>();
}
 
[Serializable]
public class Item
{
  public bool isHidden = false;
  public string description;
}

Editor/ItemsEditorWindow.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
 
public class ItemsEditorWindow : EditorWindow
{
  private SerializedObject itemsSerializedObject;
  private SerializedProperty itemList;
  private ReorderableList reorderableItemList;
 
  [MenuItem("Tools/Items Editor Window")]
  private static void OpenWindow()
  {
    GetWindow<ItemsEditorWindow>("Items");
  }
 
  private void OnEnable()
  {
    string[] itemsGUIDS = AssetDatabase.FindAssets("t:Items");
 
    if (itemsGUIDS.Length == 0) return;
 
    string path = AssetDatabase.GUIDToAssetPath(itemsGUIDS[0]);
    var itemList = AssetDatabase.LoadAssetAtPath<Items>(path);
 
    this.itemsSerializedObject = new SerializedObject(itemList);
 
    InitializeItemList();
  }
 
  private void InitializeItemList()
  {
    this.itemList = this.itemsSerializedObject.FindProperty("itemList");
 
    this.reorderableItemList =
      new ReorderableList(
        this.itemsSerializedObject,
        this.itemList,
        draggable: true,
        displayHeader: true,
        displayAddButton: true,
        displayRemoveButton: true
      );
 
    this.reorderableItemList.drawElementCallback = DrawTaskListItem;
  }
 
  public void OnGUI()
  {
    this.itemsSerializedObject.Update();
 
    this.reorderableItemList.DoLayoutList();
 
    this.itemsSerializedObject.ApplyModifiedProperties();
  }
 
  private void DrawTaskListItem(Rect rect, int index, bool isActive, bool isFocused)
  {
    SerializedProperty item = this.reorderableItemList.serializedProperty.GetArrayElementAtIndex(index);
 
    SerializedProperty isHidden = item.FindPropertyRelative("isHidden");
    SerializedProperty description = item.FindPropertyRelative("description");
 
    if (isHidden.boolValue) return;
 
    float x = rect.x;
    float y = rect.y;
 
    y += EditorGUIUtility.standardVerticalSpacing;
 
    EditorGUI.PropertyField(
      new Rect(x, y, 17f, EditorGUIUtility.singleLineHeight),
      isHidden,
      GUIContent.none
    );
 
    x += 17f;
 
    EditorGUI.PropertyField(
      new Rect(x, y, 100f, EditorGUIUtility.singleLineHeight),
      description,
      GUIContent.none
    );
  }
}

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!

Edit: This is very close, but I found if I hide the last time, the rendering gets screwed up. If I hide any of the others, it seems to work fine. This is what I'm seeing now after adding @derHugo's code and hiding the last item.

enter image description here


Solution

  • I did not find a way to work around the rendering issue. 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.