/// <summary> /// Manages (i.e. adds and removes) the scripting define symbols of the <see cref="PlayerSettings"/> for the currently set SDK infos. This method is only available in the editor, so usage of the method needs to be surrounded by `#if UNITY_EDITOR` and `#endif` when used in a type that is also compiled for a standalone build. /// </summary> /// <param name="ignoreAutoManageScriptDefines">Whether to ignore <see cref="autoManageScriptDefines"/> while deciding to manage.</param> /// <param name="ignoreIsActiveAndEnabled">Whether to ignore <see cref="Behaviour.isActiveAndEnabled"/> while deciding to manage.</param> /// <returns>Whether the <see cref="PlayerSettings"/>' scripting define symbols were changed.</returns> public bool ManageScriptingDefineSymbols(bool ignoreAutoManageScriptDefines, bool ignoreIsActiveAndEnabled) { if (!((ignoreAutoManageScriptDefines || autoManageScriptDefines) && (ignoreIsActiveAndEnabled || isActiveAndEnabled))) { return(false); } //get valid BuildTargetGroups BuildTargetGroup[] targetGroups = Enum.GetValues(typeof(BuildTargetGroup)).Cast <BuildTargetGroup>().Where(group => { if (group == BuildTargetGroup.Unknown) { return(false); } string targetGroupName = Enum.GetName(typeof(BuildTargetGroup), group); FieldInfo targetGroupFieldInfo = typeof(BuildTargetGroup).GetField(targetGroupName, BindingFlags.Public | BindingFlags.Static); return(targetGroupFieldInfo != null && targetGroupFieldInfo.GetCustomAttributes(typeof(ObsoleteAttribute), false).Length == 0); }).ToArray(); var newSymbolsByTargetGroup = new Dictionary <BuildTargetGroup, HashSet <string> >(targetGroups.Length); //get current non-removable scripting define symbols foreach (BuildTargetGroup targetGroup in targetGroups) { IEnumerable <string> nonSDKSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup) .Split(';') .Where(symbol => !symbol.StartsWith(SDK_ScriptingDefineSymbolPredicateAttribute.RemovableSymbolPrefix, StringComparison.Ordinal)); newSymbolsByTargetGroup[targetGroup] = new HashSet <string>(nonSDKSymbols); } Func <VRTK_SDKInfo, string> symbolSelector = info => info.description.symbol; var sdkSymbols = new HashSet <string>( AvailableSystemSDKInfos.Select(symbolSelector) .Concat(AvailableBoundariesSDKInfos.Select(symbolSelector)) .Concat(AvailableHeadsetSDKInfos.Select(symbolSelector)) .Concat(AvailableControllerSDKInfos.Select(symbolSelector)) ); var activeSymbols = new HashSet <string>(activeScriptingDefineSymbolsWithoutSDKClasses.Select(attribute => attribute.symbol)); //get scripting define symbols and check whether the predicates allow us to add the symbols foreach (ScriptingDefineSymbolPredicateInfo predicateInfo in AvailableScriptingDefineSymbolPredicateInfos) { string symbol = predicateInfo.attribute.symbol; if (!sdkSymbols.Contains(symbol) && !activeSymbols.Contains(symbol)) { continue; } MethodInfo methodInfo = predicateInfo.methodInfo; if (!(bool)methodInfo.Invoke(null, null)) { continue; } //add symbols from all predicate attributes on the method since multiple ones are allowed var allAttributes = (SDK_ScriptingDefineSymbolPredicateAttribute[])methodInfo.GetCustomAttributes(typeof(SDK_ScriptingDefineSymbolPredicateAttribute), false); foreach (SDK_ScriptingDefineSymbolPredicateAttribute attribute in allAttributes) { BuildTargetGroup buildTargetGroup = attribute.buildTargetGroup; HashSet <string> newSymbols; if (!newSymbolsByTargetGroup.TryGetValue(buildTargetGroup, out newSymbols)) { newSymbols = new HashSet <string>(); newSymbolsByTargetGroup[buildTargetGroup] = newSymbols; } newSymbols.Add(attribute.symbol); } } var changedSymbols = false; //apply new set of scripting define symbols foreach (KeyValuePair <BuildTargetGroup, HashSet <string> > keyValuePair in newSymbolsByTargetGroup) { BuildTargetGroup targetGroup = keyValuePair.Key; string[] currentSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup) .Split(';') .Distinct() .OrderBy(symbol => symbol, StringComparer.Ordinal) .ToArray(); string[] newSymbols = keyValuePair.Value.OrderBy(symbol => symbol, StringComparer.Ordinal).ToArray(); if (currentSymbols.SequenceEqual(newSymbols)) { continue; } PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, string.Join(";", newSymbols)); string[] removedSymbols = currentSymbols.Except(newSymbols).ToArray(); if (removedSymbols.Length > 0) { Debug.Log("Scripting Define Symbols removed from [Project Settings->Player]: " + string.Join(", ", removedSymbols)); } string[] addedSymbols = newSymbols.Except(currentSymbols).ToArray(); if (addedSymbols.Length > 0) { Debug.Log("Scripting Define Symbols added To [Project Settings->Player]: " + string.Join(", ", addedSymbols)); } if (!changedSymbols) { changedSymbols = removedSymbols.Length > 0 || addedSymbols.Length > 0; } } return(changedSymbols); }
/// <summary> /// Handles SDK selection during startup. Must be called before setupping any SDK specific stuff. /// </summary> private void SetupSDK() { // Check if we even have to do any SDK selection bool needsSDKSetup = automaticSDKSelection || (actualBoundaries == null && actualHeadset == null && actualLeftController == null && actualRightController == null); if (!needsSDKSetup) { return; } string selectedSDK = "Fallback"; // Heuristic SDK detection if (automaticSDKSelection) { if (!VRDevice.isPresent) { selectedSDK = "Simulator"; } else { if (VRDevice.model.Contains("Oculus") || VRDevice.model.Contains("Rift")) { selectedSDK = "OculusVR"; } else { // Assume everyone else except Oculus uses SteamVR selectedSDK = "SteamVR"; } } // Check for command line SDKs. These override all the previous selections. var args = System.Environment.GetCommandLineArgs(); foreach (var arg in args) { if (arg.Equals("--vr-none")) { selectedSDK = "Fallback"; } if (arg.Equals("--vr-oculus")) { selectedSDK = "OculusVR"; } if (arg.Equals("--vr-steam")) { selectedSDK = "SteamVR"; } if (arg.Equals("--vr-simulator")) { selectedSDK = "Simulator"; } } Debug.Log("Selected VR SDK: " + selectedSDK); // Set correct individual SDKs systemSDKInfo = GetSDK(selectedSDK, AvailableSystemSDKInfos); boundariesSDKInfo = GetSDK(selectedSDK, AvailableBoundariesSDKInfos); headsetSDKInfo = GetSDK(selectedSDK, AvailableHeadsetSDKInfos); controllerSDKInfo = GetSDK(selectedSDK, AvailableControllerSDKInfos); // Load the SDK camera rig if one has been assigned int sdkIndex = AvailableSystemSDKInfos.IndexOf(GetSDK(selectedSDK)); var sdkPrefab = automaticSDKPrefabList[sdkIndex]; if (sdkPrefab != null) { var go = Instantiate(sdkPrefab) as GameObject; if (go != null) { // Remove (Clone) from the name of the instantiated game object, otherwise SDKs don't work properly // as they find the gameobjects by their name. go.name = go.name.Replace("(Clone)", ""); } } // Disable VR if we don't have a true VR SDK if (selectedSDK == "Fallback" || selectedSDK == "Simulator") { VRSettings.enabled = false; VRSettings.LoadDeviceByName("None"); } // Assign VRTK components to the newly instantiated rig var playareaTransform = GetBoundariesSDK().GetPlayArea(); actualBoundaries = (playareaTransform ? playareaTransform.gameObject : null); var headsetTransform = GetHeadsetSDK().GetHeadset(); actualHeadset = (headsetTransform ? headsetTransform.gameObject : null); var controllerLeft = GetControllerSDK().GetControllerLeftHand(true); actualLeftController = controllerLeft; var controllerRight = GetControllerSDK().GetControllerRightHand(true); actualRightController = controllerRight; var controllerAliasLeft = GetControllerSDK().GetControllerModel(SDK_BaseController.ControllerHand.Left); modelAliasLeftController = controllerAliasLeft; var controllerAliasRight = GetControllerSDK().GetControllerModel(SDK_BaseController.ControllerHand.Right); modelAliasRightController = controllerAliasRight; } }
/// <summary> /// Manages (i.e. adds and removes) the scripting define symbols of the PlayerSettings for the currently set SDK infos. /// This method is only available in the editor, so usage of the method needs to be surrounded by `#if UNITY_EDITOR` and `#endif` when used /// in a type that is also compiled for a standalone build. /// </summary> /// <param name="ignoreAutoManageScriptDefines">Whether to ignore `autoManageScriptDefines` while deciding to manage.</param> /// <param name="ignoreIsActiveAndEnabled">Whether to ignore `Behaviour.isActiveAndEnabled` while deciding to manage.</param> /// <returns>Whether the PlayerSettings' scripting define symbols were changed.</returns> public bool ManageScriptingDefineSymbols(bool ignoreAutoManageScriptDefines, bool ignoreIsActiveAndEnabled) { if (!((ignoreAutoManageScriptDefines || autoManageScriptDefines) && (ignoreIsActiveAndEnabled || isActiveAndEnabled))) { return(false); } //get valid BuildTargetGroups BuildTargetGroup[] targetGroups = VRTK_SharedMethods.GetValidBuildTargetGroups(); Dictionary <BuildTargetGroup, HashSet <string> > newSymbolsByTargetGroup = new Dictionary <BuildTargetGroup, HashSet <string> >(targetGroups.Length); //get current non-removable scripting define symbols foreach (BuildTargetGroup targetGroup in targetGroups) { IEnumerable <string> nonSDKSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup) .Split(';') .Where(symbol => !symbol.StartsWith(SDK_ScriptingDefineSymbolPredicateAttribute.RemovableSymbolPrefix, StringComparison.Ordinal)); newSymbolsByTargetGroup[targetGroup] = new HashSet <string>(nonSDKSymbols); } VRTK_SDKInfo[] availableSDKInfos = AvailableSystemSDKInfos .Concat(AvailableBoundariesSDKInfos) .Concat(AvailableHeadsetSDKInfos) .Concat(AvailableControllerSDKInfos) .ToArray(); HashSet <SDK_DescriptionAttribute> descriptions = new HashSet <SDK_DescriptionAttribute>( availableSDKInfos.Select(info => info.description) .Where(description => !description.describesFallbackSDK) ); HashSet <string> activeSymbols = new HashSet <string>(activeScriptingDefineSymbolsWithoutSDKClasses.Select(attribute => attribute.symbol)); //get scripting define symbols and check whether the predicates allow us to add the symbols foreach (ScriptingDefineSymbolPredicateInfo predicateInfo in AvailableScriptingDefineSymbolPredicateInfos) { SDK_ScriptingDefineSymbolPredicateAttribute predicateAttribute = predicateInfo.attribute; string symbol = predicateAttribute.symbol; if (!activeSymbols.Contains(symbol) && !descriptions.Any(description => description.symbol == symbol && description.buildTargetGroup == predicateAttribute.buildTargetGroup)) { continue; } MethodInfo methodInfo = predicateInfo.methodInfo; if (!(bool)methodInfo.Invoke(null, null)) { continue; } //add symbols from all predicate attributes on the method since multiple ones are allowed SDK_ScriptingDefineSymbolPredicateAttribute[] allAttributes = (SDK_ScriptingDefineSymbolPredicateAttribute[])methodInfo.GetCustomAttributes(typeof(SDK_ScriptingDefineSymbolPredicateAttribute), false); foreach (SDK_ScriptingDefineSymbolPredicateAttribute attribute in allAttributes) { BuildTargetGroup buildTargetGroup = attribute.buildTargetGroup; HashSet <string> newSymbols; if (!newSymbolsByTargetGroup.TryGetValue(buildTargetGroup, out newSymbols)) { newSymbols = new HashSet <string>(); newSymbolsByTargetGroup[buildTargetGroup] = newSymbols; } newSymbols.Add(attribute.symbol); } } bool changedSymbols = false; //apply new set of scripting define symbols foreach (KeyValuePair <BuildTargetGroup, HashSet <string> > keyValuePair in newSymbolsByTargetGroup) { BuildTargetGroup targetGroup = keyValuePair.Key; string[] currentSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup) .Split(';') .Distinct() .OrderBy(symbol => symbol, StringComparer.Ordinal) .ToArray(); string[] newSymbols = keyValuePair.Value.OrderBy(symbol => symbol, StringComparer.Ordinal).ToArray(); if (currentSymbols.SequenceEqual(newSymbols)) { continue; } PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, string.Join(";", newSymbols)); string[] removedSymbols = currentSymbols.Except(newSymbols).ToArray(); if (removedSymbols.Length > 0) { VRTK_Logger.Info(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.SCRIPTING_DEFINE_SYMBOLS_REMOVED, targetGroup, string.Join(", ", removedSymbols))); } string[] addedSymbols = newSymbols.Except(currentSymbols).ToArray(); if (addedSymbols.Length > 0) { VRTK_Logger.Info(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.SCRIPTING_DEFINE_SYMBOLS_ADDED, targetGroup, string.Join(", ", addedSymbols))); } if (!changedSymbols) { changedSymbols = removedSymbols.Length > 0 || addedSymbols.Length > 0; } } return(changedSymbols); }