You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
12 KiB
325 lines
12 KiB
//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== |
|
|
|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Reflection; |
|
using UnityEngine; |
|
|
|
namespace HTC.UnityPlugin.Utility |
|
{ |
|
public static class EnumUtils |
|
{ |
|
public const int UINT_MASK_FIELD_LENGTH = sizeof(int) * 8; |
|
public const int ULONG_MASK_FIELD_LENGTH = sizeof(long) * 8; |
|
|
|
// this class pares and stored the enum's names and values in different orders |
|
// |
|
// Example: |
|
// |
|
// public enum SomeEnum |
|
// { |
|
// Invalid = -1, |
|
// AAA, |
|
// BBB, |
|
// zzz = -2, |
|
// CCC = 35, |
|
// Default = 0, |
|
// EEE, |
|
// FFF, |
|
// } |
|
// |
|
// EnumDisplayInfo for typeof(SomeEnum) will be: |
|
// |
|
// rawNames | rawValues |
|
// --------------------- |
|
// AAA | 0 |
|
// Default | 0 |
|
// EEE | 1 |
|
// BBB | 1 |
|
// FFF | 2 |
|
// CCC | 35 |
|
// zzz | -2 |
|
// Invalid | -1 |
|
// |
|
// displayedNames | displayedRawNames | displayedValues |
|
// ----------------------------------------------------- |
|
// Invalid | Invalid | -1 |
|
// AAA | AAA | 0 |
|
// BBB | BBB | 1 |
|
// zzz | zzz | -2 |
|
// CCC | CCC | 35 |
|
// Default (AAA) | Default | 0 |
|
// EEE (BBB) | EEE | 1 |
|
// FFF | FFF | 2 |
|
// |
|
// displayedMaskNames | displayedMaskRawNames | displayedMaskValues | realMaskField |
|
// --------------------------------------------------------------------------------- |
|
// AAA | AAA | 0 | 1u << 0 |
|
// BBB | BBB | 1 | 1u << 1 |
|
// Default (AAA) | Default | 0 | 1u << 0 |
|
// EEE (BBB) | EEE | 1 | 1u << 1 |
|
// FFF | FFF | 2 | 1u << 2 |
|
|
|
public class EnumDisplayInfo |
|
{ |
|
public Type enumType { get; private set; } |
|
|
|
public int minValue { get; private set; } |
|
public int maxValue { get; private set; } |
|
|
|
public string[] rawNames { get; private set; } |
|
public int[] rawValues { get; private set; } |
|
public Dictionary<int, int> rawValue2index { get; private set; } |
|
public Dictionary<string, int> rawName2index { get; private set; } |
|
|
|
public string[] displayedRawNames { get; private set; } // without parenthesis |
|
public string[] displayedNames { get; private set; } |
|
public int[] displayedValues { get; private set; } |
|
public Dictionary<int, int> value2displayedIndex { get; private set; } |
|
public Dictionary<string, int> name2displayedIndex { get; private set; } |
|
|
|
public string[] displayedMaskRawNames { get; private set; } // without parenthesis |
|
public string[] displayedMaskNames { get; private set; } |
|
public int[] displayedMaskValues { get; private set; } |
|
public Dictionary<int, int> value2displayedMaskIndex { get; private set; } |
|
public Dictionary<string, int> name2displayedMaskIndex { get; private set; } |
|
|
|
public Dictionary<int, uint> value2displayedMaskField { get; private set; } |
|
public List<uint> displayedMaskIndex2realMaskField { get; private set; } |
|
|
|
public EnumDisplayInfo(Type type) |
|
{ |
|
if (type == null) { throw new ArgumentNullException("type"); } |
|
if (!type.IsEnum) { throw new ArgumentException("Must be enum type", "type"); } |
|
|
|
enumType = type; |
|
rawNames = Enum.GetNames(type); |
|
rawValues = Enum.GetValues(type) as int[]; |
|
rawValue2index = new Dictionary<int, int>(); |
|
rawName2index = new Dictionary<string, int>(); |
|
minValue = int.MaxValue; |
|
maxValue = int.MinValue; |
|
|
|
{ |
|
var index = 0; |
|
foreach (var value in rawValues) |
|
{ |
|
minValue = Mathf.Min(minValue, value); |
|
maxValue = Mathf.Max(maxValue, value); |
|
|
|
rawName2index[rawNames[index]] = index; |
|
|
|
if (!rawValue2index.ContainsKey(value)) { rawValue2index[value] = index; } |
|
|
|
++index; |
|
} |
|
} |
|
|
|
var displayedRawNamesList = new List<string>(); |
|
var displayedNamesList = new List<string>(); |
|
var displayedValuesList = new List<int>(); |
|
value2displayedIndex = new Dictionary<int, int>(); |
|
name2displayedIndex = new Dictionary<string, int>(); |
|
|
|
var displayedMaskRawNamesList = new List<string>(); |
|
var displayedMaskNamesList = new List<string>(); |
|
var displayedMaskValuesList = new List<int>(); |
|
value2displayedMaskIndex = new Dictionary<int, int>(); |
|
name2displayedMaskIndex = new Dictionary<string, int>(); |
|
|
|
value2displayedMaskField = new Dictionary<int, uint>(); |
|
displayedMaskIndex2realMaskField = new List<uint>(); |
|
|
|
foreach (FieldInfo fi in type.GetFields() |
|
.Where(fi => fi.IsStatic && fi.GetCustomAttributes(typeof(HideInInspector), true).Length == 0) |
|
.OrderBy(fi => fi.MetadataToken)) |
|
{ |
|
int index; |
|
int priorIndex; |
|
var name = fi.Name; |
|
var value = (int)fi.GetValue(null); |
|
|
|
displayedRawNamesList.Add(name); |
|
displayedNamesList.Add(name); |
|
displayedValuesList.Add(value); |
|
index = displayedNamesList.Count - 1; |
|
|
|
name2displayedIndex[name] = index; |
|
|
|
if (!value2displayedIndex.TryGetValue(value, out priorIndex)) |
|
{ |
|
value2displayedIndex[value] = index; |
|
} |
|
else |
|
{ |
|
displayedNamesList[index] += " (" + displayedNamesList[priorIndex] + ")"; |
|
name2displayedIndex[displayedNamesList[index]] = index; |
|
} |
|
|
|
if (value < 0 || value >= UINT_MASK_FIELD_LENGTH) { continue; } |
|
|
|
displayedMaskRawNamesList.Add(name); |
|
displayedMaskNamesList.Add(name); |
|
displayedMaskValuesList.Add(value); |
|
index = displayedMaskNamesList.Count - 1; |
|
|
|
name2displayedMaskIndex[name] = index; |
|
|
|
if (!value2displayedMaskIndex.TryGetValue(value, out priorIndex)) |
|
{ |
|
value2displayedMaskIndex.Add(value, index); |
|
value2displayedMaskField.Add(value, 1u << index); |
|
} |
|
else |
|
{ |
|
displayedMaskNamesList[index] += " (" + displayedMaskNamesList[priorIndex] + ")"; |
|
name2displayedMaskIndex[displayedMaskNamesList[index]] = index; |
|
value2displayedMaskField[value] |= 1u << index; |
|
} |
|
|
|
displayedMaskIndex2realMaskField.Add(1u << value); |
|
} |
|
|
|
displayedRawNames = displayedRawNamesList.ToArray(); |
|
displayedNames = displayedNamesList.ToArray(); |
|
displayedValues = displayedValuesList.ToArray(); |
|
|
|
displayedMaskRawNames = displayedRawNamesList.ToArray(); |
|
displayedMaskNames = displayedMaskNamesList.ToArray(); |
|
displayedMaskValues = displayedMaskValuesList.ToArray(); |
|
} |
|
|
|
public int RealToDisplayedMaskField(int realMask) |
|
{ |
|
var displayedMask = 0u; |
|
var mask = 1u; |
|
|
|
for (int value = 0; value < UINT_MASK_FIELD_LENGTH && realMask != 0; ++value, mask <<= 1) |
|
{ |
|
uint mk; |
|
if ((realMask & mask) > 0 && value2displayedMaskField.TryGetValue(value, out mk)) |
|
{ |
|
displayedMask |= mk; |
|
} |
|
} |
|
|
|
return (int)displayedMask; |
|
} |
|
|
|
public int DisplayedToRealMaskField(int displayedMask, bool fillUp = true) |
|
{ |
|
var uDisMask = (uint)displayedMask; |
|
var realMask = 0u; |
|
|
|
for (int index = 0; index < displayedMaskValues.Length && uDisMask != 0; ++index) |
|
{ |
|
var mask = value2displayedMaskField[displayedMaskValues[index]]; |
|
|
|
if (fillUp) |
|
{ |
|
if ((uDisMask & mask) > 0) |
|
{ |
|
realMask |= displayedMaskIndex2realMaskField[index]; |
|
} |
|
} |
|
else |
|
{ |
|
if ((uDisMask & mask) == mask) |
|
{ |
|
realMask |= displayedMaskIndex2realMaskField[index]; |
|
} |
|
} |
|
} |
|
|
|
return (int)realMask; |
|
} |
|
} |
|
|
|
private static Dictionary<Type, EnumDisplayInfo> s_enumInfoTable = new Dictionary<Type, EnumDisplayInfo>(); |
|
|
|
public static EnumDisplayInfo GetDisplayInfo(Type type) |
|
{ |
|
EnumDisplayInfo info; |
|
if (!s_enumInfoTable.TryGetValue(type, out info)) |
|
{ |
|
info = new EnumDisplayInfo(type); |
|
s_enumInfoTable.Add(type, info); |
|
} |
|
|
|
return info; |
|
} |
|
|
|
public static int GetMinValue(Type enumType) |
|
{ |
|
return GetDisplayInfo(enumType).minValue; |
|
} |
|
|
|
public static int GetMaxValue(Type enumType) |
|
{ |
|
return GetDisplayInfo(enumType).maxValue; |
|
} |
|
|
|
public static bool GetFlag(uint maskField, int enumValue) |
|
{ |
|
if (enumValue < 0 || enumValue >= UINT_MASK_FIELD_LENGTH) { return false; } |
|
return (maskField & (1u << enumValue)) != 0u; |
|
} |
|
|
|
public static void SetFlag(ref uint maskField, int enumValue, bool value) |
|
{ |
|
if (enumValue < 0 || enumValue >= UINT_MASK_FIELD_LENGTH) { return; } |
|
if (value) |
|
{ |
|
maskField |= (1u << enumValue); |
|
} |
|
else |
|
{ |
|
maskField &= ~(1u << enumValue); |
|
} |
|
} |
|
|
|
public static uint SetFlag(uint maskField, int enumValue) |
|
{ |
|
if (enumValue < 0 || enumValue >= UINT_MASK_FIELD_LENGTH) { return maskField; } |
|
return maskField | (1u << enumValue); |
|
} |
|
|
|
public static uint UnsetFlag(uint maskField, int enumValue) |
|
{ |
|
if (enumValue < 0 || enumValue >= UINT_MASK_FIELD_LENGTH) { return maskField; } |
|
return maskField & ~(1u << enumValue); |
|
} |
|
|
|
public static bool GetFlag(ulong maskField, int enumValue) |
|
{ |
|
if (enumValue < 0 || enumValue >= ULONG_MASK_FIELD_LENGTH) { return false; } |
|
return (maskField & (1ul << enumValue)) != 0ul; |
|
} |
|
|
|
public static void SetFlag(ref ulong maskField, int enumValue, bool value) |
|
{ |
|
if (enumValue < 0 || enumValue >= UINT_MASK_FIELD_LENGTH) { return; } |
|
if (value) |
|
{ |
|
maskField |= (1u << enumValue); |
|
} |
|
else |
|
{ |
|
maskField &= ~(1u << enumValue); |
|
} |
|
} |
|
|
|
public static ulong SetFlag(ulong maskField, int enumValue) |
|
{ |
|
if (enumValue < 0 || enumValue >= ULONG_MASK_FIELD_LENGTH) { return maskField; } |
|
return maskField | (1ul << enumValue); |
|
} |
|
|
|
public static ulong UnsetFlag(ulong maskField, int enumValue) |
|
{ |
|
if (enumValue < 0 || enumValue >= ULONG_MASK_FIELD_LENGTH) { return maskField; } |
|
return maskField & ~(1ul << enumValue); |
|
} |
|
} |
|
} |