Created
April 29, 2014 09:59
-
-
Save ChemiKhazi/11395776 to your computer and use it in GitHub Desktop.
Unity3d property drawer for automatically making enums flags into mask fields in the inspector.
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
Unity3d property drawer for automatically making enums flags into mask fields in the inspector. | |
Usage: Put the .cs files somewhere in your project. When you have an enum field you want to turn into a mask field in the inspector, add the EnumFlag attribute over the field. Eg: | |
[EnumFlag] | |
MyCustomEnum thisEnum; | |
// This lets you give the field a custom name in the inspector. | |
[EnumFlag("Custom Inspector Name")] | |
MyCustomEnum anotherEnum; |
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; | |
public class EnumFlagAttribute : PropertyAttribute | |
{ | |
public string enumName; | |
public EnumFlagAttribute() {} | |
public EnumFlagAttribute(string name) | |
{ | |
enumName = name; | |
} | |
} |
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 System; | |
using System.Reflection; | |
using UnityEditor; | |
using UnityEngine; | |
[CustomPropertyDrawer(typeof(EnumFlagAttribute))] | |
public class EnumFlagDrawer : PropertyDrawer { | |
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
{ | |
EnumFlagAttribute flagSettings = (EnumFlagAttribute)attribute; | |
Enum targetEnum = GetBaseProperty<Enum>(property); | |
string propName = flagSettings.enumName; | |
if (string.IsNullOrEmpty(propName)) | |
propName = property.name; | |
EditorGUI.BeginProperty(position, label, property); | |
Enum enumNew = EditorGUI.EnumMaskField(position, propName, targetEnum); | |
property.intValue = (int) Convert.ChangeType(enumNew, targetEnum.GetType()); | |
EditorGUI.EndProperty(); | |
} | |
static T GetBaseProperty<T>(SerializedProperty prop) | |
{ | |
// Separate the steps it takes to get to this property | |
string[] separatedPaths = prop.propertyPath.Split('.'); | |
// Go down to the root of this serialized property | |
System.Object reflectionTarget = prop.serializedObject.targetObject as object; | |
// Walk down the path to get the target object | |
foreach (var path in separatedPaths) | |
{ | |
FieldInfo fieldInfo = reflectionTarget.GetType().GetField(path); | |
reflectionTarget = fieldInfo.GetValue(reflectionTarget); | |
} | |
return (T) reflectionTarget; | |
} | |
} |
Hey man, thank you so much for providing this snippet. I managed to make it shown in inspector even if the attribute is private or protected. I just had to change this line:
FieldInfo fieldInfo = reflectionTarget.GetType().GetField(path);
To this:
FieldInfo fieldInfo = reflectionTarget.GetType().GetField(path, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
// This is how it looks
[SerializeField, EnumFlag]
private Axis _axis;
[SerializeField, EnumFlag]
protected Axis _axis;
When the propertyPath contains an array it breaks for me,
my enum property is contained in a serializable class named Route
my monobehaviour has a List which breaks this method.
Fixed it in my fork
It definitely breaks when multiple objects are selected. This would overwrite the values :(
Found a workaround for your problem nicekei:
EditorGUI.BeginChangeCheck(); //new line
EditorGUI.BeginProperty(position, label, property);
Enum enumNew = EditorGUI.EnumMaskField(position, propName, targetEnum);
if (!property.hasMultipleDifferentValues || EditorGUI.EndChangeCheck()) //new line
property.intValue = (int) Convert.ChangeType(enumNew, targetEnum.GetType());
EditorGUI.EndProperty();
You don't neeed this in modern Unity if you use the '[System.Flags]` attribute as Unity will use a mask field for any enum serialized with this attribute.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
i would use the label if no propName is set: