Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
LanKuDot opened this issue Aug 25, 2021 · 9 comments

Comments

@LanKuDot
Copy link

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

  • Unity version: 2020.3.12f1
  • Sample Code:
public class Foo : MonoBehaviour
{
    [Serializable]
    public class StringListStorage : SerializableDictionary.Storage<List<string>> {}
    [Serializable]
    public class IntStringDictionary :
        SerializableDictionary<int, List<string>, StringListStorage> {}

    [SerializeField]
    private IntStringDictionary _dictionary;
}
  • Screenshot:
    screenshot1
    The value of the key is shown when the mouse hovers on the title:
    screenshot2
    And the list of values cannot be folded/unfloded by clicking the arrow.
@max-critcrew
Copy link

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

@sachapierot
Copy link

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
Copy link
Author

LanKuDot commented Nov 9, 2021

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
Copy link

sachapierot commented Nov 9, 2021

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
Copy link
Author

It works great! Thanks a lot!

@sachapierot
Copy link

That's nice to read :)

@max-critcrew
Copy link

@Ornycar Thanks! It's working :)

@Heurazio
Copy link

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

@BieniekAlexander
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants