Assignment for RMIT Mixed Reality in 2020
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.

146 lines
6.4 KiB

  1. // SDK Description|SDK_Base|002
  2. namespace VRTK
  3. {
  4. #if UNITY_EDITOR
  5. using UnityEditor;
  6. #endif
  7. using System;
  8. using System.Linq;
  9. /// <summary>
  10. /// Describes a class that represents an SDK. Only allowed on classes that inherit from SDK_Base.
  11. /// </summary>
  12. [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
  13. public sealed class SDK_DescriptionAttribute : Attribute
  14. {
  15. /// <summary>
  16. /// The pretty name of the SDK. Uniquely identifies the SDK.
  17. /// </summary>
  18. public readonly string prettyName;
  19. /// <summary>
  20. /// The scripting define symbol needed for the SDK. Needs to be the same as `SDK_ScriptingDefineSymbolPredicateAttribute.symbol` to add and remove the scripting define symbol automatically using VRTK_SDKManager.
  21. /// </summary>
  22. public readonly string symbol;
  23. /// <summary>
  24. /// The name of the VR Device to load.
  25. /// </summary>
  26. public readonly string vrDeviceName;
  27. /// <summary>
  28. /// The index of this attribute, in case there are multiple on the same target.
  29. /// </summary>
  30. public readonly int index;
  31. #if UNITY_EDITOR
  32. /// <summary>
  33. /// The build target group this SDK is for.
  34. /// </summary>
  35. public BuildTargetGroup buildTargetGroup;
  36. #endif
  37. /// <summary>
  38. /// Whether this description describes a fallback SDK.
  39. /// </summary>
  40. public bool describesFallbackSDK
  41. {
  42. get
  43. {
  44. return prettyName == "Fallback";
  45. }
  46. }
  47. /// <summary>
  48. /// Creates a new attribute.
  49. /// </summary>
  50. /// <param name="prettyName">The pretty name of the SDK. Uniquely identifies the SDK. `null` and `string.Empty` aren't allowed.</param>
  51. /// <param name="symbol">The scripting define symbol needed for the SDK. Needs to be the same as `SDK_ScriptingDefineSymbolPredicateAttribute.symbol` to add and remove the scripting define symbol automatically using VRTK_SDKManager. `null` and `string.Empty` are allowed.</param>
  52. /// <param name="vrDeviceName">The name of the VR Device to load. Set to `null` or `string.Empty` if no VR Device is needed.</param>
  53. /// <param name="buildTargetGroupName">The name of a constant of `BuildTargetGroup`. `BuildTargetGroup.Unknown`, `null` and `string.Empty` are not allowed.</param>
  54. /// <param name="index">The index of this attribute, in case there are multiple on the same target.</param>
  55. public SDK_DescriptionAttribute(string prettyName, string symbol, string vrDeviceName, string buildTargetGroupName, int index = 0)
  56. {
  57. if (prettyName == null)
  58. {
  59. VRTK_Logger.Fatal(new ArgumentNullException("prettyName"));
  60. return;
  61. }
  62. if (prettyName == string.Empty)
  63. {
  64. VRTK_Logger.Fatal(new ArgumentOutOfRangeException("prettyName", prettyName, "An empty string isn't allowed."));
  65. return;
  66. }
  67. this.prettyName = prettyName;
  68. this.symbol = symbol;
  69. this.vrDeviceName = string.IsNullOrEmpty(vrDeviceName) ? "None" : vrDeviceName;
  70. this.index = index;
  71. if (string.IsNullOrEmpty(buildTargetGroupName))
  72. {
  73. buildTargetGroupName = "Unknown";
  74. }
  75. #if UNITY_EDITOR
  76. Type buildTargetGroupType = typeof(BuildTargetGroup);
  77. try
  78. {
  79. buildTargetGroup = (BuildTargetGroup)Enum.Parse(buildTargetGroupType, buildTargetGroupName);
  80. }
  81. catch (Exception exception)
  82. {
  83. VRTK_Logger.Fatal(new ArgumentOutOfRangeException(string.Format("'{0}' isn't a valid constant name of '{1}'.", buildTargetGroupName, buildTargetGroupType.Name), exception));
  84. return;
  85. }
  86. if (buildTargetGroup == BuildTargetGroup.Unknown && !describesFallbackSDK)
  87. {
  88. VRTK_Logger.Fatal(new ArgumentOutOfRangeException("buildTargetGroupName", buildTargetGroupName, string.Format("'{0}' isn't allowed.", buildTargetGroupName)));
  89. return;
  90. }
  91. #endif
  92. }
  93. /// <summary>
  94. /// Creates a new attribute by copying from another attribute on a given type.
  95. /// </summary>
  96. /// <param name="typeToCopyExistingDescriptionFrom">The type to copy the existing SDK_DescriptionAttribute from. `null` is not allowed.</param>
  97. /// <param name="index">The index of the description to copy from the the existing SDK_DescriptionAttribute.</param>
  98. public SDK_DescriptionAttribute(Type typeToCopyExistingDescriptionFrom, int index = 0)
  99. {
  100. if (typeToCopyExistingDescriptionFrom == null)
  101. {
  102. VRTK_Logger.Fatal(new ArgumentNullException("typeToCopyExistingDescriptionFrom"));
  103. return;
  104. }
  105. Type descriptionType = typeof(SDK_DescriptionAttribute);
  106. SDK_DescriptionAttribute[] descriptions = GetDescriptions(typeToCopyExistingDescriptionFrom);
  107. if (descriptions.Length == 0)
  108. {
  109. VRTK_Logger.Fatal(new ArgumentOutOfRangeException("typeToCopyExistingDescriptionFrom", typeToCopyExistingDescriptionFrom, string.Format("'{0}' doesn't specify any SDK descriptions via '{1}' to copy.", typeToCopyExistingDescriptionFrom.Name, descriptionType.Name)));
  110. return;
  111. }
  112. if (descriptions.Length <= index)
  113. {
  114. VRTK_Logger.Fatal(new ArgumentOutOfRangeException("index", index, string.Format("'{0}' has no '{1}' at that index.", typeToCopyExistingDescriptionFrom.Name, descriptionType.Name)));
  115. return;
  116. }
  117. SDK_DescriptionAttribute description = descriptions[index];
  118. prettyName = description.prettyName;
  119. symbol = description.symbol;
  120. vrDeviceName = description.vrDeviceName;
  121. this.index = index;
  122. #if UNITY_EDITOR
  123. buildTargetGroup = description.buildTargetGroup;
  124. #endif
  125. }
  126. public static SDK_DescriptionAttribute[] GetDescriptions(Type type)
  127. {
  128. return VRTK_SharedMethods.GetTypeCustomAttributes(type, typeof(SDK_DescriptionAttribute), false)
  129. .Cast<SDK_DescriptionAttribute>()
  130. .OrderBy(attribute => attribute.index)
  131. .ToArray();
  132. }
  133. }
  134. }