-
Star
(149)
You must be signed in to star a gist -
Fork
(25)
You must be signed in to fork a gist
-
-
Save t0chas/34afd1e4c9bc28649311 to your computer and use it in GitHub Desktop.
| using UnityEngine; | |
| using UnityEditor; | |
| using UnityEditorInternal; | |
| using System.Collections.Generic; | |
| using UnityEditor.AnimatedValues; | |
| [CustomEditor(typeof(UnityEngine.Object), true, isFallback = true)] | |
| [CanEditMultipleObjects] | |
| public class CustomEditorBase : Editor | |
| { | |
| private Dictionary<string, ReorderableListProperty> reorderableLists; | |
| protected virtual void OnEnable() | |
| { | |
| this.reorderableLists = new Dictionary<string, ReorderableListProperty>(10); | |
| } | |
| ~CustomEditorBase() | |
| { | |
| this.reorderableLists.Clear(); | |
| this.reorderableLists = null; | |
| } | |
| public override void OnInspectorGUI() | |
| { | |
| EditorGUILayout.LabelField("Custom Editor", EditorStyles.centeredGreyMiniLabel); | |
| Color cachedGuiColor = GUI.color; | |
| serializedObject.Update(); | |
| var property = serializedObject.GetIterator(); | |
| var next = property.NextVisible(true); | |
| if (next) | |
| do | |
| { | |
| GUI.color = cachedGuiColor; | |
| this.HandleProperty(property); | |
| } while (property.NextVisible(false)); | |
| serializedObject.ApplyModifiedProperties(); | |
| } | |
| protected void HandleProperty(SerializedProperty property) | |
| { | |
| //Debug.LogFormat("name: {0}, displayName: {1}, type: {2}, propertyType: {3}, path: {4}", property.name, property.displayName, property.type, property.propertyType, property.propertyPath); | |
| 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; | |
| //var attr = this.GetPropertyAttributes(property); | |
| if (property.isArray && property.propertyType != SerializedPropertyType.String) | |
| this.HandleArray(property); | |
| else | |
| EditorGUILayout.PropertyField(property, property.isExpanded); | |
| if (isdefaultScriptProperty) | |
| GUI.enabled = cachedGUIEnabled; | |
| } | |
| protected void HandleArray(SerializedProperty property) | |
| { | |
| var listData = this.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 this.GetPropertyAttributes<PropertyAttribute>(property); | |
| } | |
| protected object[] GetPropertyAttributes<T>(SerializedProperty property) where T : System.Attribute | |
| { | |
| System.Reflection.BindingFlags bindingFlags = System.Reflection.BindingFlags.GetField | |
| | System.Reflection.BindingFlags.GetProperty | |
| | System.Reflection.BindingFlags.IgnoreCase | |
| | System.Reflection.BindingFlags.Instance | |
| | System.Reflection.BindingFlags.NonPublic | |
| | System.Reflection.BindingFlags.Public; | |
| if (property.serializedObject.targetObject == null) | |
| return null; | |
| var targetType = property.serializedObject.targetObject.GetType(); | |
| var 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 (this.reorderableLists.TryGetValue(property.name, out ret)) | |
| { | |
| ret.Property = property; | |
| return ret; | |
| } | |
| ret = new ReorderableListProperty(property); | |
| this.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 this._property; } | |
| set | |
| { | |
| this._property = value; | |
| this.List.serializedProperty = this._property; | |
| } | |
| } | |
| public ReorderableListProperty(SerializedProperty property) | |
| { | |
| this.IsExpanded = new AnimBool(property.isExpanded); | |
| this.IsExpanded.speed = 1f; | |
| this._property = property; | |
| this.CreateList(); | |
| } | |
| ~ReorderableListProperty() | |
| { | |
| this._property = null; | |
| this.List = null; | |
| } | |
| private void CreateList() | |
| { | |
| bool dragable = true, header = true, add = true, remove = true; | |
| this.List = new ReorderableList(this.Property.serializedObject, this.Property, dragable, header, add, remove); | |
| this.List.drawHeaderCallback += rect => this._property.isExpanded = EditorGUI.ToggleLeft(rect, this._property.displayName, this._property.isExpanded, EditorStyles.boldLabel); | |
| this.List.onCanRemoveCallback += (list) => { return this.List.count > 0; }; | |
| this.List.drawElementCallback += this.drawElement; | |
| this.List.elementHeightCallback += (idx) => { return Mathf.Max(EditorGUIUtility.singleLineHeight, EditorGUI.GetPropertyHeight(this._property.GetArrayElementAtIndex(idx), GUIContent.none, true)) + 4.0f; }; | |
| } | |
| private void drawElement(Rect rect, int index, bool active, bool focused) | |
| { | |
| if (this._property.GetArrayElementAtIndex(index).propertyType == SerializedPropertyType.Generic) | |
| { | |
| EditorGUI.LabelField(rect, this._property.GetArrayElementAtIndex(index).displayName); | |
| } | |
| //rect.height = 16; | |
| rect.height = EditorGUI.GetPropertyHeight(this._property.GetArrayElementAtIndex(index), GUIContent.none, true); | |
| rect.y += 1; | |
| EditorGUI.PropertyField(rect, this._property.GetArrayElementAtIndex(index), GUIContent.none, true); | |
| this.List.elementHeight = rect.height + 4.0f; | |
| } | |
| } | |
| #endregion | |
| } |
| #pragma strict | |
| var myInt : int = 5; | |
| var myFloat: float = 10.56; | |
| public var players : GameObject[]; | |
| public var floats : float[]; | |
| public var numbers : int[]; | |
| public var vectors : Vector3[]; | |
| function Start () { | |
| } | |
| function Update () { | |
| } |
| 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; | |
| } |
@t0chas, this doesn't work too well with recent version of Unity.
- "Element 0, Element 1, etc" text is displayed in grey behind the elements themselves: https://i.imgur.com/YecUs7z.png
- There is a big delay when expanding/collapsing the array.
- Dragging objects to add new elements is not working.
- Nested arrays not working.
I think the main flaw is that you shouldn't use Custom Inspector to solve this problem, but PropertyDrawer instead. I know they are harder to work with but it's the only way to do it properly.
How can I remove the foldout in the elements? I find it slows me down having to expand them and it looks kinda bad. I removed the expand button at the top but I can't find anything in the code about the foldouts. The regular reorderable lists don't use these so I assume you're either using something else or have manually added them. Any ideas?
@t0chas, this doesn't work too well with recent version of Unity.
- "Element 0, Element 1, etc" text is displayed in grey behind the elements themselves: https://i.imgur.com/YecUs7z.png
- There is a big delay when expanding/collapsing the array.
- Dragging objects to add new elements is not working.
- Nested arrays not working.
I think the main flaw is that you shouldn't use Custom Inspector to solve this problem, but PropertyDrawer instead. I know they are harder to work with but it's the only way to do it properly.
I recommend use https://github.com/SubjectNerd-Unity/ReorderableInspector It does solve the issue with folding and provides many more features.
@Casey-Hofland, I would also like to see your final edit, as it's not clear what to do with original line 59 once you start pulling out AnimBool and AnimatedValues.