GithubHelp home page GithubHelp logo

sakabadev / unity-reorderable-collections Goto Github PK

View Code? Open in Web Editor NEW

This project forked from lumosx/unity-reorderable-collections

0.0 0.0 0.0 271 KB

Reorderable drawer support for lists AND dictionaries in Unity!

License: MIT License

C# 100.00%

unity-reorderable-collections's Introduction

Reorderable Collections (Lists AND Dictionaries!)

An extended version of Chris Foulston's excellent Unity-Reorderable-List project.

image

New Features

  • Built-in Dictionary support with full Dictionary<TKey, TValue> functionality. It also supports all the bells and whistles supported on the list drawers, such as pagination, sorting, and whatnot. Go wild.

  • Full List functionality, too. Instead of implementing only a subset of the regular List functionality as the old "ReorderableArray" type did, the new ReorderableList now implements all features, properties, and interfaces that a List<T> has.

  • Attributes no longer mandatory. Any class that derives from the respective base classes will be drawn correctly in the Inspector. The [Reorderable] attribute can still be used to customise the a specific field's display settings.

  • Changed internal naming to make it less confusing. ReorderableArray, the actual data structure backed by a list, has been rewritten from scratch and is now called ReorderableList, and the internal Editor-only class ReorderableList has been moved to ReorderableCollection, given that it can draw any reorderable collection.

Extant features

(This list has been copy-pasted from the source repo.)

  • Drag and Drop references (like array inspector)
  • Expandable items and list itself
  • Multiple selection (ctrl/command, shift select)
  • Draggable selection
  • Context menu items (revert values, duplicate values, delete values)
  • Custom attribute which allows automatic list generation for properties*
  • Event delegates and custom styling
  • Pagination
  • Sorting (sort based on field, ascending and descending)
  • Surrogates (Enable adding elements of a different type)

Why use this one?

Because having dictionaries in the Inspector is useful. For lists, you can happily use the parent repo, but dictionaries are a different beast entirely. The only available solution which I can sincerely recommend is Rotary Heart's brilliant Serialised Dictionary, which is based on the same base reorderable list repo but relies on a very special, complex property drawer instead, and that one's pretty difficult to customise, I can tell you that for a fact.

This, however, is a unified solution whicn relies on simple rather than complicated approaches, and which won't have you running two different "reorderable collection drawers" in different namespaces. Naturally, all listed options are free, so feel free to pick and choose whichever you like most.

Usage

Unity is unable to serialise generic types, so it's always going to be necessary to create custom classes. Types not serialised by Unity can't be used for underlying collection types. Also, both examples listed here can be found in the ScriptableObjectExample present in the repo.

Lists?

Lists are easy. Simply make a new non-generic class that derives from ReorderableList<T>, just like you do with normal lists.

For the list in the screenshot above, we have:

public MyList list;

[Serializable]
public class MyList : ReorderableList<MyObject> { }

where MyObject is a struct containing three fields -- a bool, a float, and a string.

Dictionaries?

Dictionaries are still easy, though just a bit more complicated, because need to take more things into account. For the one in the screenshot above, we have the following:

[Reorderable(paginate = true, pageSize = 0, elementNameProperty = "Value")]
public MyDict dict;


[Serializable]
public class MyDict : ReorderableDictionary<float, string, MyDict.KeyValuePair> {
    public override float DeduplicateKey(float duplicateKey) {
        return duplicateKey + 0.1f;
    }
    
    [Serializable]
    public new class KeyValuePair : ReorderableDictionary<float, string, KeyValuePair>.KeyValuePair { }
}

So, what's going on here?

  • Dicts must inherit from ReorderableDictionary<TKey, TValue, TContainer> and must be flagged serialisable as normal.
  • Dicts must also implement the DeduplicateKey method (takes and returns a TKey), which tells the dictionary how to mutate an existing key. (Dictionaries must have unique keys, and it's smarter to force the implementation to do it instead of trying to come up with some "generic" way on the base level.) In this case, adding a new element will increment the last-added key by 0.1.
  • You must also create a serialisable TContainer class that inherits from ReorderableDictionary<TKey, TValue, TContainer>.KeyValuePair. This class is used to draw the individual key-value pair elements. This is convoluted, yes, but allows you to create a custom property drawer for this class alone, and thus gives you full control over how your dictionaries look. You can put the special key-value pairs right in the base class to keep it slightly less cluttered.

Here are some examples of Inspector-drawn dicts obtained using custom property drawers for value and key-value pair classes:

image

(These are from something secret I'm working on...)

Supporting other collections

You want to add a new collection type? That one's also pretty easy, though it takes a little work. To see how, just have a look at how ReorderableDictionary has been implemented here, which is, essentially, the following:

  • Open your target collection class with the decompiler;
  • Copy-paste it into your ReorderableWhatever file;
  • Implement everything by pointing towards an internal object of the same type;
  • Now wrap your internal object's data into a single List<T> named items that the extant reorderable drawer can work with. You can use Unity's ISerializationCallbackReceiver to make the magic happen.
  • That's it, more or less!

Downsides

The way this is implemented is smarter than some alternatives (e.g. not using BaseReorderableCollection which would have forced you, the user, to manually add CustomPropertyDrawer tags to editor scripts for every single custom collection you define. That'd be very annoying.

However, an even smarter idea would have been to simply modify the ReorderableCollection drawer to be able to draw multiple lists of serialised properties instead of just one. That'd avoid the need for container classes for dictionaries that we observe now. However, I've been writing property drawers for three moths now, and preferred to NOT do that.

unity-reorderable-collections's People

Contributors

lumosx avatar cfoulston avatar leloctai avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.