HKMBFZ/Assets/SKFramework/Tools/Variables/Editor/VariableArrayDrawer.cs

182 lines
6.8 KiB
C#

using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
namespace SK.Framework
{
[CustomPropertyDrawer(typeof(Variables))]
public class VariableArrayDrawer : PropertyDrawer
{
private const float HORIZONTAL_GAP = 5;
private const float VERTICAL_GAP = 5;
private ReorderableList list;
private ReorderableList GetList(SerializedProperty property)
{
if (list == null)
{
list = new ReorderableList(property.serializedObject, property, true, true, true, true)
{
elementHeight = 21,
drawElementCallback = DrawElement,
drawHeaderCallback = DrawHeader,
onAddDropdownCallback = OnAddElement,
onRemoveCallback = OnRemoveElement,
drawElementBackgroundCallback = DrawElementBackground
};
}
else
{
list.serializedProperty = property;
}
return list;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
float height = base.GetPropertyHeight(property, label) + 60;
var variables = property.FindPropertyRelative("variables");
for (int i = 0; i < variables.arraySize; i++)
height += EditorGUI.GetPropertyHeight(variables.GetArrayElementAtIndex(i)) + VERTICAL_GAP;
return height;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var list = GetList(property.FindPropertyRelative("variables"));
list.DoList(position);
}
private void OnAddElement(Rect rect, ReorderableList list)
{
var variables = list.serializedProperty;
int index = variables.arraySize > 0 ? variables.arraySize : 0;
DrawContextMenu(variables, index);
}
private void OnRemoveElement(ReorderableList list)
{
var variables = list.serializedProperty;
AskRemoveVariable(variables, list.index);
}
private void DrawElementBackground(Rect rect, int index, bool isActive, bool isFocused)
{
ReorderableList.defaultBehaviours.DrawElementBackground(rect, index, isActive, false, true);
}
private void DrawHeader(Rect rect)
{
GUI.Label(rect, "Variables");
}
private void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
var variables = list.serializedProperty;
if (index < 0 || index >= variables.arraySize)
return;
var variable = variables.GetArrayElementAtIndex(index);
float x = rect.x;
float y = rect.y + 2;
float width = rect.width - 40;
float height = rect.height;
Rect variableRect = new Rect(x, y, width, height);
EditorGUI.PropertyField(variableRect, variable, GUIContent.none);
var buttonLeftRect = new Rect(variableRect.xMax + HORIZONTAL_GAP, y - 1, 18, 18);
var buttonRightRect = new Rect(buttonLeftRect.xMax, y - 1, 18, 18);
if (GUI.Button(buttonLeftRect, new GUIContent("+"), EditorStyles.miniButtonLeft))
{
DuplicateVariable(variables, index);
}
if (GUI.Button(buttonRightRect, new GUIContent("-"), EditorStyles.miniButtonRight))
{
AskRemoveVariable(variables, index);
}
}
protected virtual void DrawContextMenu(SerializedProperty variables, int index)
{
GenericMenu menu = new GenericMenu();
foreach (VariableType variableType in System.Enum.GetValues(typeof(VariableType)))
{
var type = variableType;
menu.AddItem(new GUIContent(variableType.ToString()), false, context =>
{
AddVariable(variables, index, type);
}, null);
}
menu.ShowAsContext();
}
protected virtual void AddVariable(SerializedProperty variables, int index, VariableType type)
{
if (index < 0 || index > variables.arraySize)
return;
variables.serializedObject.Update();
variables.InsertArrayElementAtIndex(index);
SerializedProperty variableProperty = variables.GetArrayElementAtIndex(index);
variableProperty.FindPropertyRelative("variableType").enumValueIndex = (int)type;
variableProperty.FindPropertyRelative("name").stringValue = "";
variableProperty.FindPropertyRelative("objectValue").objectReferenceValue = null;
variableProperty.FindPropertyRelative("dataValue").stringValue = "";
variables.serializedObject.ApplyModifiedProperties();
GUI.FocusControl(null);
}
protected virtual void DuplicateVariable(SerializedProperty variables, int index)
{
if (index < 0 || index >= variables.arraySize)
return;
variables.serializedObject.Update();
variables.InsertArrayElementAtIndex(index);
SerializedProperty variableProperty = variables.GetArrayElementAtIndex(index + 1);
variableProperty.FindPropertyRelative("name").stringValue = "";
variableProperty.FindPropertyRelative("objectValue").objectReferenceValue = null;
variableProperty.FindPropertyRelative("dataValue").stringValue = "";
variables.serializedObject.ApplyModifiedProperties();
GUI.FocusControl(null);
}
protected virtual void AskRemoveVariable(SerializedProperty variables, int index)
{
if (variables == null || index < 0 || index >= variables.arraySize)
return;
var variable = variables.GetArrayElementAtIndex(index);
var name = variable.FindPropertyRelative("name").stringValue;
if (string.IsNullOrEmpty(name))
{
RemoveVariable(variables, index);
return;
}
if (EditorUtility.DisplayDialog("Confirm delete", string.Format("Are you sure you want to delete the item named \"{0}\"?", name), "Yes", "Cancel"))
{
RemoveVariable(variables, index);
}
}
protected virtual void RemoveVariable(SerializedProperty variables, int index)
{
if (index < 0 || index >= variables.arraySize)
return;
variables.serializedObject.Update();
variables.DeleteArrayElementAtIndex(index);
variables.serializedObject.ApplyModifiedProperties();
GUI.FocusControl(null);
}
}
}