using System; using System.Linq; using System.Collections; using System.Collections.Generic; using System.Reflection; using UnityEditor; using UnityEngine; using UnityEngine.Networking; using Label = HIKKY.VketCloudSDK.UI.EditorWindow.GUIHelper.Label; using Unity.Plastic.Newtonsoft.Json; using System.Threading.Tasks; using static HIKKY.VketCloudSDK.AddOn.ExternalPackageImporter; using System.IO; using UnityEditor.PackageManager; using static HIKKY.VketCloudSDK.AddOn.LanguageSetting; using Unity.Plastic.Newtonsoft.Json.Linq; using UnityEditor.Rendering; using static UnityEngine.GraphicsBuffer; using UnityEngine.Rendering; using System.Text.RegularExpressions; namespace HIKKY.VketCloudSDK.AddOn { public class InstallWizardWindow : EditorWindow { private const int TOTAL_PAGES = 5; private static int _currentPage; private Texture2D _initialTopImage; private Texture2D _logoImage; private Texture2D _logoLightImage; private float _buttonWidth = 80; private string _nextString = string.Empty; private LanguageSetting.Language _currentLanguage; private string[] _languageOptions = { "English", "日本語" }; private int _selectedLanguageIndex = 0; private static LocalizationManager _localizationManager; private string _stableVersion = ""; private string _latestVersion = ""; private List _archivedVersions = new List { }; private string _selectedVersion = ""; private string _latestETSVersion = ""; private static string npmjsURL = "https://registry.npmjs.org/com.hikky.vketcloudsdk"; private static string npmjsETSURL = "https://registry.npmjs.org/com.hikky.editortutorialsystem"; private static UnityWebRequest www; private static string json; private static string jsonETS; private float _progress = 0f; private float _progressSpeed = 0.05f; private bool _progressForward = true; // Frames private Texture2D[] frames; private Texture2D[] frames_Light; private int currentFrame = 0; private float frameRate = 10.0f; // Adjust the frame rate as needed private float lastFrameTime; private string framesDarkPath = ""; private string framesLightPath = ""; private static readonly string manualURL = "https://vrhikky.github.io/VketCloudSDK_Documents/"; private static readonly string discordURL = "https://discord.gg/VrsA26bDyP"; private Texture2D _versionImage; GUIStyle buttonStyle = null; private Vector2 _scrollPosition; [MenuItem("VketCloudSDK_Wizard/ SDK Installation Wizard", true)] public static bool ValidateShowStartup() { return !CheckForPackage("com.hikky.vketcloudsdk"); } [MenuItem("VketCloudSDK_Wizard/ SDK Installation Wizard")] public static void ShowStartup() { ShowInstallWizardWindow(); } [InitializeOnLoadMethod] public static void Initialize() { StartBackgroundTask(StartRequest(npmjsURL, () => { var temp = www.downloadHandler.text; if (temp != null) { json = temp; } })); StartBackgroundTask(StartRequest(npmjsETSURL, () => { var temp = www.downloadHandler.text; if (temp != null) { jsonETS = temp; } })); if (!CheckForPackage("com.hikky.vketcloudsdk")) { EditorApplication.update += ShowStartupWindowOnStart; } } private static void ShowStartupWindowOnStart() { ShowInstallWizardWindow(); EditorApplication.update -= ShowStartupWindowOnStart; } private static bool ContainsSpaceOrDoubleByteCharacter(string input) { // Check if the input contains space or double-byte characters return Regex.IsMatch(input, @"[\s\u00A1-\uFFFF]"); } public static void ShowInstallWizardWindow() { string projectPath = Application.dataPath; if (ContainsSpaceOrDoubleByteCharacter(projectPath)) { EditorUtility.DisplayDialog( "Warning/警告", "The installation of VketCloudSDK has been interrupted due to an invalid UnityProject file path." + "\n" + "If the UnityProject file path contains spaces, Japanese characters, or any other multi-byte characters, the authentication for VketCloudSDK might fail." + "\n" + "\n" + "Please ensure that the UnityProject file path consists of only single-byte alphanumeric characters without any spaces." + "\n" + "\n" + "UnityProjectのファイルパスが不正のためVketCloudSDKのインストールを中断しました。" + "\n" + "UnityProjectのファイルパスにスペース、もしくは日本語や全角文字などの2バイト文字が含まれていると、VketCloudSDKの認証に失敗する場合があります。" +"\n" + "\n" + "スペースが含まれない半角英数字のみで、UnityProjectのファイルパスを構成するようにして下さい。", "OK" ); return; } InstallWizardWindow window = (InstallWizardWindow)GetWindow(typeof(InstallWizardWindow), true, "VketCloudSDK Install Wizard"); window.minSize = new Vector2(650, 360); window.maxSize = new Vector2(650, 360); if (CheckForPackage("com.hikky.vketcloudsdk")) { _currentPage = 5; } window.titleContent = new GUIContent($"{GetLocalizedString("InstallationWizardWindow_Title")} ({_currentPage + 1}/{TOTAL_PAGES})"); if (HasOpenInstances()) return; window.Show(); } public static bool CheckForPackage(string packageName) { string path = Path.Combine(Application.dataPath, "..", "Packages", "manifest.json"); if (File.Exists(path)) { string jsonText = File.ReadAllText(path); try { JObject json = JObject.Parse(jsonText); JToken dependencies = json["dependencies"]; return dependencies[packageName] != null; } catch (JsonException e) { UnityEngine.Debug.LogError("Failed to parse manifest.json: " + e.Message); } } else { UnityEngine.Debug.LogError("manifest.json not found."); } return false; } public async void OnEnable() { if (CheckForPackage("com.hikky.vketcloudsdk")) { _currentPage = 5; UpdateWindowTitle(); } _initialTopImage = AssetDatabase.LoadAssetAtPath(PathManager.GetWizardTopImageEn); _logoImage = AssetDatabase.LoadAssetAtPath(PathManager.GetWizardLogoImage); _logoLightImage = AssetDatabase.LoadAssetAtPath(PathManager.GetWizardLogoLightImage); _versionImage = AssetDatabase.LoadAssetAtPath(PathManager.GetWizardVersionImage); _currentLanguage = LanguageSetting.GetLanguage(); _selectedLanguageIndex = (int)_currentLanguage; _localizationManager = AssetDatabase.LoadAssetAtPath(PathManager.GetLocalizationManagerSetting); if (_localizationManager != null) { _localizationManager.LoadLanguage(_currentLanguage); } _progress = 0f; if (_currentLanguage == Language.Japanese) { _initialTopImage = AssetDatabase.LoadAssetAtPath(PathManager.GetWizardTopImageJa); } UpdateWindowTitle(); // 自動でVersionリストに追加する。 try { json = await FetchVersions(); } catch (Exception e) { UnityEngine.Debug.LogError(e.Message); } StartBackgroundTask(StartRequest(npmjsURL, () => { var temp = www.downloadHandler.text; if (temp != null) { json = temp; } })); ParseJsonData(json); try { jsonETS = await FetchETSVersions(); } catch (Exception e) { UnityEngine.Debug.LogError(e.Message); } StartBackgroundTask(StartRequest(npmjsETSURL, () => { var temp = www.downloadHandler.text; if (temp != null) { jsonETS = temp; } })); ParseETSJsonData(jsonETS); if (buttonStyle == null) { buttonStyle = new GUIStyle(); buttonStyle.alignment = TextAnchor.MiddleCenter; buttonStyle.margin = buttonStyle.margin; buttonStyle.margin.right = 0; } framesDarkPath = PathManager.GetLoadingDarkImageFolder; LoadDarkFrames(); framesLightPath = PathManager.GetLoadingLightImageFolder; LoadLightFrames(); EditorApplication.update += UpdateAnimation; } private void OnDisable() { EditorApplication.update -= UpdateAnimation; } private void UpdateAnimation() { // Use EditorApplication.timeSinceStartup to get the current time double timeSinceStartup = EditorApplication.timeSinceStartup; if (timeSinceStartup - lastFrameTime >= 1.0f / frameRate) { currentFrame = (currentFrame + 1) % frames.Length; // Loop back to the first frame after the last lastFrameTime = (float)timeSinceStartup; // Request the window to repaint itself Repaint(); } } private async Task FetchVersions() { using (UnityWebRequest www = UnityWebRequest.Get(npmjsURL)) { var operation = www.SendWebRequest(); while (!operation.isDone) { await Task.Delay(100); // Delay for a short period before checking if the request is done } return www.downloadHandler.text; } } private async Task FetchETSVersions() { using (UnityWebRequest www = UnityWebRequest.Get(npmjsETSURL)) { var operation = www.SendWebRequest(); while (!operation.isDone) { await Task.Delay(100); // Delay for a short period before checking if the request is done } return www.downloadHandler.text; } } private void UpdateWindowTitle() { string title = $"{GetLocalizedString("InstallationWizardWindow_Title")} ({_currentPage + 1}/{TOTAL_PAGES})"; titleContent = new GUIContent(title); } private void LoadDarkFrames() { var guids = AssetDatabase.FindAssets("t:Texture2D", new[] { framesDarkPath }); frames = new Texture2D[guids.Length]; for (int i = 0; i < guids.Length; i++) { string path = AssetDatabase.GUIDToAssetPath(guids[i]); frames[i] = AssetDatabase.LoadAssetAtPath(path); } } private void LoadLightFrames() { var guids = AssetDatabase.FindAssets("t:Texture2D", new[] { framesLightPath }); frames_Light = new Texture2D[guids.Length]; for (int i = 0; i < guids.Length; i++) { string path = AssetDatabase.GUIDToAssetPath(guids[i]); frames_Light[i] = AssetDatabase.LoadAssetAtPath(path); } } private void OnGUI() { switch (_currentPage) { case 0: DrawTopImage(); break; case 1: DrawLanguageSelectionPage(); break; case 2: DrawRecommendationSettingPage(); break; case 3: DrawVersionSelectionPage(); break; case 4: DrawProgressBarPage(); break; case 5: DrawCompletionPage(); break; default: GUILayout.Label($"Page {_currentPage}"); GUILayout.FlexibleSpace(); break; } using (new EditorGUILayout.HorizontalScope(GUILayout.Height(30), GUILayout.ExpandWidth(true))) { DrawBottomBarLogo(); GUILayout.FlexibleSpace(); DrawBottomBarPageButton(); } } private void DrawCompletionPage() { GUILayout.Space(25); using (new EditorGUILayout.HorizontalScope()) { GUILayout.Space(25); using (new EditorGUILayout.VerticalScope()) { Label.Title(GetLocalizedString("DownloadCompletion_Title")); Label.Header1(GetLocalizedString("DownloadCompletion_Text1")); Label.WrappedText(GetLocalizedString("DownloadCompletion_Text2")); Label.WrappedText(GetLocalizedString("DownloadCompletion_Text3")); DrawVersionTopImage(); DrawLearningResourcesButtons(); } GUILayout.Space(25); } GUILayout.FlexibleSpace(); } private void DrawVersionTopImage() { using (new EditorGUILayout.HorizontalScope()) { GUILayout.FlexibleSpace(); EditorGUILayout.LabelField(new GUIContent(_versionImage), GUILayout.Height(180), GUILayout.Width(500)); GUILayout.FlexibleSpace(); } } public void DrawLearningResourcesButtons() { using (new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button(new GUIContent(GetLocalizedString("VersionSelectionPage_Manual")))) { // バージョン、言語とマッチしたドキュメントを返す場合 var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssembly(System.Reflection.Assembly.Load("HIKKY.VketCloudSDK")); var currentVersion = GetSubstringUntilFirstPeriod(packageInfo.version); if (_currentLanguage == Language.English) { Application.OpenURL(manualURL + currentVersion + "/"); } else if (_currentLanguage == Language.Japanese) { Application.OpenURL(manualURL + currentVersion + "/" + "ja"); } } if (GUILayout.Button(new GUIContent(GetLocalizedString("VersionSelectionPage_Discord")))) { Application.OpenURL(discordURL); } } } private static string GetSubstringUntilFirstPeriod(string input) { int indexOfFirstPeriod = input.IndexOf('.'); if (indexOfFirstPeriod >= 0) { int indexOfSecondPeriod = input.IndexOf('.', indexOfFirstPeriod + 1); if (indexOfSecondPeriod >= 0) { return input.Substring(0, indexOfSecondPeriod); } else { return input; } } else { return input; } } private void DrawTopImage() { using (new EditorGUILayout.HorizontalScope(GUIStyle.none, GUILayout.Width(position.width), GUILayout.ExpandHeight(true))) { GUILayout.FlexibleSpace(); EditorGUILayout.LabelField(new GUIContent(_initialTopImage), GUILayout.Width(position.width), GUILayout.ExpandHeight(true)); GUILayout.FlexibleSpace(); } } private void DrawBottomBarLogo() { using (new EditorGUILayout.VerticalScope(GUILayout.Height(30), GUILayout.Width(81), GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false))) { GUILayout.FlexibleSpace(); using (new EditorGUILayout.HorizontalScope(GUILayout.Height(18), GUILayout.Width(81), GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false))) { if (EditorGUIUtility.isProSkin) { EditorGUILayout.LabelField(new GUIContent(_logoImage), GUILayout.Height(18), GUILayout.Width(81)); } else { EditorGUILayout.LabelField(new GUIContent(_logoLightImage), GUILayout.Height(18), GUILayout.Width(81)); } GUILayout.Label("©HIKKY All rights reserved."); } GUILayout.FlexibleSpace(); } } private void DrawBottomBarPageButton() { using (new EditorGUILayout.VerticalScope(GUILayout.Height(30), GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false))) { GUILayout.FlexibleSpace(); using (new EditorGUILayout.HorizontalScope(GUILayout.Height(25), GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(false))) { if (_currentPage != 4) // Check if it's not the fifth page { if (_currentPage > 0) { if (_currentPage != 5) { // Back button GUI.enabled = _currentPage > 0; if (GUILayout.Button(GetLocalizedString("Page_Back"), GUILayout.Width(_buttonWidth), GUILayout.Height(25))) { _currentPage--; UpdateWindowTitle(); } } } // Next button GUI.enabled = _currentPage < TOTAL_PAGES + 1; if (_currentPage == 0) { _nextString = "Next/次へ"; } else if (_currentPage == 3) { _nextString = GetLocalizedString("VersionManager_Install"); } else if (_currentPage == 5) { _nextString = GetLocalizedString("VersionSelectionPage_Completion"); } else { _nextString = GetLocalizedString("Page_Next"); } if (GUILayout.Button(_nextString, GUILayout.Width(_buttonWidth), GUILayout.Height(25))) { if (_currentPage == 2 && !AreRecommendedSettingsCorrect()) { EditorUtility.DisplayDialog(GetLocalizedString("RecommendationWarning_Title"), GetLocalizedString("RecommendationWarning_Text"), "OK"); } else if (_currentPage == 2 && AreRecommendedSettingsCorrect()) { _currentPage++; UpdateWindowTitle(); } else if (_currentPage == 5) { this.Close(); } else { _currentPage++; UpdateWindowTitle(); } } GUI.enabled = true; } } GUILayout.FlexibleSpace(); } } private bool AreRecommendedSettingsCorrect() { var apiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup); var lightmapEncoding = GetLightmapEncoding(BuildTargetGroup.Standalone); var colorSpace = PlayerSettings.colorSpace; bool isApiCorrect = false; if (Application.unityVersion.Contains("2019")) { isApiCorrect = apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6; } else { isApiCorrect = true; } bool isLightmapCorrect = lightmapEncoding == "Normal"; bool isColorSpaceCorrect = colorSpace == ColorSpace.Linear; var tier1Settings = EditorGraphicsSettings.GetTierSettings(BuildTargetGroup.Standalone, (GraphicsTier)GraphicsTier.Tier1).standardShaderQuality; var tier2Settings = EditorGraphicsSettings.GetTierSettings(BuildTargetGroup.Standalone, (GraphicsTier)GraphicsTier.Tier2).standardShaderQuality; var tier3Settings = EditorGraphicsSettings.GetTierSettings(BuildTargetGroup.Standalone, (GraphicsTier)GraphicsTier.Tier3).standardShaderQuality; bool isTier1Correct = tier1Settings == ShaderQuality.Medium; bool isTier2Correct = tier2Settings == ShaderQuality.Medium; bool isTier3Correct = tier3Settings == ShaderQuality.Medium; return isApiCorrect && isLightmapCorrect && isColorSpaceCorrect && isTier1Correct && isTier2Correct && isTier3Correct; } private void DrawLanguageSelectionPage() { GUILayout.Space(25); using (new EditorGUILayout.HorizontalScope()) { GUILayout.Space(25); using (new EditorGUILayout.VerticalScope()) { Label.Title(GetLocalizedString("LanguageSelectionPage_Title")); int newSelectedLanguageIndex = EditorGUILayout.Popup("Language/言語", _selectedLanguageIndex, _languageOptions, GUILayout.Width(250)); if (newSelectedLanguageIndex != _selectedLanguageIndex) { _selectedLanguageIndex = newSelectedLanguageIndex; LanguageSetting.SetLanguage((LanguageSetting.Language)_selectedLanguageIndex); _currentLanguage = LanguageSetting.GetLanguage(); _localizationManager.LoadLanguage(_currentLanguage); UpdateWindowTitle(); if (_currentLanguage == Language.Japanese) { _initialTopImage = AssetDatabase.LoadAssetAtPath(PathManager.GetWizardTopImageJa); } } } GUILayout.Space(25); } GUILayout.FlexibleSpace(); } private void DrawRecommendationSettingPage() { GUILayout.Space(25); using (new EditorGUILayout.HorizontalScope()) { GUILayout.Space(25); using (new EditorGUILayout.VerticalScope()) { Label.Title(GetLocalizedString("RecommendationSettingsPage_Title")); GUILayout.Label(GetLocalizedString("RecommendationSettingWindow_Title")); // Hyperlink style GUIStyle hyperlinkStyle = new GUIStyle(GUI.skin.label); if(EditorGUIUtility.isProSkin) { hyperlinkStyle.normal.textColor = Color.cyan; hyperlinkStyle.hover.textColor = Color.cyan; } else { hyperlinkStyle.normal.textColor = Color.blue; hyperlinkStyle.hover.textColor = Color.blue; } hyperlinkStyle.alignment = TextAnchor.MiddleCenter; var rect = EditorGUILayout.GetControlRect(GUILayout.Width(50)); if (EditorGUI.DropdownButton(rect, new GUIContent("※ " + GetLocalizedString("Help_Text")), FocusType.Passive, hyperlinkStyle)) { if (_currentLanguage == LanguageSetting.Language.Japanese) { Application.OpenURL("https://vrhikky.github.io/VketCloudSDK_Documents/latest/ja/AboutVketCloudSDK/OperatingEnvironment.html"); } else { Application.OpenURL("https://vrhikky.github.io/VketCloudSDK_Documents/latest/en/AboutVketCloudSDK/OperatingEnvironment.html"); } } GUILayout.Space(10); GUILayout.Label("1. " + GetLocalizedString("RecommendationStep1_Text")); GUILayout.Label("2. " + GetLocalizedString("RecommendationStep2_Text")); GUILayout.Space(10); var tier1Settings = EditorGraphicsSettings.GetTierSettings(BuildTargetGroup.Standalone, (GraphicsTier)GraphicsTier.Tier1).standardShaderQuality; var tier2Settings = EditorGraphicsSettings.GetTierSettings(BuildTargetGroup.Standalone, (GraphicsTier)GraphicsTier.Tier2).standardShaderQuality; var tier3Settings = EditorGraphicsSettings.GetTierSettings(BuildTargetGroup.Standalone, (GraphicsTier)GraphicsTier.Tier3).standardShaderQuality; bool isTier1Correct = tier1Settings == ShaderQuality.Medium; bool isTier2Correct = tier2Settings == ShaderQuality.Medium; bool isTier3Correct = tier3Settings == ShaderQuality.Medium; // Get the current settings from the Player Settings and Quality Settings var colorSpace = PlayerSettings.colorSpace; var lightmapEncoding = GetLightmapEncoding(BuildTargetGroup.Standalone); var apiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup); // Check for Graphics Setting string tierSettingCheck = (isTier1Correct && isTier2Correct && isTier3Correct) ? "✔️ " : " "; Label.Bold(tierSettingCheck + "Graphics: " + GetLocalizedString("GraphicsTier_Title")); EditorGUI.indentLevel++; EditorGUILayout.LabelField(GetLocalizedString("GraphicsTier_Text")); EditorGUI.indentLevel--; // Check for Color Space string colorSpaceCheck = (colorSpace == ColorSpace.Linear) ? "✔️ " : " "; Label.Bold(colorSpaceCheck + "Player: " + GetLocalizedString("ColorSpace_Title")); EditorGUI.indentLevel++; EditorGUILayout.LabelField(GetLocalizedString("ColorSpace_Text")); EditorGUI.indentLevel--; // Check for Lightmap Encoding string lightmapCheck = (lightmapEncoding == "Normal") ? "✔️ " : " "; Label.Bold(lightmapCheck + "Player: " + GetLocalizedString("LightmapEncoding_Title")); EditorGUI.indentLevel++; EditorGUILayout.LabelField(GetLocalizedString("LightmapEncoding_Text")); EditorGUI.indentLevel--; // Check for API Compatibility Level if (Application.unityVersion.Contains("2019")) { string apiCheck = (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) ? "✔️ " : " "; Label.Bold(apiCheck + "Player: " + GetLocalizedString("APICompatibilityLevel_Title")); EditorGUI.indentLevel++; EditorGUILayout.LabelField(GetLocalizedString("APICompatibilityLevel_Text")); EditorGUI.indentLevel--; } } GUILayout.Space(25); } GUILayout.FlexibleSpace(); } private void DrawVersionSelectionPage() { GUILayout.Space(25); using (new EditorGUILayout.HorizontalScope()) { GUILayout.Space(25); // Left Box - Stable Version using (new EditorGUILayout.VerticalScope()) { Label.Title(GetLocalizedString("VersionSelectionPage_Title")); using (new EditorGUILayout.HorizontalScope()) { using (new EditorGUILayout.VerticalScope(GUILayout.Width(285), GUILayout.Height(260))) { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox, GUILayout.Width(285), GUILayout.Height(117f))) { Label.Header1(GetLocalizedString("StableVersion")); Label.TextArea(GetLocalizedString("StableSupport")); Label.TextArea(GetLocalizedString("StableUser")); GUILayout.FlexibleSpace(); bool stableToggle = EditorGUILayout.ToggleLeft(_stableVersion, _selectedVersion == _stableVersion); if (stableToggle && _selectedVersion != _stableVersion) { _selectedVersion = _stableVersion; } GUILayout.FlexibleSpace(); } GUILayout.FlexibleSpace(); using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox, GUILayout.Width(285), GUILayout.Height(117f))) { Label.Header1(GetLocalizedString("LatetstVersion")); Label.TextArea(GetLocalizedString("LatetstTextOne")); Label.TextArea(GetLocalizedString("LatetstTextTwo")); GUILayout.FlexibleSpace(); bool stableToggle = EditorGUILayout.ToggleLeft(_latestVersion, _selectedVersion == _latestVersion); if (stableToggle && _selectedVersion != _latestVersion) { _selectedVersion = _latestVersion; } GUILayout.FlexibleSpace(); } } GUILayout.FlexibleSpace(); // Right Box - Version Archive using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox, GUILayout.Width(285), GUILayout.Height(260))) { Label.Header1(GetLocalizedString("VersionArchive")); Label.TextArea(GetLocalizedString("VersionArchiveTextOne")); Label.TextArea(GetLocalizedString("VersionArchiveTextTwo")); GUILayout.FlexibleSpace(); _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, GUILayout.Height(150)); foreach (var version in _archivedVersions) { bool versionToggle = EditorGUILayout.ToggleLeft(version, _selectedVersion == version); if (versionToggle && _selectedVersion != version) { _selectedVersion = version; } } EditorGUILayout.EndScrollView(); } } } GUILayout.Space(25); } GUILayout.FlexibleSpace(); } private void AddPackages() { var res = Client.Add("com.unity.editorcoroutines"); while (!res.IsCompleted) { } AddScopedRegistry(new ScopedRegistry { name = "VketCloudSDK", url = "https://registry.npmjs.org", scopes = new string[] { "com.hikky.vketcloudsdk" } }, "com.hikky.vketcloudsdk", _selectedVersion); // Deeplink AddScopedRegistry(new ScopedRegistry { name = "Deeplink", url = "https://package.openupm.com", scopes = new string[] { "com.needle.deeplink" } }, "com.needle.deeplink", "1.2.1"); AddSymbol("DEEPLINK"); string etsVersion = string.IsNullOrEmpty(_latestETSVersion) ? "1.0.1" : _latestETSVersion; // EditorTutorialSystem AddScopedRegistry(new ScopedRegistry { name = "EditorTutorialSystem", url = "https://registry.npmjs.org", scopes = new string[] { "com.hikky.editortutorialsystem" } }, "com.hikky.editortutorialsystem", etsVersion); AddSymbol("EDITORTUTORIALSYSTEM"); } public static void AddSymbol(string name) { BuildTargetGroup targetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; string settingSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup); if (Array.Find(settingSymbols.Split(';'), n => n == name) != null) return; settingSymbols += $";{name}"; PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, settingSymbols); } private void DrawProgressBarPage() { // Update progress if (_progressForward) { _progress += _progressSpeed; if (_progress >= 1f) { _progress = 1f; _progressForward = false; } } else { _progress -= _progressSpeed; if (_progress <= 0f) { _progress = 0f; _progressForward = true; } } GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if(frames != null && frames.Length > 0) { if(EditorGUIUtility.isProSkin) { GUILayout.Label(frames[currentFrame], GUILayout.Width(200), GUILayout.Height(200)); } else { GUILayout.Label(frames_Light[currentFrame], GUILayout.Width(200), GUILayout.Height(200)); } } if (Time.realtimeSinceStartup - lastFrameTime >= 1.0f / frameRate) { currentFrame = (currentFrame + 1) % frames.Length; // Loop back to the first frame after the last lastFrameTime = Time.realtimeSinceStartup; Repaint(); } GUILayout.FlexibleSpace(); // Ends centering horizontally GUILayout.EndHorizontal(); // End horizontal groupin GUILayout.FlexibleSpace(); AddPackages(); } private static string GetLocalizedString(string key) { if (_localizationManager != null) { return _localizationManager.GetString(key); } return key; } public static string GetLightmapEncoding(BuildTargetGroup platformGroup) { var getLightmapEncodingMethod = typeof(PlayerSettings).GetMethod("GetLightmapEncodingQualityForPlatformGroup", BindingFlags.Static | BindingFlags.NonPublic); if (getLightmapEncodingMethod != null) { var result = getLightmapEncodingMethod.Invoke(null, new object[] { platformGroup }); if (result != null) { return result.ToString(); } } return string.Empty; } public static IEnumerator StartRequest(string url, Action success = null) { using (www = UnityWebRequest.Get(url)) { #if UNITY_2017_2_OR_NEWER yield return www.SendWebRequest(); #else yield return www.Send(); #endif while (!www.isDone) yield return null; if (www.isNetworkError || www.isHttpError) { UnityEngine.Debug.LogError($"Request error: {www.error}"); } else { if (success != null) success(); } } } public static void StartBackgroundTask(IEnumerator update, Action end = null) { EditorApplication.CallbackFunction closureCallback = null; closureCallback = () => { try { if (update.MoveNext() == false) { if (end != null) end(); EditorApplication.update -= closureCallback; } } catch (Exception ex) { if (end != null) end(); UnityEngine.Debug.LogException(ex); EditorApplication.update -= closureCallback; } }; EditorApplication.update += closureCallback; } private void ParseJsonData(string json) { var settings = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore }; if (json != null) { var jsonData = JsonConvert.DeserializeObject(json, settings); _stableVersion = jsonData.distTags.stable; _latestVersion = jsonData.distTags.latest; _archivedVersions = jsonData.versions .Where(v => string.IsNullOrEmpty(v.Value.deprecated)) .Select(v => v.Key) .ToList(); FilterMaxPatchVersions(); _archivedVersions.Remove(_stableVersion); _archivedVersions.Remove(_latestVersion); SortVersionsDescending(); _selectedVersion = _stableVersion; } } private void ParseETSJsonData(string json) { var settings = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore }; if (json != null) { var jsonData = JsonConvert.DeserializeObject(json, settings); _latestETSVersion = jsonData.distTags.latest; } } private void SortVersionsDescending() { _archivedVersions = _archivedVersions.OrderByDescending(v => { var versionParts = v.Split('.'); int major = int.Parse(versionParts[0]); int minor = int.Parse(versionParts[1]); int patch = versionParts.Length > 2 ? int.Parse(versionParts[2]) : 0; return (major, minor, patch); }).ToList(); } private void FilterMaxPatchVersions() { var maxPatchVersions = new Dictionary<(int Major, int Minor), int>(); foreach (var version in _archivedVersions) { var versionParts = version.Split('.'); int major = int.Parse(versionParts[0]); int minor = int.Parse(versionParts[1]); int patch = versionParts.Length > 2 ? int.Parse(versionParts[2]) : 0; var key = (Major: major, Minor: minor); if (maxPatchVersions.TryGetValue(key, out var existingMaxPatch) && patch > existingMaxPatch) { maxPatchVersions[key] = patch; } else { maxPatchVersions[key] = patch; } } _archivedVersions = maxPatchVersions.Select(kvp => $"{kvp.Key.Major}.{kvp.Key.Minor}.{kvp.Value}").ToList(); } } }