Skip to content

Instantly share code, notes, and snippets.

@ChemiKhazi
Created April 29, 2014 09:59
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save ChemiKhazi/11395776 to your computer and use it in GitHub Desktop.
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.
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;
using UnityEngine;
public class EnumFlagAttribute : PropertyAttribute
{
public string enumName;
public EnumFlagAttribute() {}
public EnumFlagAttribute(string name)
{
enumName = name;
}
}
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;
}
}
@emanuelmaues
Copy link

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;

@ikriz
Copy link

ikriz commented Aug 10, 2015

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

@nicekei
Copy link

nicekei commented Nov 4, 2017

It definitely breaks when multiple objects are selected. This would overwrite the values :(

@FFouetil
Copy link

FFouetil commented Jan 11, 2018

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();

Forked it

@codiemorgan
Copy link

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