Feature Request: dynamic TabGroup for lists or customizable page size in ListDrawerSettings

Issue #55 resolved
Ivan Wang created an issue

I like tabs, but I'd like them even better if you could dynamically create one tab for each element of a list.

Alternatively, you could add an extra option to ListDrawerSettings for the number of elements per page. This way, I could fake the effect by setting the page size to 1 (functionally giving me a "tabbed" list).

Comments (4)

  1. Bjarke Elias

    Haha, Never thought of that before, clever. I'll add that to the list drawer settings.

    We actually have a [TabList] attribute in our prototyping folder which we used internally for some time. But I would much rather want a general solution that solves it for all group drawers. Just haven't thought of one yet 😀

    For now though, you could also create your own tab list drawer which could look something like this:

    _oJqEcwVEUwON482HGh8ix3w9qgJTyliAgGjqOcRfpRjs_0NI7NDTvwQlQAm1Y4PaDpuzwgAuaBzNpO7td3txd0Iq-_ZMIwlJNqsu6s4bO0F1kR3dMUjedqC16uBUu85.png

    public class MyComponent : MonoBehaviour
    {
        public MyType[] MyTypeList;
    }
    
    [Serializable]
    public class MyType
    {
        public string TabTitle;
        public string SomeField1;
        public string SomeField2;
        public string SomeField3;
    }
    
    [OdinDrawer]
    [DrawerPriority(0, 0, 2)]
    public class MyTypeDrawer<TList> : OdinValueDrawer<TList> where TList : IList<MyType>
    {
        protected override void DrawPropertyLayout(IPropertyValueEntry<TList> entry, GUIContent label)
        {
            var list = entry.SmartValue;
    
            if (list == null)
            {
                this.CallNextDrawer(entry, label);
                return;
            }
    
            // Draws a foldout to toggle the list in order to add, edit or remove tabs.
            var showList = entry.Property.Context.Get(this, "showList", false);
            showList.Value = SirenixEditorGUI.Foldout(showList.Value, "Edit List");
            if (SirenixEditorGUI.BeginFadeGroup(showList, showList.Value))
            {
                this.CallNextDrawer(entry, label);
            }
            SirenixEditorGUI.EndFadeGroup();
    
            // Draws the tabs
            var smallestSelectedListLength = entry.Property.Children.Count;
            var tabGroup = SirenixEditorGUI.CreateAnimatedTabGroup(UniqueDrawerKey.Create(entry, this));
    
            for (int i = 0; i < smallestSelectedListLength; i++)
            {
                tabGroup.RegisterTab(list[i].TabTitle ?? "Empty");
            }
    
            tabGroup.BeginGroup();
            for (int i = 0; i < smallestSelectedListLength; i++)
            {
                var tab = tabGroup.RegisterTab(list[i].TabTitle ?? "Empty");
                if (tab.BeginPage())
                {
                    entry.Property.Children[i].Draw(null);
    
                    // If you want to hide the MyType.TabTitle field. You can do something like this:
                    // var listElementProperty = entry.Property.Children[i];
                    // if (listElementProperty.ValueEntry.WeakSmartValue == null)
                    // {
                    //     listElementProperty.Draw(null);
                    // }
                    // else
                    // {
                    //     for (int j = 0; j < listElementProperty.Children.Count; j++)
                    //     {
                    //         if (listElementProperty.Children[j].Name != "TabTitle")
                    //         {
                    //             listElementProperty.Children[j].Draw();
                    //         }
                    //     }
                    // }
                }
                tab.EndPage();
            }
            tabGroup.EndGroup();
        }
    }
    
  2. Ivan Wang reporter

    Thanks for the detailed solution :) Is there a way to have add and remove buttons (just like the list header) instead of re-rendering the entire list in the foldout? I'd consult the documentation but it seems like it's still under construction...

  3. Bjarke Elias

    You have access to insert and add via the entry.GetListValueEntryChanger() it will handle multi-selection, and resolve references and all that.

    Note that entry.GetListValueEntryChanger().AddListElement() takes an array of objects in order to make it work with multi-selection.

    So you would need to do something like:

    entry.GetListValueEntryChanger()
         .AddListElement(Enumerable.Repeat(valueToAdd, this.ListChanger.ValueCount).ToArray(), "Added values to the list");
    
  4. Bjarke Elias

    From patch 1.0.4.1 notes:

    "You can now override the number of items per page for lists via the ListDrawerSettings attribute."

  5. Log in to comment