Instantly share code, notes, and snippets.
Last active
May 24, 2023 15:30
-
Star
(1)
1
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save eddieparker/7bb1fd3b253ce039994b5d677e620978 to your computer and use it in GitHub Desktop.
easy buttons property drawer version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEditor; | |
using System.Reflection; | |
using System.Linq; | |
using EasyButtons; | |
using System; | |
using System.Collections.Generic; | |
using System.Collections; | |
public class EasyButtonsPropertyDrawer<T> : PropertyDrawer | |
{ | |
// Needed to extract the index frop the property path that looks like foo.bar.myList[5]; | |
static int GetIndexFromPropertyPath(string propertyPath) | |
{ | |
return Convert.ToInt32(new string(propertyPath.Where(c => char.IsDigit(c)).ToArray())); | |
} | |
// Lazily return the objects this property is referencing. | |
// Only handles basic types, lists and arrays for now. | |
IEnumerable<System.Object> GetObjects(SerializedProperty property) | |
{ | |
foreach(var targetObject in property.serializedObject.targetObjects) | |
{ | |
var obj = this.fieldInfo.GetValue( targetObject); | |
if (obj.GetType().IsArray) | |
{ | |
var index = GetIndexFromPropertyPath(property.propertyPath); | |
obj = ((T[])obj)[index]; | |
} | |
else if(obj is IList) | |
{ | |
var index = GetIndexFromPropertyPath(property.propertyPath); | |
IList asList = ((IList)obj); | |
obj = (T)( asList[index] ); | |
} | |
yield return obj; | |
} | |
} | |
// Unity adds annoying padding at the start, and since we're using gui layouts we can just say we take up no space | |
// and let the normal layout junk do it's magic. | |
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { return -2f; } | |
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
{ | |
property.isExpanded = EditorGUILayout.Foldout(property.isExpanded, label); | |
if(property.isExpanded) | |
{ | |
// Loop through all methods with no parameters | |
var methods = typeof(T) | |
.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) | |
.Where(m => m.GetParameters().Length == 0); | |
foreach (var method in methods) | |
{ | |
// Get the ButtonAttribute on the method (if any) | |
var ba = (ButtonAttribute)Attribute.GetCustomAttribute(method, typeof(ButtonAttribute)); | |
if (ba != null) | |
{ | |
// Determine whether the button should be enabled based on its mode | |
var wasEnabled = GUI.enabled; | |
GUI.enabled = ba.Mode == ButtonMode.AlwaysEnabled | |
|| (EditorApplication.isPlaying ? ba.Mode == ButtonMode.EnabledInPlayMode : ba.Mode == ButtonMode.DisabledInPlayMode); | |
if (((int)ba.Spacing & (int)ButtonSpacing.Before) != 0) EditorGUILayout.Space(10); | |
// Draw a button which invokes the method | |
var buttonName = String.IsNullOrEmpty(ba.Name) ? ObjectNames.NicifyVariableName(method.Name) : ba.Name; | |
using(new GUILayout.HorizontalScope()) | |
{ | |
GUILayout.Space(EditorGUI.indentLevel*30); | |
if (GUILayout.Button(buttonName)) | |
{ | |
foreach(var t in GetObjects(property)) | |
{ | |
method.Invoke(t, null); | |
} | |
} | |
} | |
if (((int)ba.Spacing & (int)ButtonSpacing.After) != 0) EditorGUILayout.Space(10); | |
GUI.enabled = wasEnabled; | |
} | |
} | |
EditorGUI.indentLevel++; | |
var propertyIterator = property.Copy(); | |
var siblingProperty = property.Copy(); | |
siblingProperty.Next(false); | |
bool bOnceThrough = false; | |
while( propertyIterator.NextVisible(!bOnceThrough) // First time through, enter children (!bOnceThrough), otherwise don't | |
&& !SerializedProperty.EqualContents(propertyIterator, siblingProperty) // We haven't entered a sibling | |
) | |
{ | |
bOnceThrough = true; | |
// Default | |
EditorGUILayout.PropertyField(propertyIterator, includeChildren: true); | |
} | |
EditorGUI.indentLevel--; | |
} | |
} | |
} | |
// Users can implement the property drawer like this. Not as nice as | |
[CustomPropertyDrawer(typeof(MyCustomType))] | |
public class CCA_Parameters_PropertyDrawer : EasyButtonsPropertyDrawer<MyCustomType> | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment