azixMcAze / Unity-SerializableDictionary

Serializable dictionary class for Unity
MIT License
738 stars 92 forks source link

SerializedDictionary: The key is hidden in the title of the list of value #26

Open LanKuDot opened 3 years ago

LanKuDot commented 3 years ago

Thanks for the awesome project! But I got some problems while using the dictionary with a list of value.

max-critcrew commented 3 years ago

We're having the same issues, is there any fix for this? :)

sachapierot commented 3 years ago

Hello, i've fixed the issue, in the file SerializableDictionaryPropertyDrawer you just need to swap the value and the key code blocks. Value must be drawn before the key property. Like this : image

LanKuDot commented 3 years ago

Hi, thanks! The hidden problem is solved in the almost cases. Unfortunately, I am using enum as the key, its value cannot be selected after change the drawing order.

sachapierot commented 3 years ago

Hello i think i just solved the problem, i had the same issue as you, i could not click on textfield nor edit it.

The problem happens when we want to draw a dictionary which values are arrays. (ie using SerializableDictionary.Store class). I think since Unity now (2020 and later, 2019.4 was working on my pc) uses FoldoutHeaderGroup control to draw array headers, its conflicting with the editable fields which are on the same line. I did not succeed drawing a simple foldout, so i ended up doint it this way :

The StoragePropertyDrawer was causing issue, so i edited it and added a custom way of drawing it.

I first swapped back the key and value code blocks.

I then used a ReorderableList to draw elements of the underlying array in the SerializableDictionaryStoragePropertyDrawer.

Here is the code :

[CustomPropertyDrawer(typeof(SerializableDictionaryBase.Storage), true)]
public class SerializableDictionaryStoragePropertyDrawer : PropertyDrawer
{
    private Dictionary<string, ReorderableList> _dict = new Dictionary<string, ReorderableList>();
    private ReorderableList _currentList = null;

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        property.Next(true);

        if (!property.isArray)
        {
            return;
        }

        ReorderableList list;
        if (_dict.ContainsKey(property.propertyPath))
        {
            list = _dict[property.propertyPath];
        }
        else
        {
            list = new ReorderableList(property.serializedObject, property, true, true, true, true);
            list.drawElementCallback += DrawElementCallback;
            list.elementHeightCallback += ElementHeightCallback;
            list.headerHeight = 0.0f;

            _dict.Add(property.propertyPath, list);
        }

        _currentList = list;

        if (_currentList == null)
        {
            _dict.Remove(property.propertyPath);
            return;
        }

        var foldoutRect = position;
        foldoutRect.height = 18;
        property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, label, true);
        if (property.isExpanded)
        {
            position.y += 20;
            position = EditorGUI.IndentedRect(position);
            list.DoList(position);
        }
    }

    private float ElementHeightCallback(int index)
    {
        if (_currentList == null)
            return 0.0f;

        var element = _currentList.serializedProperty.GetArrayElementAtIndex(index);
        return EditorGUI.GetPropertyHeight(element);
    }

    private void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused)
    {
        if (_currentList == null)
            return;

        var element = _currentList.serializedProperty.GetArrayElementAtIndex(index);
        rect.x += 10;
        rect.width -= 10;
        EditorGUI.PropertyField(rect, element, true);
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        property.Next(true);
        return EditorGUI.GetPropertyHeight(property);
    }
}

EDIT : removed useless code

LanKuDot commented 3 years ago

It works great! Thanks a lot!

sachapierot commented 3 years ago

That's nice to read :)

max-critcrew commented 3 years ago

@Ornycar Thanks! It's working :)

Heurazio commented 1 year ago

Yes, that's still the best solution. Thanks for sharing.

BieniekAlexander commented 2 months ago

Would anybody mind making a PR for these changes? I might be able to get around to it myself... maybe