Skip to content

Instantly share code, notes, and snippets.

@brunomikoski
Forked from t0chas/CustomEditorBase.cs
Last active July 23, 2016 22:12
Show Gist options
  • Save brunomikoski/e6e0d61705d96598d0133f0ae670e8ee to your computer and use it in GitHub Desktop.
Save brunomikoski/e6e0d61705d96598d0133f0ae670e8ee to your computer and use it in GitHub Desktop.
Default Custom Inspector-Editor for Unity3D with ReorderableLists for arrays handling
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditorInternal;
using UnityEngine;
using Object = UnityEngine.Object;
[CustomEditor(typeof (Object), true, isFallback = true)]
[CanEditMultipleObjects]
public class CustomEditorBase : Editor
{
private Dictionary<string, ReorderableListProperty> reorderableLists;
protected virtual void OnEnable()
{
reorderableLists = new Dictionary<string, ReorderableListProperty>(10);
}
~CustomEditorBase()
{
reorderableLists.Clear();
reorderableLists = null;
}
public override void OnInspectorGUI()
{
EditorGUILayout.LabelField("Custom Editor", EditorStyles.centeredGreyMiniLabel);
Color cachedGuiColor = GUI.color;
serializedObject.Update();
SerializedProperty property = serializedObject.GetIterator();
bool next = property.NextVisible(true);
if (next)
do
{
GUI.color = cachedGuiColor;
HandleProperty(property);
} while (property.NextVisible(false));
serializedObject.ApplyModifiedProperties();
}
protected void HandleProperty(SerializedProperty property)
{
bool isdefaultScriptProperty = property.name.Equals("m_Script") && property.type.Equals("PPtr<MonoScript>") &&
property.propertyType == SerializedPropertyType.ObjectReference &&
property.propertyPath.Equals("m_Script");
bool cachedGUIEnabled = GUI.enabled;
if (isdefaultScriptProperty)
GUI.enabled = false;
if (property.isArray && property.propertyType != SerializedPropertyType.String)
HandleArray(property);
else
EditorGUILayout.PropertyField(property, property.isExpanded);
if (isdefaultScriptProperty)
GUI.enabled = cachedGUIEnabled;
}
protected void HandleArray(SerializedProperty property)
{
ReorderableListProperty listData = GetReorderableList(property);
listData.IsExpanded.target = property.isExpanded;
if ((!listData.IsExpanded.value && !listData.IsExpanded.isAnimating) ||
(!listData.IsExpanded.value && listData.IsExpanded.isAnimating))
{
EditorGUILayout.BeginHorizontal();
property.isExpanded = EditorGUILayout.ToggleLeft(string.Format("{0}[]", property.displayName),
property.isExpanded, EditorStyles.boldLabel);
EditorGUILayout.LabelField(string.Format("size: {0}", property.arraySize));
EditorGUILayout.EndHorizontal();
}
else
{
if (EditorGUILayout.BeginFadeGroup(listData.IsExpanded.faded))
listData.List.DoLayoutList();
EditorGUILayout.EndFadeGroup();
}
}
protected object[] GetPropertyAttributes(SerializedProperty property)
{
return GetPropertyAttributes<PropertyAttribute>(property);
}
protected object[] GetPropertyAttributes<T>(SerializedProperty property) where T : Attribute
{
BindingFlags bindingFlags = BindingFlags.GetField
| BindingFlags.GetProperty
| BindingFlags.IgnoreCase
| BindingFlags.Instance
| BindingFlags.NonPublic
| BindingFlags.Public;
if (property.serializedObject.targetObject == null)
return null;
Type targetType = property.serializedObject.targetObject.GetType();
FieldInfo field = targetType.GetField(property.name, bindingFlags);
if (field != null)
return field.GetCustomAttributes(typeof (T), true);
return null;
}
private ReorderableListProperty GetReorderableList(SerializedProperty property)
{
ReorderableListProperty ret = null;
if (reorderableLists.TryGetValue(property.name, out ret))
{
ret.Property = property;
return ret;
}
ret = new ReorderableListProperty(property);
reorderableLists.Add(property.name, ret);
return ret;
}
#region Inner-class ReorderableListProperty
private class ReorderableListProperty
{
public AnimBool IsExpanded { get; private set; }
/// <summary>
/// ref http://va.lent.in/unity-make-your-lists-functional-with-reorderablelist/
/// </summary>
public ReorderableList List { get; private set; }
private SerializedProperty _property;
public SerializedProperty Property
{
get { return _property; }
set
{
_property = value;
List.serializedProperty = _property;
}
}
public ReorderableListProperty(SerializedProperty property)
{
IsExpanded = new AnimBool(property.isExpanded)
{
speed = 0f
};
_property = property;
CreateList();
}
~ReorderableListProperty()
{
_property = null;
List = null;
}
private void CreateList()
{
bool dragable = true, header = true, add = true, remove = true;
List = new ReorderableList(Property.serializedObject, Property, dragable, header, add, remove);
List.drawHeaderCallback +=
rect =>
_property.isExpanded =
EditorGUI.ToggleLeft(rect, _property.displayName, _property.isExpanded, EditorStyles.boldLabel);
List.onCanRemoveCallback += list => { return List.count > 0; };
List.drawElementCallback += drawElement;
List.elementHeightCallback +=
idx =>
{
return
Mathf.Max(EditorGUIUtility.singleLineHeight,
EditorGUI.GetPropertyHeight(_property.GetArrayElementAtIndex(idx), GUIContent.none, true)) +
4.0f;
};
}
private void drawElement(Rect rect, int index, bool active, bool focused)
{
//rect.height = 16;
rect.height = EditorGUI.GetPropertyHeight(_property.GetArrayElementAtIndex(index), GUIContent.none, true);
rect.y += 1;
EditorGUI.PropertyField(rect, _property.GetArrayElementAtIndex(index), GUIContent.none, true);
List.elementHeight = rect.height + 4.0f;
}
}
#endregion
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//using System;
[System.Flags]
public enum Stuff{
Coke = 1 << 0,
Hamburguer = 1 << 1,
Pizza = 1 << 2,
Hotdog = 1 << 3,
Pepsi = 1 << 4,
Beer = 1 << 5,
BuffaloWings = 1 << 6,
IceCream = 1 << 7,
}
[System.Serializable]
public struct SomeOtherData
{
public int aNumber;
[Range(0f, 1f)]
public float anotherNumber;
public Vector3 position;
}
public class Tester : MonoBehaviour {
public int aNumber;
public int AFloat;
[Range(0f, 100f)]
public float AFloatRangeAttr;
public string aString;
public int[] aNumerArray;
public float[] aFloatArray;
[Range(0.0f, 100.0f)]
public float[] anotherFloatArray;
[SerializeField]
private List<Stuff> privateListOfStuff;
[SerializeField]
private SomeOtherData NestedData;
[SerializeField]
private AudioMixerClip mixerClip;
[SerializeField]
private AudioMixerClip[] mixerClips;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment