using System; using System.Collections.Generic; using System.Linq; using Unity.Services.Mediation.Adapters.Editor; using Unity.Services.Mediation.Dashboard.Editor; using UnityEditor; using UnityEditor.Advertisements; using UnityEngine; using UnityEngine.UIElements; namespace Unity.Services.Mediation.Settings.Editor { class MediationAdapterSettings : EditorWindow { const string k_DashboardUrl = @"https://dashboard.unity3d.com/monetization"; const string k_DocumentationUrl = @"https://docs.unity3d.com/2020.2/Documentation/Manual/"; const string k_Install = "Install"; const string k_Uninstall = "Uninstall"; const string k_ApiRangeTooltip = "This adapter supports API versions: \n" + "Android: {0} to {1} \n" + "iOS: {2} to {3}"; const string k_SourceConfigUrl = @"https://dashboard.unity3d.com/organizations/{0}/monetization/mediation/ad-sources"; const string k_DisableDexingArtifactTransformKey = "DisableDexingArtifactTransform"; const string k_ForceDynamicLinkingKey = "ForceDynamicLinking"; const string k_DeterministicBuildsKey = "DeterministicBuilds"; const string k_ForceDependencyUpdate = "ForceDependencyUpdate"; const string k_SettingsStyle = @"Packages/com.unity.services.mediation/Editor/Settings/Layout/SettingsStyle.uss"; const string k_SettingsTemplate = @"Packages/com.unity.services.mediation/Editor/Settings/Layout/SettingsTemplate.uxml"; const string k_AdapterTemplate = @"Packages/com.unity.services.mediation/Editor/Settings/Layout/AdapterTemplate.uxml"; #if UNITY_2020_1_OR_NEWER const string k_ServiceBaseStyle = @"StyleSheets/ServicesWindow/ServicesProjectSettingsCommon.uss"; static readonly string k_SkinStyle = $@"StyleSheets/ServicesWindow/ServicesProjectSettings{(EditorGUIUtility.isProSkin ? "Dark" : "Light")}.uss"; #else const string k_ServiceBaseStyle = @"Packages/com.unity.services.mediation/Editor/Settings/Layout/2019/BaseStyle.uss"; static readonly string k_SkinStyle = $@"Packages/com.unity.services.mediation/Editor/Settings/Layout/2019/SkinStyle{(EditorGUIUtility.isProSkin ? "Dark" : "Light")}.uss"; #endif static Dictionary s_AdapterInfos; static Dictionary s_AdapterSelectToggle; static Dictionary s_AdapterInstalledInfo; static Dictionary s_AdapterUninstalledInfo; static Dictionary s_AdapterInstalledIcon; static Dictionary s_AdapterUnavailableConfigInfo; static Dictionary s_AdapterConfiguredInfo; static Dictionary s_AdapterUnconfiguredInfo; static Dictionary s_AdapterConfiguredIcon; static Dictionary s_AdapterInstallButton; static List s_AdapterSettings; static List s_configuredAdNetworks; static bool s_Initialized; static bool s_SettingsChanged; static ReloadableUserSetting s_ForceDynamicLinkingSetting = new ReloadableUserSetting(MediationSettingsProvider.instance, MediationUserSettingsKeys.forceDynamicLinkingKey, true); static ReloadableUserSetting s_DisableDexingArtifactTransform = new ReloadableUserSetting(MediationSettingsProvider.instance, MediationUserSettingsKeys.disableDexingArtifactTransform, true); static ReloadableUserSetting s_DeterministicBuildsSetting = new ReloadableUserSetting(MediationSettingsProvider.instance, MediationUserSettingsKeys.deterministicBuildsKey, true); static ReloadableUserSetting s_ForceDependencyUpdateSetting = new ReloadableUserSetting(MediationSettingsProvider.instance, MediationUserSettingsKeys.forceDependencyUpdateKey, false); [InitializeOnLoadMethod] static void Initialize() { if (s_Initialized) return; s_Initialized = true; var adapters = MediationSdkInfo.GetAllAdapters(); s_AdapterInfos = adapters.ToDictionary(info => info.Identifier); s_AdapterSettings = ConfigureAdapterSettings(adapters); s_AdapterSelectToggle = new Dictionary(); s_AdapterInstalledInfo = new Dictionary(); s_AdapterUninstalledInfo = new Dictionary(); s_AdapterInstalledIcon = new Dictionary(); s_AdapterUnavailableConfigInfo = new Dictionary(); s_AdapterConfiguredInfo = new Dictionary(); s_AdapterUnconfiguredInfo = new Dictionary(); s_AdapterConfiguredIcon = new Dictionary(); s_AdapterInstallButton = new Dictionary(); MediationSdkInfo.AdaptersChanged += Refresh; DashboardClient.GetConfiguredAdNetworksAsync(RefreshConfiguredAdNetworks); } /// /// Refreshes the list of available adapters, installed adapters and installed versions /// Called on MediationSDKInfo.AdaptersChanged /// static void Refresh() { var installedAdapters = MediationSdkInfo.GetInstalledAdapters(); var changed = false; foreach (var adapterSetting in s_AdapterSettings) { var adapterInfo = installedAdapters .FirstOrDefault(info => info.Identifier == adapterSetting.AdapterId); var isInstalled = adapterInfo != null; if (isInstalled) { if (adapterInfo.InstalledVersion.Identifier != adapterSetting.InstalledVersion.value) { adapterSetting.InstalledVersion.value = adapterInfo.InstalledVersion.Identifier; changed = true; } } else { if (adapterSetting.InstalledVersion.value != "") { changed = true; adapterSetting.InstalledVersion.value = ""; } } } if (changed) { MediationSettingsProvider.instance.Save(); } RefreshAdaptersData(); RefreshAllInstallButton(); } [MenuItem("Services/" + MediationServiceIdentifier.k_PackageDisplayName + "/Configure", priority = 100)] public static void ShowWindow() { EditorGameServiceAnalyticsSender.SendTopMenuConfigureEvent(); SettingsService.OpenProjectSettings($"Project/Services/{MediationServiceIdentifier.k_PackageDisplayName}"); } public static List ConfigureAdapterSettings(IEnumerable adapters) { var adaptersIds = adapters.Select(info => info.Identifier).ToList(); var adapterSettings = CreateAdapterSettings(FindAdaptersWithDefinedSettingsClass()); ConfigureAdapterSettingsWithGenericSettings(adapterSettings, adaptersIds); SortAdaptersByOriginalOrder(adapterSettings, adaptersIds); return adapterSettings; } static IEnumerable FindAdaptersWithDefinedSettingsClass() { return typeof(MediationAdapterSettings).Assembly.GetTypes() .Where(type => typeof(IAdapterSettings).IsAssignableFrom(type) && !type.IsAbstract && !typeof(GenericAdapterSettings).IsAssignableFrom(type)) .ToList(); } static List CreateAdapterSettings(IEnumerable definedTypes) { return definedTypes .Select(type => (IAdapterSettings)Activator.CreateInstance(type)) .ToList(); } static void ConfigureAdapterSettingsWithGenericSettings(List adaptersSettings, IEnumerable adaptersIds) { var adapterIdsWithGenericSettings = adaptersIds .Where(id => adaptersSettings.All(settings => settings.AdapterId != id)).ToList(); adaptersSettings.AddRange(adapterIdsWithGenericSettings.Select(id => new GenericAdapterSettings(id))); } static void SortAdaptersByOriginalOrder(List adapters, IList adaptersIds) { adapters.Sort((settings1, settings2) => { var i1 = adaptersIds.IndexOf(settings1.AdapterId); var i2 = adaptersIds.IndexOf(settings2.AdapterId); return i1 - i2; }); } public static VisualElement GenerateUIElementUI() { var rootElement = new VisualElement(); LoadExternalAssets(rootElement); CreateButton(rootElement, "GoToAdUnits", MediationAdUnitsWindow.ShowWindow); CreateButton(rootElement, "GoToCodeGenerator", MediationCodeGeneratorWindow.ShowWindow); CreateToggle(rootElement, k_ForceDynamicLinkingKey, ForceDynamicLinkingToggleValueChanged, s_ForceDynamicLinkingSetting.value); CreateToggle(rootElement, k_DisableDexingArtifactTransformKey, DisableDexingArtifactTransformToggleValueChanged, s_DisableDexingArtifactTransform.value); CreateToggle(rootElement, k_DeterministicBuildsKey, DeterministicBuildsToggleValueChanged, s_DeterministicBuildsSetting.value); CreateToggle(rootElement, k_ForceDependencyUpdate, ForceDependencyUpdateToggleValueChanged, s_ForceDependencyUpdateSetting.value); //Clear references to graphic elements as they will be generated here. ClearGraphicElementsReferences(); FillAdaptersList(rootElement); RefreshAdaptersData(); RefreshAllInstallButton(); #if !ENABLE_EDITOR_GAME_SERVICES MediationEditorService.RefreshGameId(); #endif CreateTextElement(rootElement, "android-game-id", AdvertisementSettings.GetGameId(RuntimePlatform.Android)); CreateTextElement(rootElement, "ios-game-id", AdvertisementSettings.GetGameId(RuntimePlatform.IPhonePlayer)); return rootElement; } static void LoadExternalAssets(VisualElement rootElement) { var settingsTemplate = AssetDatabase.LoadAssetAtPath(k_SettingsTemplate); var stylesheet = AssetDatabase.LoadAssetAtPath(k_SettingsStyle); rootElement.styleSheets.Add(stylesheet); stylesheet = EditorGUIUtility.Load(k_ServiceBaseStyle) as StyleSheet; rootElement.styleSheets.Add(stylesheet); stylesheet = EditorGUIUtility.Load(k_SkinStyle) as StyleSheet; rootElement.styleSheets.Add(stylesheet); settingsTemplate.CloneTree(rootElement); } static void ClearGraphicElementsReferences() { s_AdapterSelectToggle.Clear(); s_AdapterInstalledInfo.Clear(); s_AdapterUninstalledInfo.Clear(); s_AdapterInstalledIcon.Clear(); s_AdapterUnavailableConfigInfo.Clear(); s_AdapterConfiguredInfo.Clear(); s_AdapterUnconfiguredInfo.Clear(); s_AdapterConfiguredIcon.Clear(); s_AdapterInstallButton.Clear(); } static void FillAdaptersList(VisualElement rootElement) { var adapterListRoot = rootElement.Q("AdapterList"); var isEven = true; foreach (var adapterSetting in s_AdapterSettings) { adapterListRoot.Add(FillSingleAdapter(adapterSetting, isEven)); isEven = !isEven; } } static VisualElement FillSingleAdapter(IAdapterSettings adapterSetting, bool isEven) { var adapterTemplate = AssetDatabase.LoadAssetAtPath(k_AdapterTemplate); var adapterInfo = s_AdapterInfos[adapterSetting.AdapterId]; var adapter = new VisualElement(); adapterTemplate.CloneTree(adapter); var adapterContainer = adapter.Q("Adapter"); var backgroundUssPrefix = EditorGUIUtility.isProSkin ? "dark" : "light"; var rowUssPrefix = isEven ? "even" : "odd"; adapterContainer.AddToClassList($"{backgroundUssPrefix}-{rowUssPrefix}-background"); adapter.Q("AdapterName").text = adapterInfo.DisplayName; adapter.Q