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

ReorderableLists

Discussion in 'Immediate Mode GUI (IMGUI)' started by Roland1234, Aug 31, 2015.

  1. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Hello Unity peeps,

    I've been mashing up a new ReorderableList based off of the undocumented UnityEngineInternal (using Unity 5.1.1f1) one. It's operational, but still a work in progress - so backup your projects please.

    Huge credit to CDF for his implementation which helped fix several issues and add new features.

    Currently supports
    • No need to define a CustomEditor or CustomPropertyDrawer.
    • Drag and drop reordering.
    • Multiple selection (ctrl/command to toggle, shift to select range).
    • Collapsible list and child elements (shift-click to expand/collapse all child elements).
    • Variable element heights.
    • Add, and delete selection.
    • Helper method to transfer data serialized from regular lists/arrays into ReorderableLists.

    Current downsides
    • The need to subclass a new list for every type you need.
      The biggest downside, but necessary due to Unity's design which doesn't play nice with generic/polymorphic types, and because they insist on handling lists their own way - locking out access any other way. I've alleviated the burden as much as possible by providing my ReorderableList.OfType<T> definition to derive from, which implements the same interfaces and methods as a regular List<T> (in fact it just forwards all calls to an internal List<T>), as well as added an implicit operator to convert to List<T> when needed. It ends up needing little more than one line for each new type of list, and I've added definitions for common ones already.
    • Some reflection to access internal editor functionality.
      Though bound to add a performance overhead, I haven't noticed a difference. But more importantly this introduces dependencies on undocumented Unity internals which are vulnerable to breaking changes on Unity updates.
    • Uses a default CustomEditor to draw all components that do not have their own CustomEditor defined.
      Necessary for a strange and mysterious reason which would otherwise result in a graphical glitch when dragging elements. No idea.
    • Removed list editor callbacks.
      To make it easier on me and because I didn't care to keep them around (in case anyone knows what I'm talking about, otherwise ignore). Could be added back in with a little bit of work if somebody really wants them back.
    Those are all the points I can think of for now. It's late. Sleep is imminent.

    Usage
    Simply use one of the supplied list classes (ListOfString, ListOfVector3, or define your own), et voila. Everything else should be automagically taken care of.

    Defining Custom Lists
    Just follow the pattern, passing in your own Serializable type as the generic parameter (here Custom):
    Code (csharp):
    1.  
    2. using Assets.ReorderableList;
    3.  
    4. [Serializable]
    5. public class ListOfCustom : ReorderableList.Of<Custom> { }
    6.  
    Converting Old Lists
    To transfer existing data from regular lists to new fancy-pants lists you can use my supplied helper shtuff with some serialization callback logic like so:
    Code (csharp):
    1.  
    2. using System.Collections.Generic;
    3. using Assets.ReorderableList;
    4. using Assets.ReorderableList.Helpers;
    5. using UnityEngine;
    6.  
    7. public class MyComponent : MonoBehaviour, ISerializationCallbackReceiver
    8. {
    9.    public List<string> MyStrings;
    10.  
    11.    [TransferList("MyStrings")]
    12.    public ListOfString MyNewStrings;
    13.  
    14.    void ISerializationCallbackReceiver.OnBeforeSerialize() { }
    15.  
    16.    void ISerializationCallbackReceiver.OnAfterDeserialize()
    17.    {
    18.       ListSerializationHelper.TransferLists(this);
    19.    }
    20. }
    21.  
    And the next time the scene gets deserialized, your new list will be populated with elements of the old. Then you should remove the serialization callback and TransferList nonsense and rename your new list if you'd like (make sure you use Unity's FormerlySerializedAs attribute to preserve the values if you do). You'll most likely need to do this for each scene in your project.

    That's it for now, hope it's useful to someone. Post with fixes/suggestions/feedback if you'd like.
    Good coding!
     

    Attached Files:

    Last edited: Sep 6, 2015
    hippocoder likes this.
  2. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Added multiple selection and child expand/collapse capabilities.
     
    hippocoder likes this.
  3. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Fixed an error caused when deleting multiple items, and added keyboard shortcut for deleting.
    Also fixed height calculation to attempt to prevent GUI appearing to flicker.
     
    rigidbuddy likes this.
  4. shihui142857

    shihui142857

    Joined:
    Oct 21, 2016
    Posts:
    12
    If a list nest in a list, then I can not duplicate or delete the top list element, only the child element can be selected.
     
  5. shihui142857

    shihui142857

    Joined:
    Oct 21, 2016
    Posts:
    12
    The drag operation for a list is strange, the element will only move if the cursor is out of range.
     
  6. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Fixed error that started showing up when getting control ID in property drawer.
     
  7. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Thanks for the notice! But I'm having a spot of trouble seeing what you're describing.

    I did fix an error that started popping up in subsequent Unity versions - I don't know if that would have had any impact on what you're seeing, but could you try downloading the package again and see if anything changed?

    Other than that... maybe you could post a sample scene which produces the issues or some sort of screen capture if you're able?

    Thanks mate!
     
  8. shihui142857

    shihui142857

    Joined:
    Oct 21, 2016
    Posts:
    12
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System;
    4. using Assets.ReorderableList;
    5.  
    6. public class Example : MonoBehaviour {
    7.  
    8.     public ListOfCustom list1;
    9.  
    10.     [Serializable]
    11.     public class ListOfCustom : ReorderableList.Of<ListOfItem> { }
    12.  
    13.     [Serializable]
    14.     public class ListOfItem : ReorderableList.Of<ExampleObject> { }
    15.  
    16.     [Serializable]
    17.     public class ExampleObject
    18.     {
    19.         public string Name;
    20.         public int Amount;
    21.     }
    22. }
    This is a list nest in a list example, the effect is
     

    Attached Files:

    • file.png
      file.png
      File size:
      29.3 KB
      Views:
      1,153
  9. shihui142857

    shihui142857

    Joined:
    Oct 21, 2016
    Posts:
    12
    And the problem is, I can duplicate "Element 0", but can not duplicate the element "Element 0" above it.
     
  10. shihui142857

    shihui142857

    Joined:
    Oct 21, 2016
    Posts:
    12
  11. shihui142857

    shihui142857

    Joined:
    Oct 21, 2016
    Posts:
    12
    Comparing with the reorderable List made by CDF, other problems are:
    1. drag item is difficult, the element will only move if the cursor is out of range.
    2. click on element to collapse is annoying, it should only collapse when click on the left triangle icon.
    Also, lots of elements named "Element 0", so how can we change it ?
     
  12. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Thanks for the feedback! I've updated the package to enable the context menu on nested list elements, and changed the naming convention to use the element type's name when it's a generic serialized property type.

    I'll see if I can figure out a better way to drag items, although I don't think it's so bad the way it is (aside from an occasional glitch I'm having trouble finding the cause of).

    As far as an element's collapsing function: I could be wrong but I believe that's Unity's default foldout control, which is getting invoked by the object's property drawer. Even if I could override it with something that only activates when clicking on the triangle icon, I think that would break custom property drawer support in the list. I'll try to see if there's some workaround though, I agree it can be annoying.

    Cheers!