Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Editor bit mask

Discussion in 'Scripting' started by gads, Jan 17, 2009.

  1. gads

    gads

    Joined:
    Oct 10, 2008
    Posts:
    34
    Hi everyone,

    I have an enum that acts like a bitmaks, and now I would like to have it in Editor with the same behavior as the Camera->CullingMask.

    My enum is something like this:
    Code (csharp):
    1. [Flags]
    2. public enum MyFlags {
    3.   None = 0,
    4.   A = 1 << 0,
    5.   B = 1 << 1,
    6.   C = 1 << 2,
    7.   All = A | B | C,
    8. }
    how can I do this?
    Thanks.
     
  2. Bugfoot

    Bugfoot

    Joined:
    Jan 9, 2009
    Posts:
    533
    I'd be interested to know this as well.
     
  3. orb_9

    orb_9

    Joined:
    Feb 10, 2010
    Posts:
    47
    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?

    Working in Unity3 here.
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You can use the LayerMask type to get that nice dropdown, but I don't know if you can do that with enums.

    --Eric
     
  5. orb_9

    orb_9

    Joined:
    Feb 10, 2010
    Posts:
    47
    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. :(
     
  6. BitFish

    BitFish

    Joined:
    Nov 5, 2010
    Posts:
    21
    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);

    // Properties
    public int value { get; set; }
    }
     
    Last edited: Dec 17, 2010
  7. OP_toss

    OP_toss

    Joined:
    Oct 19, 2012
    Posts:
    19
  8. Marco-Sperling

    Marco-Sperling

    Joined:
    Mar 5, 2012
    Posts:
    620
    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:
    Code (csharp):
    1.  
    2. [Flags]
    3.  public enum VertexEffect
    4.  {
    5.  //None = 0,
    6.  Glow = 1,
    7.  Refraction = 2,
    8.  Shadow = 4
    9.  }
    10.  
    11. m_vertexEffects.intValue = (int)((VertexEffect)EditorGUILayout.EnumMaskField("Vertex Effects", (VertexEffect)m_vertexEffects.intValue));
    12.  
     
  9. Marco-Sperling

    Marco-Sperling

    Joined:
    Mar 5, 2012
    Posts:
    620
    So is this a bug? Or is it intended behaviour and I am just doing something wrong when casting from my enum to int?
     
  10. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    968
    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.
     
  11. Titos

    Titos

    Joined:
    Jul 26, 2012
    Posts:
    12
    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,
    }

    enum EditingMode : uint {
    STANDARD = (uint)EditFlag.GLOBAL_ROTATION | (uint)EditFlag.SCALING,
    ALT1 = (uint)EditFlag.LOCAL_ROTATION | (uint)EditFlag.SCALING,
    }

    etc etc.. Will do it
     
  12. ulfsvarti

    ulfsvarti

    Joined:
    Apr 24, 2015
    Posts:
    1
  13. MetaMythril

    MetaMythril

    Joined:
    May 5, 2010
    Posts:
    150
    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.

    Any ideas?
     
  14. Jadefire16

    Jadefire16

    Joined:
    Jul 14, 2019
    Posts:
    19
    mateomogar likes this.
  15. FaffyWaffles

    FaffyWaffles

    Joined:
    Apr 10, 2020
    Posts:
    45
    My goodness, this thread transcends generations.
     
  16. theonlysake

    theonlysake

    Joined:
    Dec 12, 2019
    Posts:
    4
    Let's bring it back one more time, since none of the answers are now correct!

    The OFFICIAL way of showing an Enum as a bitmask can be achieved simply by following the Unity Scripting API Documentation for:

    EditorGUI.EnumFlagsField

    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:

    Code (CSharp):
    1. # if UNITY_EDITOR
    2. using System;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6. public class EnumMaskAttribute : PropertyAttribute
    7. {
    8.     public Type EnumType;
    9.     public Enum Enum;
    10.     public EnumMaskAttribute(Type enumType)
    11.     {
    12.         this.EnumType = enumType;
    13.         this.Enum = (Enum)Enum.GetValues(enumType).GetValue(0);
    14.     }
    15. }
    16.  
    17. [CustomPropertyDrawer(typeof(EnumMaskAttribute))]
    18. public class EnumMaskDrawer : PropertyDrawer
    19. {
    20.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    21.     {
    22.         EnumMaskAttribute enumMaskAttribute = attribute as EnumMaskAttribute;
    23.         enumMaskAttribute.Enum = EditorGUI.EnumFlagsField(position, label, enumMaskAttribute.Enum);
    24.         if (enumMaskAttribute.EnumType == typeof(Enum))
    25.         {
    26.             Debug.Log(enumMaskAttribute.Enum);
    27.             property.intValue = Convert.ToInt32(Enum.Parse(enumMaskAttribute.EnumType, Enum.GetName(enumMaskAttribute.EnumType, enumMaskAttribute.Enum)));
    28.         }
    29.         else
    30.         {
    31.             property.intValue = Convert.ToInt32(enumMaskAttribute.Enum);
    32.         }
    33.     }
    34. }
    35. #endif


    Now. Create another script called `EnumMaskAttributeTest` and replace it's contents with the following:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public enum TestEnum
    4. {
    5.     A = 1 << 0,
    6.     B = 1 << 1,
    7.     C = 1 << 2
    8. }
    9.  
    10. public class EnumMaskAttributeTest : MonoBehaviour
    11. {
    12.     [EnumMask(typeof(TestEnum))]
    13.     public int testEnumMask;
    14. }
    15.  


    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 )
     
    Last edited: Sep 9, 2021
  17. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    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
    Code (csharp):
    1. public enum TestFlags {
    2.   A = 0x1,
    3.   B = 0x2,
    4.   C = 0x4,
    5.   D = 0x10, // etc
    6. }
    or in binary
    Code (csharp):
    1. public enum TestFlags {
    2.   A = 0b1,
    3.   B = 0b10,
    4.   C = 0b100,
    5.   D = 0b1000, // etc
    6. }
    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.
     
    theonlysake likes this.
  18. sidchou

    sidchou

    Joined:
    Apr 13, 2020
    Posts:
    12
    just need to create the variable as the enum

    Code (CSharp):
    1.    [Flags]
    2.     public enum BitMask
    3.     {
    4.         None = 0,
    5.         Walk= 1,
    6.         Run = 2,
    7.         Jump = 4,
    8.         Attack = 8
    9.     }
    10.    public BitMask bitMask;

    so generally you already have the right idea

    https://medium.com/@sidchou93/creating-bitmask-216f8d154a32
     
  19. CodeRonnie

    CodeRonnie

    Joined:
    Oct 2, 2015
    Posts:
    287
    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.