// SDK Description|SDK_Base|002 namespace VRTK { #if UNITY_EDITOR using UnityEditor; #endif using System; using System.Linq; /// /// Describes a class that represents an SDK. Only allowed on classes that inherit from SDK_Base. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public sealed class SDK_DescriptionAttribute : Attribute { /// /// The pretty name of the SDK. Uniquely identifies the SDK. /// public readonly string prettyName; /// /// 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. /// public readonly string symbol; /// /// The name of the VR Device to load. /// public readonly string vrDeviceName; /// /// The index of this attribute, in case there are multiple on the same target. /// public readonly int index; #if UNITY_EDITOR /// /// The build target group this SDK is for. /// public BuildTargetGroup buildTargetGroup; #endif /// /// Whether this description describes a fallback SDK. /// public bool describesFallbackSDK { get { return prettyName == "Fallback"; } } /// /// Creates a new attribute. /// /// The pretty name of the SDK. Uniquely identifies the SDK. `null` and `string.Empty` aren't allowed. /// 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. /// The name of the VR Device to load. Set to `null` or `string.Empty` if no VR Device is needed. /// The name of a constant of `BuildTargetGroup`. `BuildTargetGroup.Unknown`, `null` and `string.Empty` are not allowed. /// The index of this attribute, in case there are multiple on the same target. public SDK_DescriptionAttribute(string prettyName, string symbol, string vrDeviceName, string buildTargetGroupName, int index = 0) { if (prettyName == null) { VRTK_Logger.Fatal(new ArgumentNullException("prettyName")); return; } if (prettyName == string.Empty) { VRTK_Logger.Fatal(new ArgumentOutOfRangeException("prettyName", prettyName, "An empty string isn't allowed.")); return; } this.prettyName = prettyName; this.symbol = symbol; this.vrDeviceName = string.IsNullOrEmpty(vrDeviceName) ? "None" : vrDeviceName; this.index = index; if (string.IsNullOrEmpty(buildTargetGroupName)) { buildTargetGroupName = "Unknown"; } #if UNITY_EDITOR Type buildTargetGroupType = typeof(BuildTargetGroup); try { buildTargetGroup = (BuildTargetGroup)Enum.Parse(buildTargetGroupType, buildTargetGroupName); } catch (Exception exception) { VRTK_Logger.Fatal(new ArgumentOutOfRangeException(string.Format("'{0}' isn't a valid constant name of '{1}'.", buildTargetGroupName, buildTargetGroupType.Name), exception)); return; } if (buildTargetGroup == BuildTargetGroup.Unknown && !describesFallbackSDK) { VRTK_Logger.Fatal(new ArgumentOutOfRangeException("buildTargetGroupName", buildTargetGroupName, string.Format("'{0}' isn't allowed.", buildTargetGroupName))); return; } #endif } /// /// Creates a new attribute by copying from another attribute on a given type. /// /// The type to copy the existing SDK_DescriptionAttribute from. `null` is not allowed. /// The index of the description to copy from the the existing SDK_DescriptionAttribute. public SDK_DescriptionAttribute(Type typeToCopyExistingDescriptionFrom, int index = 0) { if (typeToCopyExistingDescriptionFrom == null) { VRTK_Logger.Fatal(new ArgumentNullException("typeToCopyExistingDescriptionFrom")); return; } Type descriptionType = typeof(SDK_DescriptionAttribute); SDK_DescriptionAttribute[] descriptions = GetDescriptions(typeToCopyExistingDescriptionFrom); if (descriptions.Length == 0) { VRTK_Logger.Fatal(new ArgumentOutOfRangeException("typeToCopyExistingDescriptionFrom", typeToCopyExistingDescriptionFrom, string.Format("'{0}' doesn't specify any SDK descriptions via '{1}' to copy.", typeToCopyExistingDescriptionFrom.Name, descriptionType.Name))); return; } if (descriptions.Length <= index) { VRTK_Logger.Fatal(new ArgumentOutOfRangeException("index", index, string.Format("'{0}' has no '{1}' at that index.", typeToCopyExistingDescriptionFrom.Name, descriptionType.Name))); return; } SDK_DescriptionAttribute description = descriptions[index]; prettyName = description.prettyName; symbol = description.symbol; vrDeviceName = description.vrDeviceName; this.index = index; #if UNITY_EDITOR buildTargetGroup = description.buildTargetGroup; #endif } public static SDK_DescriptionAttribute[] GetDescriptions(Type type) { return VRTK_SharedMethods.GetTypeCustomAttributes(type, typeof(SDK_DescriptionAttribute), false) .Cast() .OrderBy(attribute => attribute.index) .ToArray(); } } }