// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. using System; using System.Reflection; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace HoloToolkit.Unity { // Displays an enum value as a set of checkboxes [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public sealed class EnumCheckboxAttribute : DrawOverrideAttribute { public string DefaultName { get; private set; } public int DefaultValue { get; private set; } public int ValueOnZero { get; private set; } public bool IgnoreNone { get; private set; } public bool IgnoreAll { get; private set; } public string CustomLabel { get; private set; } public EnumCheckboxAttribute(string customLabel = null) { DefaultName = null; DefaultValue = 0; ValueOnZero = 0; IgnoreNone = true; IgnoreAll = true; CustomLabel = customLabel; } public EnumCheckboxAttribute(bool ignoreNone, bool ignoreAll, string customLabel = null) { DefaultName = null; DefaultValue = 0; ValueOnZero = 0; IgnoreNone = ignoreNone; IgnoreAll = ignoreAll; CustomLabel = customLabel; } public EnumCheckboxAttribute(string defaultName, object defaultValue, object valueOnZero = null, bool ignoreNone = true, bool ignoreAll = true, string customLabel = null) { DefaultName = defaultName; DefaultValue = Convert.ToInt32(defaultValue); ValueOnZero = Convert.ToInt32(valueOnZero); IgnoreNone = ignoreNone; IgnoreAll = ignoreAll; CustomLabel = customLabel; } #if UNITY_EDITOR public override void DrawEditor(UnityEngine.Object target, FieldInfo field, SerializedProperty property) { int value = EnumCheckbox( (string.IsNullOrEmpty(CustomLabel) ? SplitCamelCase(field.Name) : CustomLabel), field.GetValue(target), DefaultName, DefaultValue, ValueOnZero, IgnoreNone, IgnoreAll); field.SetValue(target, value); } public override void DrawEditor(UnityEngine.Object target, PropertyInfo prop) { int value = EnumCheckbox( (string.IsNullOrEmpty(CustomLabel) ? SplitCamelCase(prop.Name) : CustomLabel), prop.GetValue(target, null), DefaultName, DefaultValue, ValueOnZero, IgnoreNone, IgnoreAll); prop.SetValue(target, value, null); } private static int EnumCheckbox(string label, object enumObj, string defaultName, object defaultVal, object valOnZero, bool ignoreNone = true, bool ignoreAll = true) { if (!enumObj.GetType().IsEnum) { throw new ArgumentException("enumObj must be an enum."); } // Convert enum value to an int64 so we can treat it as a flag set int enumFlags = Convert.ToInt32(enumObj); EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.LabelField(label, EditorStyles.miniLabel); GUIStyle styleHR = new GUIStyle(GUI.skin.box); styleHR.stretchWidth = true; styleHR.fixedHeight = 2; GUILayout.Box("", styleHR); System.Array enumVals = Enum.GetValues(enumObj.GetType()); int lastvalue = Convert.ToInt32(enumVals.GetValue(enumVals.GetLength(0) - 1)); foreach (object enumVal in enumVals) { int flagVal = Convert.ToInt32(enumVal); if (ignoreNone && flagVal == 0 && enumVal.ToString().ToLower() == "none") { continue; } if (ignoreAll && flagVal == lastvalue && enumVal.ToString().ToLower() == "all") { continue; } bool selected = (flagVal & enumFlags) != 0; selected = EditorGUILayout.Toggle(enumVal.ToString(), selected); // If it's selected add it to the enumObj, otherwise remove it if (selected) { enumFlags |= flagVal; } else { enumFlags &= ~flagVal; } } if (!string.IsNullOrEmpty(defaultName)) { if (GUILayout.Button(defaultName, EditorStyles.miniButton)) { enumFlags = Convert.ToInt32(defaultVal); } } EditorGUILayout.EndVertical(); if (enumFlags == 0) { enumFlags = Convert.ToInt32(valOnZero); } return enumFlags; } #endif } }