Reorderable List v2

Hi, just wanted to share some work I’ve been doing on a Reorderable List.

Moved to Github: GitHub - cfoulston/Unity-Reorderable-List: Extended version of the Reorderable List in Unity

It’s an attempt to mimic functionality of the ReorderableList within Unity while adding some extended functionality.

7 Likes

How would this go with nested list structures. Say trees up to 5-7 levels deep?

It should work the same as a 5-7 level deep array, you’ll just need someway to define these nested arrays as Reorderable Lists. e.g:

public class Example : MonoBehaviour {

    [Reorderable]
    public ExampleChildList list;

    [System.Serializable]
    public class ExampleChild {

        [Reorderable]
        public ExampleChildList nested;
    }

    [System.Serializable]
    public class ExampleChildList : ReorderableArray<ExampleChild> {
    }
}

This code will however throw a SerializationDepth error as there is a possibility of infinite nested lists.

I’m still trying to figure out a better way to define these lists using Attributes… Shame you can’t define an attribute for the entire array. And it’s not possible to write a propertyDrawer for a generic type.

Ok, I think I’ve got a better solution to the whole reference issue.

instead of referencing by propertyPath, the list generates an id (GetHashCode), the ReorderableArray then stores this id as a private serializedProperty. The reference to the list is acquired using this id, if it doesn’t exist, make a new list, otherwise return the existing one. It’s working so far, selection is maintained.

Also added optional sliding to the dragging.

What up CDF? It looks like we’ve been thinking along the exact same lines. Eerily so. We should look into each other’s implementations and see if we can’t collaborate in some way. For now (because I’m about to pass out) imma drop me link. Hope you don’t mind:

Cheers mate!

I’m surprised we didn’t join on the same date as well, because now we have the same number of messages :stuck_out_tongue:

Cool, yeah I’ll take a look. I’m really busy with Work right now, but hopefully there’s something in both that people can benefit from

  • HELP

  • NullReferenceException: (null)

  • UnityEditor.SerializedObject…ctor (UnityEngine.Object[ ] objs) (at C:/buildslave/unity/build/artifacts/generated/common/editor/SerializedPropertyBindings.gen.cs:74)

  • UnityEditor.Editor.GetSerializedObjectInternal () (at C:/buildslave/unity/build/artifacts/generated/common/editor/EditorBindings.gen.cs:154)

  • UnityEditor.Editor.get_serializedObject () (at C:/buildslave/unity/build/artifacts/generated/common/editor/EditorBindings.gen.cs:147)

  • TestEditor.OnEnable () (at Assets/Editor/TestEditor.cs:275)

Will need to see the code of TestEditor.cs in order to help.

CDF, where can I change the code so that instead of saying ‘Element 0, Element 1, etc’ it display custom strings like in your case ‘My Kewl Element’?

set the value of “elementNameProperty” to a property of your objects in the list

list = new ReorderableList(mySerializedObject.FindProperty("myList"));
list.elementNameProperty = "myCustomField"

class Container {

    [SerializeField]
    private Child[] myList;
}

[Serializable]
class Child {

    public string myCustomField = "Hello";
}

Ye, I can’t quite get it to work, code:

using UnityEngine;
using UnityEditor;
using System.Collections;
using Malee.Editor;

[CanEditMultipleObjects]
[CustomEditor(typeof(Example))]
public class ExampleEditor : Editor
{

    private ReorderableList RotationTimeline;

    class Container {
 
    [SerializeField]
    private Child[] RotationTimeline;
}


[System.Serializable]
class Child {
 
    public string myCustomField = "Hello";
}


    void OnEnable() {

        RotationTimeline = new ReorderableList(serializedObject.FindProperty("RotationTimeline"));
        RotationTimeline.elementNameProperty = "myCustomField";
    }

    public override void OnInspectorGUI() {

        serializedObject.Update();

        //draw the list using GUILayout, you can of course specify your own position and label
        RotationTimeline.DoLayoutList();

        //Caching the property is recommended

        //Still works, but there are some minor issues with selection state as properties can only be referenced by propertyPath
        //And if that propertyPath changes (by array modification) then the list will be either rebuilt or point to a different reference
        //EditorGUILayout.PropertyField(serializedObject.FindProperty("list2"));

        serializedObject.ApplyModifiedProperties();
    }
}

RotationTimeline.elementNameProperty=“myCustomField”;

This is just saying, set the display of each element in the list to the value of “myCustomField” on each element.
So the elements in the array need to have this property defined.

Got it to work, thanks! And another question if I’m not bothering you, how can I access a variable in the list? So in another script for example, how do I access the value of ‘InitialAngle’?

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Malee;

public class Example : MonoBehaviour {

    public List<ExampleChild> RotationTimeline;


    //[Reorderable]
//    public ExampleChildList list2;

    [System.Serializable]
    public class ExampleChild
    {

        public string SingleRotation;
        public string LoopedRotation;

//VAriables in each element
//Just for showing, RotationType is used nowhere
        public enum TypeOfRotation
        {
                    SingleRotation,
                    LoopedRotation,
        }
        public TypeOfRotation RotationType;


        public float InitialAngle;
        public float FinalAngle;
        public float Speed;

    }

    class Container {
 
    [SerializeField]
    private ExampleChild[] RotationTimeline;
}

    [System.Serializable]
    public class ExampleChildList : ReorderableArray<ExampleChild> {
    }
}
RotationTimeline = new ReorderableList(serializedObject.FindProperty("RotationTimeline"));
//Get the first item in the list, if there are no items this will result in an error
RotationTimeline.GetItem(0).FindPropertyRelative("InitialAngle").floatValue;

At some point I plan to document the class, soon…

and…

I have this enum in one script:

   public enum TypeOfRotation
         {
                     SingleRotation,
                     LoopedRotation,
         }
         public TypeOfRotation RotationType;

And then in another script I want set the value of elementNameProperty to be whatever was selected in the enum (SingleRotation or LoopedRotation). The following code doesn’t work and I don’t quite know how to achieve this.

 RotationTimeline.elementNameProperty = RotationTimeline.GetItem(0).FindPropertyRelative("TypeOfRotation").enumNames;

Merry christmas

CDF you win!! Loveable package!! I hope to see that even on asset store (or in unity by default ahah) a thing like that!!

Merry Christmas alexanderameye I’ve updated the package with some name features. Hopefully they will work for your needs. Check the example for using an enum as the display name.

In your example above, the code would simply be: RotationTimeline.elementNameProperty = “RotationType”

1 Like

Thanks :smile:.

Unfortunately I can’t really support this full time because of other work, but sure I’d love to see this in Unity :wink: