// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; using UnityEditor; namespace UltimateXR.Editor.Sdks { /// /// Static class that will store all SDK locators through auto-registration. Each /// implementation will register itself through this class. /// public static partial class UxrSdkManager { #region Public Types & Data /// /// Gets the global list of registered SDK locators. SDK locators will auto-register every time Unity is installed or /// the project is updated. /// public static IReadOnlyList SDKLocators => s_locators; #endregion #region Public Methods /// /// Registers a new SDK locator if it is not already registered. /// The locator then is used to update the project symbols adding the necessary symbols if the SDK was found or /// removing them if it wasn't. /// /// SDK locator interface public static void RegisterLocator(UxrSdkLocator locator) { if (s_locators == null) { s_locators = new List(); } // Check if it was already registered bool locatorAlreadyRegistered = false; foreach (UxrSdkLocator registeredLocator in s_locators) { if (string.Equals(registeredLocator.Name, locator.Name, StringComparison.Ordinal)) { locatorAlreadyRegistered = true; break; } } // Register if not found if (locatorAlreadyRegistered == false) { s_locators.Add(locator); } // Try to locate SDK and set up symbols locator.TryLocate(); if (!locator.IsPackage) { SetupSymbols(locator); } } /// /// Checks if a given SDK is present and available. /// /// Type of the SDK locator /// True if installed and available, false if not public static bool IsAvailable() where T : UxrSdkLocator { if (s_locators != null) { foreach (UxrSdkLocator locator in s_locators) { if (locator.GetType() == typeof(T)) { return locator.CurrentState == UxrSdkLocator.State.Available; } } } return false; } /// /// Checks if a given SDK is present and available. /// /// The SDK name (looks to match any UxrSdkLocator.Name) /// True if installed and available, false if not public static bool IsAvailable(string name) { if (s_locators != null) { foreach (UxrSdkLocator locator in s_locators) { if (locator.Name == name) { return locator.CurrentState == UxrSdkLocator.State.Available; } } } return false; } /// /// Updates the project symbols removing the symbols of the SDK locator given as argument. /// /// The SDK locator to remove the symbols from public static void RemoveSymbols(UxrSdkLocator locator) { if (!locator.IsPackage) { SetupSymbols(locator, SetupSymbolsMode.ForceRemove); } } /// /// Checks if currently the project has any symbols defined for the given SDK locator. /// /// The SDK locator to check the symbols for public static bool HasAnySymbols(UxrSdkLocator locator) { string[] targetGroupNames = Enum.GetNames(typeof(BuildTargetGroup)); int targetGroupIndex = 0; foreach (BuildTargetGroup targetGroup in Enum.GetValues(typeof(BuildTargetGroup))) { // Get the BuildTargetGroup name through targetGroupNames. targetGroup.ToString() does not work because there are // enum entries with the same numerical value string targetGroupName = targetGroupNames[targetGroupIndex]; targetGroupIndex++; // Ignore target groups to avoid scripting errors (thank you Ludiq!) if (targetGroup == BuildTargetGroup.Unknown) { continue; } if (typeof(BuildTargetGroup).GetField(targetGroupName).IsDefined(typeof(ObsoleteAttribute), true)) { continue; } // Get trimmed target symbol list List currentSymbols = new List(PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup).Split(';')); for (int currentSymbolIndex = 0; currentSymbolIndex < currentSymbols.Count; ++currentSymbolIndex) { currentSymbols[currentSymbolIndex] = currentSymbols[currentSymbolIndex].Trim(); } // Look for symbols foreach (string sdkSymbolString in locator.AllSymbols) { if (currentSymbols.IndexOf(sdkSymbolString) != -1) { return true; } } } return false; } #endregion #region Private Methods /// /// Updates the project symbols adding the necessary symbols if the SDK is present or removing them if it is not. Also /// allows to remove the symbols if necessary. /// /// The SDK locator /// /// If is specified then it will update the symbols depending on the SDK /// presence (add if SDK is present, remove if it is not present). /// In mode it will remove all symbols linked to the SDK locator. /// private static void SetupSymbols(UxrSdkLocator locator, SetupSymbolsMode setupSymbolsMode = SetupSymbolsMode.AddOrRemove) { string[] targetGroupNames = Enum.GetNames(typeof(BuildTargetGroup)); int targetGroupIndex = 0; foreach (BuildTargetGroup targetGroup in Enum.GetValues(typeof(BuildTargetGroup))) { // Get the BuildTargetGroup name through targetGroupNames. targetGroup.ToString() does not work because there are // enum entries with the same numerical value string targetGroupName = targetGroupNames[targetGroupIndex]; targetGroupIndex++; // Ignore target groups to avoid scripting errors (thank you Ludiq!) if (targetGroup == BuildTargetGroup.Unknown) { continue; } if (typeof(BuildTargetGroup).GetField(targetGroupName).IsDefined(typeof(ObsoleteAttribute), true)) { continue; } // Get trimmed target symbol list List currentSymbols = new List(PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup).Split(';')); for (int currentSymbolIndex = 0; currentSymbolIndex < currentSymbols.Count; ++currentSymbolIndex) { currentSymbols[currentSymbolIndex].Trim(); } // Look for symbols, adding or removing if necessary bool updated = false; List availableSymbols = new List(locator.AvailableSymbols); foreach (string sdkSymbolString in locator.AllSymbols) { if (setupSymbolsMode == SetupSymbolsMode.AddOrRemove) { // Add if (availableSymbols.Contains(sdkSymbolString) && currentSymbols.IndexOf(sdkSymbolString) == -1) { currentSymbols.Add(sdkSymbolString); updated = true; } else { while (currentSymbols.IndexOf(sdkSymbolString) != currentSymbols.LastIndexOf(sdkSymbolString)) { // Remove duplicates currentSymbols.Remove(sdkSymbolString); updated = true; } } } else { // Remove while (currentSymbols.IndexOf(sdkSymbolString) != -1) { currentSymbols.Remove(sdkSymbolString); updated = true; } } } // Update target symbol list if (updated) { PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, string.Join(";", currentSymbols.ToArray())); } } } #endregion #region Private Types & Data private static List s_locators; #endregion } }