VR模拟枪支打靶,消灭鬼怪,换弹以及上弦等等硬核枪支操作。 使用HTCVive设备,开启SteamVR进行游玩。
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

3 years ago
//========= 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);
}
}
}