[Unity]在编辑器中实现位操作(Bit)的编辑

2020/04 18 08:04

有些时候,想高效利用数据,把一个int(32位)掰成32个bool值。那么编辑器中有没有一个这样的插件支持呢?

以下是代码

using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Reflection;
 
public enum MyEnum
{
	Enum1 = 1,
	Enum2 = 2,
}
 
public class MyEnumFieldName
{
	public const string Enum1 = @"第一位";
	public const string Enum2 = @"第一位";
}
 
public class BitMaskAttribute : PropertyAttribute
{
	public BitMaskAttribute()
	{
	}
}
 
[CustomPropertyDrawer(typeof(BitMaskAttribute))]
public class BitMaskDrawer : PropertyDrawer
{
    private float extraHeight = 20.0f;
    private static bool showValues = true;
    private bool hasError = false;
 
    public string GetFieldName(string enumName)
    {
        string className = string.Format("{0}FieldName", this.fieldInfo.FieldType.Name);
        Type classType = Type.GetType(className);
        if (classType != null)
        {
            FieldInfo fi = classType.GetField(enumName);
            if (fi != null)
            {
                return fi.GetValue(null).ToString();
            }
        }
 
        return enumName;
    }
 
    public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label)
    {
        if (CheckInvalid(position, prop, label))
        {
            return;
        }
 
        showValues = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, extraHeight), showValues, label);
 
        if (!showValues)
        {
            return;
        }
 
        EditorGUI.indentLevel++;
 
        for (int i = 0; i < prop.enumNames.Length; i++)
        {
            bool toggleValue = (prop.intValue & (1 << i)) == (1 << i);
 
            Rect rect = new Rect(position.x, position.y + ((i + 1) * extraHeight), position.width, extraHeight);
            string enumTitle = GetFieldName(prop.enumNames [i]);
            if (EditorGUI.Toggle(rect, enumTitle, toggleValue))
            {
                prop.intValue |= 1 << i;
            } else
            {
                prop.intValue &= ~(1 << i);
            }
        }
    }
 
    private bool CheckInvalid(Rect position, SerializedProperty prop, GUIContent label)
    {
        if (prop.propertyType != SerializedPropertyType.Enum)
        {
            showValues = false;
            hasError = true;
            return true;
        }
 
        return false;
    }
 
    public override float GetPropertyHeight(SerializedProperty prop, GUIContent label)
    {
        if (!showValues)
        {
            if (!hasError)
            {
                return base.GetPropertyHeight(prop, label);
            } else
            {
                return base.GetPropertyHeight(prop, label) + extraHeight;
            }
        }
        return base.GetPropertyHeight(prop, label) * (prop.enumNames.Length + 3);
    }
}

用的时候很简单,只需要一句:

[BitMask] public MyEnum enumData;

在编辑器看效果吧