2021년 4학년 1학기 기업연계프로젝트2 컴퓨터소프트웨어공학과 <원광투어팀> 팀장 : 송유진 팀원 : 김나영, 이경희, 한유진
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.

375 lines
14 KiB

5 years ago
  1. //========= Copyright 2016-2020, HTC Corporation. All rights reserved. ===========
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Reflection;
  6. using UnityEngine;
  7. namespace HTC.UnityPlugin.Utility
  8. {
  9. public static class EnumUtils
  10. {
  11. public const int UINT_MASK_FIELD_LENGTH = sizeof(int) * 8;
  12. public const int ULONG_MASK_FIELD_LENGTH = sizeof(long) * 8;
  13. // this class pares and stored the enum's names and values in different orders
  14. //
  15. // Example:
  16. //
  17. // public enum SomeEnum
  18. // {
  19. // Invalid = -1,
  20. // AAA,
  21. // BBB,
  22. // zzz = -2,
  23. // CCC = 35,
  24. // Default = 0,
  25. // EEE,
  26. // FFF,
  27. // GGG = 65,
  28. // }
  29. //
  30. // EnumDisplayInfo for typeof(SomeEnum) will be:
  31. //
  32. // rawNames | rawValues
  33. // ---------------------
  34. // AAA | 0
  35. // Default | 0
  36. // EEE | 1
  37. // BBB | 1
  38. // FFF | 2
  39. // CCC | 35
  40. // GGG | 65
  41. // zzz | -2
  42. // Invalid | -1
  43. //
  44. // displayedNames | displayedRawNames | displayedValues
  45. // -----------------------------------------------------
  46. // Invalid | Invalid | -1
  47. // AAA | AAA | 0
  48. // BBB | BBB | 1
  49. // zzz | zzz | -2
  50. // CCC | CCC | 35
  51. // Default (AAA) | Default | 0
  52. // EEE (BBB) | EEE | 1
  53. // FFF | FFF | 2
  54. // GGG | GGG | 65
  55. //
  56. // displayedMaskNames | displayedMaskRawNames | displayedMaskValues | realMaskField
  57. // ---------------------------------------------------------------------------------
  58. // AAA | AAA | 0 | 1ul << 0
  59. // BBB | BBB | 1 | 1ul << 1
  60. // CCC | CCC | 35 | 1ul << 35
  61. // Default (AAA) | Default | 0 | 1ul << 0
  62. // EEE (BBB) | EEE | 1 | 1ul << 1
  63. // FFF | FFF | 2 | 1ul << 2
  64. public class EnumDisplayInfo
  65. {
  66. public Type enumType { get; private set; }
  67. public int minValue { get; private set; }
  68. public int maxValue { get; private set; }
  69. public string[] rawNames { get; private set; }
  70. public int[] rawValues { get; private set; }
  71. public Dictionary<int, int> rawValue2index { get; private set; }
  72. public Dictionary<string, int> rawName2index { get; private set; }
  73. public int displayedLength { get { return displayedRawNames.Length; } }
  74. public string[] displayedRawNames { get; private set; } // without parenthesis
  75. public string[] displayedNames { get; private set; }
  76. public int[] displayedValues { get; private set; }
  77. public Dictionary<int, int> value2displayedIndex { get; private set; }
  78. public Dictionary<string, int> name2displayedIndex { get; private set; }
  79. public int displayedMaskLength { get { return displayedMaskRawNames.Length; } }
  80. public string[] displayedMaskRawNames { get; private set; } // without parenthesis
  81. public string[] displayedMaskNames { get; private set; }
  82. public int[] displayedMaskValues { get; private set; }
  83. public ulong[] displayedMaskRealMaskField { get; private set; }
  84. public Dictionary<int, int> value2displayedMaskIndex { get; private set; }
  85. public Dictionary<string, int> name2displayedMaskIndex { get; private set; }
  86. public EnumDisplayInfo(Type type)
  87. {
  88. if (type == null) { throw new ArgumentNullException("type"); }
  89. if (!type.IsEnum) { throw new ArgumentException("Must be enum type", "type"); }
  90. enumType = type;
  91. rawNames = Enum.GetNames(type);
  92. rawValues = Enum.GetValues(type) as int[];
  93. rawValue2index = new Dictionary<int, int>();
  94. rawName2index = new Dictionary<string, int>();
  95. minValue = int.MaxValue;
  96. maxValue = int.MinValue;
  97. {
  98. var index = 0;
  99. foreach (var value in rawValues)
  100. {
  101. minValue = Mathf.Min(minValue, value);
  102. maxValue = Mathf.Max(maxValue, value);
  103. rawName2index[rawNames[index]] = index;
  104. if (!rawValue2index.ContainsKey(value)) { rawValue2index[value] = index; }
  105. ++index;
  106. }
  107. }
  108. var displayedRawNamesList = new List<string>();
  109. var displayedNamesList = new List<string>();
  110. var displayedValuesList = new List<int>();
  111. value2displayedIndex = new Dictionary<int, int>();
  112. name2displayedIndex = new Dictionary<string, int>();
  113. var displayedMaskRawNamesList = new List<string>();
  114. var displayedMaskNamesList = new List<string>();
  115. var displayedMaskValuesList = new List<int>();
  116. var displayedMaskRealMaskFieldList = new List<ulong>();
  117. value2displayedMaskIndex = new Dictionary<int, int>();
  118. name2displayedMaskIndex = new Dictionary<string, int>();
  119. foreach (FieldInfo fi in type.GetFields()
  120. .Where(fi => fi.IsStatic && fi.GetCustomAttributes(typeof(HideInInspector), true).Length == 0)
  121. .OrderBy(fi => fi.MetadataToken))
  122. {
  123. int index;
  124. int priorIndex;
  125. var name = fi.Name;
  126. var value = (int)fi.GetValue(null);
  127. displayedRawNamesList.Add(name);
  128. displayedNamesList.Add(name);
  129. displayedValuesList.Add(value);
  130. index = displayedNamesList.Count - 1;
  131. name2displayedIndex[name] = index;
  132. if (!value2displayedIndex.TryGetValue(value, out priorIndex))
  133. {
  134. value2displayedIndex[value] = index;
  135. }
  136. else
  137. {
  138. displayedNamesList[index] += " (" + displayedNamesList[priorIndex] + ")";
  139. name2displayedIndex[displayedNamesList[index]] = index;
  140. }
  141. if (value < 0 || value >= ULONG_MASK_FIELD_LENGTH) { continue; }
  142. displayedMaskRawNamesList.Add(name);
  143. displayedMaskNamesList.Add(name);
  144. displayedMaskValuesList.Add(value);
  145. displayedMaskRealMaskFieldList.Add(1ul << value);
  146. index = displayedMaskNamesList.Count - 1;
  147. name2displayedMaskIndex[name] = index;
  148. if (!value2displayedMaskIndex.TryGetValue(value, out priorIndex))
  149. {
  150. value2displayedMaskIndex.Add(value, index);
  151. }
  152. else
  153. {
  154. displayedMaskNamesList[index] += " (" + displayedMaskNamesList[priorIndex] + ")";
  155. name2displayedMaskIndex[displayedMaskNamesList[index]] = index;
  156. }
  157. }
  158. displayedRawNames = displayedRawNamesList.ToArray();
  159. displayedNames = displayedNamesList.ToArray();
  160. displayedValues = displayedValuesList.ToArray();
  161. displayedMaskRawNames = displayedMaskRawNamesList.ToArray();
  162. displayedMaskNames = displayedMaskNamesList.ToArray();
  163. displayedMaskValues = displayedMaskValuesList.ToArray();
  164. displayedMaskRealMaskField = displayedMaskRealMaskFieldList.ToArray();
  165. }
  166. [Obsolete]
  167. public int RealToDisplayedMaskField(int realMask)
  168. {
  169. var displayedMask = 0u;
  170. for (int i = 0; i < UINT_MASK_FIELD_LENGTH && realMask != 0; ++i)
  171. {
  172. if (GetFlag((uint)realMask, i))
  173. {
  174. UnsetFlag((uint)realMask, i);
  175. if (value2displayedMaskIndex[i] < UINT_MASK_FIELD_LENGTH)
  176. {
  177. displayedMask |= 1u << value2displayedMaskIndex[i];
  178. }
  179. }
  180. }
  181. return (int)displayedMask;
  182. }
  183. [Obsolete]
  184. public int DisplayedToRealMaskField(int displayedMask, bool fillUp = true)
  185. {
  186. var realMask = 0u;
  187. for (int i = 0; i < UINT_MASK_FIELD_LENGTH && displayedMask != 0; ++i)
  188. {
  189. if (GetFlag((uint)displayedMask, i))
  190. {
  191. UnsetFlag((uint)displayedMask, i);
  192. if (i < UINT_MASK_FIELD_LENGTH)
  193. {
  194. realMask |= (uint)displayedMaskRealMaskField[i];
  195. }
  196. }
  197. }
  198. return (int)realMask;
  199. }
  200. }
  201. private static Dictionary<Type, EnumDisplayInfo> s_enumInfoTable = new Dictionary<Type, EnumDisplayInfo>();
  202. public static EnumDisplayInfo GetDisplayInfo(Type type)
  203. {
  204. EnumDisplayInfo info;
  205. if (!s_enumInfoTable.TryGetValue(type, out info))
  206. {
  207. info = new EnumDisplayInfo(type);
  208. s_enumInfoTable.Add(type, info);
  209. }
  210. return info;
  211. }
  212. public static int GetMinValue(Type enumType)
  213. {
  214. return GetDisplayInfo(enumType).minValue;
  215. }
  216. public static int GetMaxValue(Type enumType)
  217. {
  218. return GetDisplayInfo(enumType).maxValue;
  219. }
  220. public static bool GetFlag(uint maskField, int enumValue)
  221. {
  222. if (enumValue < 0 || enumValue >= UINT_MASK_FIELD_LENGTH) { return false; }
  223. return (maskField & (1u << enumValue)) != 0u;
  224. }
  225. public static void SetFlag(ref uint maskField, int enumValue, bool value)
  226. {
  227. if (enumValue < 0 || enumValue >= UINT_MASK_FIELD_LENGTH) { return; }
  228. if (value)
  229. {
  230. maskField |= (1u << enumValue);
  231. }
  232. else
  233. {
  234. maskField &= ~(1u << enumValue);
  235. }
  236. }
  237. public static void SetFlag(ref uint maskField, bool value, int enumValue, params int[] enumValues)
  238. {
  239. SetFlag(ref maskField, enumValue, value);
  240. if (enumValues != null && enumValues.Length > 0)
  241. {
  242. foreach (var ev in enumValues) { SetFlag(ref maskField, ev, value); }
  243. }
  244. }
  245. public static uint SetFlag(uint maskField, int enumValue, params int[] enumValues)
  246. {
  247. if (enumValue >= 0 && enumValue < UINT_MASK_FIELD_LENGTH) { maskField |= (1u << enumValue); }
  248. if (enumValues != null && enumValues.Length > 0)
  249. {
  250. foreach (var ev in enumValues)
  251. {
  252. if (ev >= 0 && ev < UINT_MASK_FIELD_LENGTH) { maskField |= (1u << ev); }
  253. }
  254. }
  255. return maskField;
  256. }
  257. public static uint UnsetFlag(uint maskField, int enumValue, params int[] enumValues)
  258. {
  259. if (enumValue >= 0 && enumValue < UINT_MASK_FIELD_LENGTH) { maskField &= ~(1u << enumValue); }
  260. if (enumValues != null && enumValues.Length > 0)
  261. {
  262. foreach (var ev in enumValues)
  263. {
  264. if (ev >= 0 && ev < UINT_MASK_FIELD_LENGTH) { maskField &= ~(1u << ev); }
  265. }
  266. }
  267. return maskField;
  268. }
  269. public static bool GetFlag(ulong maskField, int enumValue)
  270. {
  271. if (enumValue < 0 || enumValue >= ULONG_MASK_FIELD_LENGTH) { return false; }
  272. return (maskField & (1ul << enumValue)) != 0ul;
  273. }
  274. public static void SetFlag(ref ulong maskField, int enumValue, bool value)
  275. {
  276. if (enumValue < 0 || enumValue >= ULONG_MASK_FIELD_LENGTH) { return; }
  277. if (value)
  278. {
  279. maskField |= (1ul << enumValue);
  280. }
  281. else
  282. {
  283. maskField &= ~(1ul << enumValue);
  284. }
  285. }
  286. public static void SetFlag(ref ulong maskField, bool value, int enumValue, params int[] enumValues)
  287. {
  288. SetFlag(ref maskField, enumValue, value);
  289. if (enumValues != null && enumValues.Length > 0)
  290. {
  291. foreach (var ev in enumValues) { SetFlag(ref maskField, ev, value); }
  292. }
  293. }
  294. public static ulong SetFlag(ulong maskField, int enumValue, params int[] enumValues)
  295. {
  296. if (enumValue >= 0 && enumValue < ULONG_MASK_FIELD_LENGTH) { maskField |= (1ul << enumValue); }
  297. if (enumValues != null && enumValues.Length > 0)
  298. {
  299. foreach (var ev in enumValues)
  300. {
  301. if (ev >= 0 && ev < ULONG_MASK_FIELD_LENGTH) { maskField |= (1ul << ev); }
  302. }
  303. }
  304. return maskField;
  305. }
  306. public static ulong UnsetFlag(ulong maskField, int enumValue, params int[] enumValues)
  307. {
  308. if (enumValue >= 0 && enumValue < ULONG_MASK_FIELD_LENGTH) { maskField &= ~(1ul << enumValue); }
  309. if (enumValues != null && enumValues.Length > 0)
  310. {
  311. foreach (var ev in enumValues)
  312. {
  313. if (ev >= 0 && ev < ULONG_MASK_FIELD_LENGTH) { maskField &= ~(1ul << ev); }
  314. }
  315. }
  316. return maskField;
  317. }
  318. }
  319. }