📜 ⬆️ ⬇️

Simplify drawing Enum Flags in Unity



In this post, I will try to briefly describe the type of enumeration in C # , its use as flags, as well as how to simplify their drawing in the Unity inspector.

What is Enum?


Enums are a meaningful type in C # consisting of a set of constants. To declare it, use the enum keyword. Each enumerator has an integer value. The first is 0 by default, and the following ones increase by 1 .
')
enum Color { Red, // 0 Green, // 1 Blue // 2 } 

For redefinition of values ​​it is possible to use initializers.

 enum Color { Red = 1, Green = 2, Blue = 3 } 

Each type of enumeration has a base type, which can be any integer type except char (the default is int ). It can also be specified explicitly.

 enum Color : byte { Red = 1, Green = 2, Blue = 3 } 

Flags


Sometimes it is necessary to endow an entity with a number of properties. You can declare several fields or create a list, but sometimes a single enumeration is enough. To use an enumeration as flags, add the special attribute System.FlagsAttribute . This requires explicit initialization of the values, each of which is raised to a power.

 [System.FlagsAttribute] enum Color : byte { None = 0, Red = 1, // 2 ^ 0 Green = 2, // 2 ^ 1 Blue = 4 // 2 ^ 2 } 

Using the bitwise OR operation, you can combine the elements of an enumeration, and using the HasFlag (Enum) method, check for the presence of bit fields in the instance.

 var color = Color.Red | Color.Green | Color.Blue; var hasFlag = color.HasFlag(Color.Red | Color.Green); // True 

Using the bitwise AND operation, you can also perform checks.

 var aColor = Color.Red | Color.Green; var bColor = Color.Green | Color.Blue; //     var contains = (aColor & bColor) == bColor; // False //     var overlaps = (aColor & bColor) != 0; // True 

Unity transfers


For example, take the code below.

 using UnityEngine; public enum Color { Red, Green, Blue } public class Example : MonoBehaviour { public Color Color; } 

Unity's built-in tools allow you to display enumerations as a drop-down list.



Unfortunately, the editor does not know how to automatically draw enums in the form of flags. For these purposes, a redefinition of the inspector is required, which is not always convenient. But you can go to the trick and override the drawing of enum globally. To begin, modify the example.

 using System; using UnityEngine; [Flags] public enum Color { Red = 1, Green = 2, Blue = 4 } public class Example : MonoBehaviour { public Color Color; } 

Next you need to implement your PropertyDrawer . If the property being serialized has the Flags attribute, then we will use the EditorGUI.MaskField method for drawing, and otherwise the standard EditorGUI.PropertyField method. Also note that a property can be an element of an array. The code below should be placed in a folder named Editor .

 [CustomPropertyDrawer(typeof(Enum), true)] public sealed class EnumPropertyDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { using (new EditorGUI.PropertyScope(position, label, property)) { if (HasEnumFlagsAttribute()) { var intValue = EditorGUI.MaskField(position, label, property.intValue, property.enumDisplayNames); if (property.intValue != intValue) { property.intValue = intValue; } } else { EditorGUI.PropertyField(position, property, label); } } bool HasEnumFlagsAttribute() { var fieldType = fieldInfo.FieldType; if (fieldType.IsArray) { var elementType = fieldType.GetElementType(); return elementType.IsDefined(typeof(FlagsAttribute), false); } return fieldType.IsDefined(typeof(FlagsAttribute), false); } } } 

Now the field is correctly displayed in the inspector for any Enum type.



In addition to the specific enumeration values, the editor adds two more:


Related Links


Source: https://habr.com/ru/post/456852/


All Articles