EditorGUILayout.EnumMaskField How to use the value

Hi guys.

This is my first experience writing a custom editor and I want to create a dropdown for an enum where I can select multiple options in the inspector and then use those values in the scriptable object. I don’t really want to use them as masks for anything but I couldn’t see another way to create a dropdown of this type so if I’m wrong about that please point me towards that! :slight_smile:

So my example is as follows:

Skill Class and enum

public enum DestroyType{duration = 1, distance = 2, collision = 4};

public class Skill: ScriptableObject
{
	public DestroyType destroyType;
	...//code
}

From the examples it looked to me like an enum can have multiple values at once or something so I initially had it as an array or list but not anymore, I also don’t really know what’s correct there.

Editor Script

[CustomEditor(typeof(Skill))]
public class SkillEditor : Editor
{
	Skill mySkill;
	void Awake()
	{
		mySkill = (Skill)target;
	}
	public override void OnInspectorGUI()
	{ 
		serializedObject.Update ();
	 	...//code
		mySkill.destroyType = (DestroyType)EditorGUILayout.EnumMaskField("Destroy On", mySkill.destroyType );

		if(mySkill.destroyType == DestroyType.collision)
		{
			EditorGUILayout.LabelField("Collision",GUILayout.MaxWidth(100));
		}
		if(mySkill.destroyType == DestroyType.distance)
		{
			EditorGUILayout.LabelField("Distance",GUILayout.MaxWidth(100));
		}
		if(mySkill.destroyType == DestroyType.duration)
		{
			EditorGUILayout.LabelField("Duration",GUILayout.MaxWidth(100));
		}
		serializedObject.ApplyModifiedProperties ();
	}
}

So basically I don’t know if: mySkill.destroyType = (DestroyType)EditorGUILayout.EnumMaskField("Destroy On", mySkill.destroyType ); is correct and then how to reference it in an if statement because they’re not showing anything. Any help would be greatly appreciated! Thanks!

Edit

Okay so I was wrong the if statements are working as I expected (I must’ve just not saved the script or something daft)… but obviously not if it’s a mixed value so I still don’t know what the if statement for a mixed value situation would be. Any ideas?

Edit
I can see that logging the value of destroyType gives me a value (5,6,-1). I have no idea how to predict these values in advance and for me it would be a lot easier to reference each by name and then if it subscribes to multiple firing both if statements rather than having more if statements with different conditions (if that makes sense).

As the name “EnumMaskField” suggests it only works with enums which represents a bitmask. However the implementation of “EnumMaskField” is a bit, well, “strange” as i said in the comment over here. You can use my wrapper i’ve posted in my answer so it actually uses the values of your enum members.

Of course the enum values need to represent a bitflag, so each member need to represents a different “bit”. In your case your “DestroyType” meets that requirement. The actual bitflag however need to be tested in a different way. If two or more are selected at the same time, all those bits will be set in the value.

duration = 0001 // == 0x01
distance = 0010 // == 0x02
collision = 0100 // == 0x04

If for example “duration” and “collision” are selected the value would be “5” (0101) if all 3 are selected it would be “7” (0111). To test a certain bit you have to use bit operations:

if(mySkill.destroyType & DestroyType.collision > 0)
{
}

This will make a bitwise “and” operation between your actual value and the value of “collision” since collision is “4” (0100) it only returns a value greater than 0 if that bit is set in the value

value    mask     result
0000  &  0100  =  0000
0010  &  0100  =  0000
0110  &  0100  =  0100
0111  &  0100  =  0100
0100  &  0100  =  0100
0101  &  0010  =  0000
0110  &  0010  =  0010

Of course since an enum is actually an integer as underlying type you only have 32 bits you can use. The decimal value of “-1” is equivalent with “11111111 11111111 11111111 11111111” in binary, so all 32 bits are set.