// --------------------------------------------------------------------------------------------
    public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
    {
        var content = EditorGUI.BeginProperty(rect, label, property);

        m_info = GetArrayFieldInfo(property);

        var headerHeight = GetHeaderHeight(property, content);

        var elementRect = rect;

        elementRect.y += (m_info != null && m_info.elementIndex == 0) ? headerHeight : 0;

        if (m_info != null)
        {
            // Draw reorderable buttons first because we want to know their size, so the drawHeader
            // method can properly adjust the position of its content.
            elementRect = DrawReorderableButtons(elementRect, property);
        }

        // Draw the header if it's the first element.
        if (m_info != null && m_info.elementIndex == 0)
        {
            var headerRect = new Rect(elementRect.x, elementRect.y - headerHeight, elementRect.width, headerHeight);
            DrawHeader(rect, headerRect, property, content);
        }

        elementRect.height = GetElementHeight(property, content);
        DrawElement(rect, elementRect, property, content);

        EditorGUI.EndProperty();
    }
    // --------------------------------------------------------------------------------------------
    private static void ReorderElement(ArrayFieldInfo info, int offset)
    {
        var value = info.arrayFieldInfo.GetValue(info.arrayOwner);

        if (info.collectionType == CollectionType.Array)
        {
            var array    = value as Array;
            var newIndex = Mathf.Clamp(info.elementIndex + offset, 0, array.Length - 1);
            var element  = array.GetValue(info.elementIndex);

            // We don't simply swap the elements because the offset is not always 1 or -1
            // This function is also used to put elements on top or to the bottom.
            array = ArrayRemove(info.elementType, array, info.elementIndex);
            array = ArrayInsert(info.elementType, array, newIndex, element);
            info.arrayFieldInfo.SetValue(info.arrayOwner, array);
        }
        else if (info.collectionType == CollectionType.List)
        {
            var list     = value as IList;
            var newIndex = Mathf.Clamp(info.elementIndex + offset, 0, list.Count - 1);
            var element  = list[info.elementIndex];
            list.RemoveAt(info.elementIndex);
            list.Insert(newIndex, element);
        }
    }
    // --------------------------------------------------------------------------------------------
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        m_info = GetArrayFieldInfo(property);
        var height = GetElementHeight(property, label);

        if (m_info != null && m_info.elementIndex == 0)
        {
            height += GetHeaderHeight(property, label);
        }

        return(height);
    }
    // --------------------------------------------------------------------------------------------
    private static void DeleteElement(ArrayFieldInfo info)
    {
        var value = info.arrayFieldInfo.GetValue(info.arrayOwner);

        if (info.collectionType == CollectionType.Array)
        {
            var array = ArrayRemove(info.elementType, value as Array, info.elementIndex);
            info.arrayFieldInfo.SetValue(info.arrayOwner, array);
        }
        else if (info.collectionType == CollectionType.List)
        {
            var list = value as IList;
            list.RemoveAt(info.elementIndex);
        }
    }
    // --------------------------------------------------------------------------------------------
    private static void InsertElement(ArrayFieldInfo info)
    {
        var value = info.arrayFieldInfo.GetValue(info.arrayOwner);

        if (info.collectionType == CollectionType.Array)
        {
            var newInstance = Activator.CreateInstance(info.elementType);
            var array       = ArrayInsert(info.elementType, value as Array, info.elementIndex + 1, newInstance);
            info.arrayFieldInfo.SetValue(info.arrayOwner, array);
        }
        else if (info.collectionType == CollectionType.List)
        {
            var newInstance = Activator.CreateInstance(info.elementType);
            var list        = value as IList;
            list.Insert(info.elementIndex + 1, newInstance);
        }
    }
    // --------------------------------------------------------------------------------------------
    public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginChangeCheck();

        var content = EditorGUI.BeginProperty(rect, label, property);

        m_info = GetArrayFieldInfo(property);

        var headerHeight = GetHeaderHeight(property, content);

        var elementRect = rect;

        elementRect.y += (m_info != null && m_info.elementIndex == 0) ? headerHeight : 0;

        if (m_info != null)
        {
            // Draw reorderable buttons first because we want to know their size, so the drawHeader
            // method can properly adjust the position of its content.
            elementRect = DrawReorderableButtons(elementRect, property);
        }

        // Draw the header if it's the first element.
        if (m_info != null && m_info.elementIndex == 0)
        {
            var headerRect = new Rect(elementRect.x, elementRect.y - headerHeight, elementRect.width, headerHeight);
            DrawHeader(rect, headerRect, property, content);
        }

        elementRect.height = GetElementHeight(property, content);
        DrawElement(rect, elementRect, property, content);

        EditorGUI.EndProperty();

        if (EditorGUI.EndChangeCheck())
        {
            //On check si c'est un asset, et non un scene-object
            var obj = property.serializedObject.targetObject;
            if (AssetDatabase.Contains(obj))
            {
                EditorUtility.SetDirty(obj);
            }
        }
    }