Support for long for EditorGUILayout.MaskField

It would be useful to support long for EditorGUILayout.MaskField. Having to narrow down to 32 bits feels really restrictive. 64 would be great help.

Please this is still very much needed for my workflow.

Why not just write your own property drawer for this?

Honestly the number of custom inspectors I have to rely on and maintain is unreal. If Unity could get this one right at least it would be a blessing. Beside I don’t even know how I would get started. Seems like every option menu (allowing multiple selected), only supports integers.

Iunno, start with the C# ref? UnityCsReference/Editor/Mono/Inspector/MaskFieldDropdown.cs at master · Unity-Technologies/UnityCsReference · GitHub

I suspect that this is the way it is for one or more technical reasons which would be “getting it right”, but I wouldn’t be surprised if it were technical debt which would be annoying but equally unchangeable. I checked UI Elements which is intended to replace IMGUI for creating editors and it still uses 32-bits.

https://docs.unity3d.com/Packages/com.unity.ui@1.0/api/UnityEditor.UIElements.MaskField.html

I started building this but I can’t get it to work. Maybe someone else can, and share it. Let’s help each other out!

    public static class ExtendedEditorGUI
    {
        public static long LongMaskField(Rect position, string label,long mask, string[] displayedOptions)
        {
            float width = 100;
            EditorGUI.LabelField(new Rect(position.x, position.y, width, position.height), label);
            position = new Rect(width + 10, position.y, position.width - width - 10, position.height);

            if (EditorGUI.DropdownButton(position, new GUIContent(GetMaskString(mask, displayedOptions)), FocusType.Keyboard))
            {
                GenericMenu menu = new GenericMenu();

                bool nothing = false;
                if (mask == 0) { nothing = true; }
                menu.AddItem(new GUIContent("Nothing"), nothing, () =>
                {
                    mask = 0;

                });

                bool all = false;
                if (mask == -1) { all = true; }
                menu.AddItem(new GUIContent("Everything"), all, () =>
                {
                    mask = -1;

                });

                for (int i = 0; i < displayedOptions.Length; i++)
                {
                    int index = i; // Capture the index for the closure
                    bool isSet = (mask & (1L << i)) != 0;
                    menu.AddItem(new GUIContent(displayedOptions[i]), isSet, () =>
                    {
                        mask = ToggleMask(mask, index);

                    });
                }
                menu.DropDown(position);

            }

            return mask;
        }

        private static long ToggleMask(long mask, int index)
        {
            if ((mask & (1L << index)) != 0)
            {
                mask &= ~(1L << index);
            }
            else
            {
                mask |= (1L << index);
            }
            return mask;
        }

        private static string GetMaskString(long mask, string[] displayedOptions)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            if (mask == -1) { sb.Append("Everything"); return sb.ToString(); }
            for (int i = 0; i < displayedOptions.Length; i++)
            {
                if ((mask & (1L << i)) != 0)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(", ");
                    }
                    sb.Append(displayedOptions[i]);
                }
            }
            return sb.Length > 0 ? sb.ToString() : "Nothing";
        }
    }

So for some reason the mask value is not returning to the LongMaskField method when clicking the menu item. (line 17, 25 and 36) Apart from that, I believe this is the right approach.

From a custom editor or property drawer, you should call:

bitmask = ExtendedEditorGUI.LongMaskField(position,"mask",bitmask,options);