/// <summary>
        /// Delete the variable with Undo functionality
        /// </summary>
        /// <param name="index">The index of the variable to be deleted</param>
        internal void DeleteVariable(int index)
        {
            SerializedContainer.UpdateIfRequiredOrScript();

            Undo.SetCurrentGroupName("Delete Scene Variable");
            int undoGroup = Undo.GetCurrentGroup();

            Undo.RegisterCompleteObjectUndo(SerializedContainer.targetObject, "Scene Variable Deleted");

            SerializedSceneVariable serializedVariable = GetSerializedVariableAt(index);

            Undo.DestroyObjectImmediate(serializedVariable.ValueInstance);

            // Need to call delete once because it isn't an object reference value
            VariableListProp.DeleteArrayElementAtIndex(index);

            SerializedContainer.ApplyModifiedProperties();

            Undo.CollapseUndoOperations(undoGroup);
        }
        internal void CreateNewVariable(string name, System.Type typeToCreate)
        {
            if (!CanCreateVariable(name, typeToCreate))
            {
                return;
            }

            ScriptableObject variableType =
                AssetDatabaseExtensions.CreateSubScriptableObject(SceneVariablesContainer,
                                                                  typeToCreate, name);

            Undo.SetCurrentGroupName("Variable " + name + " creation");
            int undoGroup = Undo.GetCurrentGroup();

            Undo.RegisterCreatedObjectUndo(variableType, "Created " + name);

            Undo.RegisterCompleteObjectUndo(SceneVariablesContainer, "Created " + name);

            SceneVariablesContainer.CreateNewVariable(name, variableType);

            SerializedContainer.Update();

            Undo.CollapseUndoOperations(undoGroup);
        }
    private static TResult GetDragAndDropResult <TResult>(Rect dropArea, bool selectingForProjectAsset, SerializedContainer serializedContainer)
        where TResult : class
    {
        TResult result   = null;
        bool?   dropping = null;

        switch (_currentEvent.rawType)
        {
        case EventType.DragExited:
        case EventType.DragUpdated:
        case EventType.DragPerform:
            dropping = false;
            if (!serializedContainer.MouseInRects(dropArea, _currentEvent.mousePosition))
            {
                break;
            }

            var single = DragAndDrop.objectReferences.SelectMany(o => GetObjectImplementationsOf <TResult>(o)).FirstOrDefault();
            if (single != null)
            {
                var singleObject = single as Object;
                if (singleObject != null && (!selectingForProjectAsset || InterfaceableGUIHelper.IsProjectAsset(singleObject)))
                {
                    dropping = true;
                }
            }
            DragAndDrop.visualMode = SerializedContainer.AnyDropping ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Rejected;

            if (_currentEvent.type == EventType.DragPerform)
            {
                DragAndDrop.AcceptDrag();
                _currentEvent.Use();
                dropping = false;
                result   = single;
            }
            break;
        }

        if (dropping != null)
        {
            serializedContainer.SetDropping(dropping.Value);
        }

        return(result);
    }
    private static void DrawInterfaceableContainer <TResult>(Rect position, GUIContent label, SerializedContainer serializedContainer)
        where TResult : class
    {
        _currentEvent = Event.current;
        var resultTypeName = NeverLab.Interfaceable.InterfaceableContainerBase.ConstructResolvedName(CachedType <TResult> .Type);

        if (string.IsNullOrEmpty(label.tooltip))
        {
            label.tooltip = resultTypeName;
        }
        var labelRect = new GUIContentRect(label, position);

        labelRect.SetWidth(EditorGUIUtility.labelWidth);

        var resultRect = new GUIContentRect(null, position);

        resultRect.MoveNextTo(labelRect);
        resultRect.Rect.xMax -= (ButtonSpace + ButtonWidth) * 2;

        var nullButonRect = new GUIContentRect(null, position);

        nullButonRect.MoveNextTo(resultRect, ButtonSpace);
        nullButonRect.SetWidth(ButtonWidth);

        var listButtonRect = new GUIContentRect(null, position);

        listButtonRect.MoveNextTo(nullButonRect, ButtonSpace);
        listButtonRect.SetWidth(ButtonWidth);

        var isProjectAsset = serializedContainer.IsProjectAsset;
        var pingable       = !serializedContainer.ObjectFieldProperty.hasMultipleDifferentValues && InterfaceableGUIHelper.IsPingable(serializedContainer.ObjectField);
        var dragDropResult = GetDragAndDropResult <TResult>(resultRect, isProjectAsset, serializedContainer);

        EditorGUI.LabelField(labelRect, label);
        InterfaceableGUIHelper.EnabledBlock(() =>
        {
            GUI.enabled = pingable;

            InterfaceableGUIHelper.ColorBlock(() =>
            {
                if (serializedContainer.Selecting || serializedContainer.Dropping)
                {
                    GUI.color = new Color(1, 1, 1, 2);
                }
                else
                {
                    GUI.color = pingable ? new Color(1, 1, 1, 2) : Color.white;
                }

                DrawField(serializedContainer, resultRect, pingable);
            });
        });

        if (dragDropResult != null)
        {
            serializedContainer.ObjectField = dragDropResult as Object;
            GUI.changed = true;
        }

        if (GUI.Button(nullButonRect, new GUIContent("○", "Set to null"), InterfaceableGUIHelper.InspectorStyles.NullOutButton))
        {
            serializedContainer.ObjectField = null;
        }

        InterfaceableGUIHelper.EnabledBlock(() =>
        {
            if (GUI.Button(listButtonRect, new GUIContent("◉", "Select from list"), InterfaceableGUIHelper.InspectorStyles.SelectFromListButton))
            {
                _selectWindow = InterfaceableContainerSelectWindow.ShowSelectWindow(resultTypeName, isProjectAsset, serializedContainer, GetSelectable <TResult>(isProjectAsset));
            }
        });
    }
    private static void DrawField(SerializedContainer serializedContainer, Rect rect, bool pingable)
    {
        var buttonId = GUIUtility.GetControlID(FocusType.Passive) + 1;

        if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
        {
            if (pingable)
            {
                InterfaceableGUIHelper.PingObject(serializedContainer.ObjectField);
            }
        }
        var pinging = GUIUtility.hotControl == buttonId && pingable;

        GUIStyle style;

        if (serializedContainer.Dropping)
        {
            style = InterfaceableGUIHelper.InspectorStyles.DropBox;
        }
        else if (pinging)
        {
            style = InterfaceableGUIHelper.InspectorStyles.Pinging;
        }
        else if (serializedContainer.Selecting)
        {
            style = InterfaceableGUIHelper.InspectorStyles.Selecting;
        }
        else
        {
            style = InterfaceableGUIHelper.InspectorStyles.Result;
        }

        if (serializedContainer.ObjectFieldProperty.hasMultipleDifferentValues || serializedContainer.ObjectField == null)
        {
            style.alignment     = TextAnchor.MiddleCenter;
            style.imagePosition = ImagePosition.TextOnly;
        }
        else
        {
            style.alignment     = TextAnchor.MiddleLeft;
            style.imagePosition = ImagePosition.ImageLeft;
        }

        GUI.Label(rect, GUIContent.none, style);

        GUIContentRect icon, label;

        serializedContainer.GetContainerContents(rect, serializedContainer.Dropping, out icon, out label);

        style.normal.background = null;

        if (icon.Content != null)
        {
            icon.SetWidth(InterfaceableGUIHelper.GetScaledTextureWidth(icon.Content.image, rect.height + 2.0f));
            label.MoveNextTo(icon, -3.0f);
            GUI.Label(icon, icon, style);
        }
        GUI.Label(label, label, style);

        if (!SerializedContainer.AnyDropping && pingable)
        {
            EditorGUIUtility.AddCursorRect(rect, MouseCursor.Zoom);
        }
    }