Despite the fact that this thread is very old - does anybody have a solution to this?
Display a enum bitmask in the editor just like the “Culling mask” property of a Camera?
Because Camera’s culling mask is still rendered as a nice enum dropdown when the inspector GUI is switched to Debug mode, I assume that rendering the dropdown is not a customized editor, but rather achievable via C# syntax (just like an enum shows up as a dropdown with single selection).
So what is the magic trick/keyword to get a dropdown with MULTI selection using enums?
Thanks for the hint, but can’t use that. LayerMask displays the layer masks while I want to display my enum entries.
I now have placed the [System.Flags] attribute above the definition of my enum but Unity doesn’t honor that.
Furthermore the EditorLayout and related classed do not offer a function for drawing a dropdown with multiple selection - therefore even a custom editor for the component the “enum mask” property belongs to is not an option.
IMHO Unity should honor the [System.Flags] attribute and everything would be fine.
But so… stuck here.
I’m running into this right now as well. Having the ability to make an inspector element just like Camera’s “Culling mask” would be really useful!
I don’t know if this helps at all, but as I perused the Camera class in the Assembly Browser in MonoDevelop I found this property…
“public int cullingMask { get; set; }”
Is there another attribute you have to use to make it visible to Unity? Does the enum have to extend a certain value type?
It seems that LayerMask extends the System.ValueType class. This is what I found in Assembly Browser:
public sealed struct LayerMask : ValueType
{
// Methods
public static string LayerToName (int layer);
public static int NameToLayer (string layerName);
EnumMaskField is not giving me the expected integer value when when selecting “Everything”. It returns -1.0 instead.
Also any combination of bits thereafter is negative and tends to overshoot the possible integer value one would expect to get when combining all Flags.
How is this supposed to be used correctly? This is what I have in my custom editor:
Ok so again an old thread, but because it was the top result at google I’ll leave an answer for the next adventurer to come along.
Yes this is intended behaviour, the integer -1, if you look at it as a binary value, is actually all 1’s, or in hexadecimal 0xFFFFFFFF. The correct way to use it is with bitwise operators.
old thread… but if you don’t want to use an editor entry, then:
enum EditFlag : uint {
GLOBAL_ROTATION = 1,
LOCAL_ROTATION = 2,
NO_ROTATION = 4,
SCALING = 8,
}
old thread, but just for the next one, unity make obsolete EditorGUILayout.EnumMaskField and in unity 2017.3 they add EditorGUILayout.EnumFlagsField, but i m in 2017.2 and i dont have enyone of this methods
I’m actually trying to figure out how to use this with multi-object selection, but
EditorGUILayout.PropertyField() just spits it out as a normal enum and not as bitwise selection field like LayerMask.
This will do exactly what you are looking for, and they even have a nice little example in there that tells you everything you need to know
EDIT:
I have a solution that I think everyone will love even more!
I like Attributes, and I wanted this functionality in an Attribute, so I did:
First create a script called EnumMaskAttribute and shove this code in there:
# if UNITY_EDITOR
using System;
using UnityEditor;
using UnityEngine;
public class EnumMaskAttribute : PropertyAttribute
{
public Type EnumType;
public Enum Enum;
public EnumMaskAttribute(Type enumType)
{
this.EnumType = enumType;
this.Enum = (Enum)Enum.GetValues(enumType).GetValue(0);
}
}
[CustomPropertyDrawer(typeof(EnumMaskAttribute))]
public class EnumMaskDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EnumMaskAttribute enumMaskAttribute = attribute as EnumMaskAttribute;
enumMaskAttribute.Enum = EditorGUI.EnumFlagsField(position, label, enumMaskAttribute.Enum);
if (enumMaskAttribute.EnumType == typeof(Enum))
{
Debug.Log(enumMaskAttribute.Enum);
property.intValue = Convert.ToInt32(Enum.Parse(enumMaskAttribute.EnumType, Enum.GetName(enumMaskAttribute.EnumType, enumMaskAttribute.Enum)));
}
else
{
property.intValue = Convert.ToInt32(enumMaskAttribute.Enum);
}
}
}
#endif
Now. Create another script called EnumMaskAttributeTest and replace it’s contents with the following:
using UnityEngine;
public enum TestEnum
{
A = 1 << 0,
B = 1 << 1,
C = 1 << 2
}
public class EnumMaskAttributeTest : MonoBehaviour
{
[EnumMask(typeof(TestEnum))]
public int testEnumMask;
}
Now attach that to a GameObject in your scene and watch the magic All you have to do is make sure you create your enum like the one above (using bits) and you can go all the way up to 31 I believe (please correct me if I’m wrong )
enums assume an underlying type, which is Int32 by default. and so yes, you can use up to 32 bits, by bit shifting from 0 to 31.
you can also use fixed literals, instead of shifting expressions, traditionally in hexadecimal
public enum TestFlags {
A = 0x1,
B = 0x2,
C = 0x4,
D = 0x10, // etc
}
or in binary
public enum TestFlags {
A = 0b1,
B = 0b10,
C = 0b100,
D = 0b1000, // etc
}
also call your flag enums ~Flags, not ~Enum, by convention.
you can also mark them as [System.Flags] which is another hint for the programmer (and the enum will get an extension method GetFlag).
in your drawer, at line 24, you should probably check whether the enum values has actually changed, and do the enum shenanigans only then (the entire if block evaluating serialized property’s intValue). what you’re doing can be terribly slow especially for large enums and/or many such enum flags fields, while editor will call this repeatedly on repaint.
You used to need to create your own property drawer, but somewhere along the way that became unnecessary. Now, just marking the enum as a [Flags] enum will draw it correctly, but that does not invalidate the old posts on this thread from a time when that was not true.