using System; using System.Collections.Generic; using System.IO; using JetBrains.Annotations; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; namespace Module.NavigationTool.Editor.Toolbar { [UsedImplicitly] internal sealed class ToolScenePicker : AbstractToolbarDrawer { public override bool Visible => ToolbarScenePickerSettings.IsSceneEnabled; public override bool Enabled => !EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode; public override EToolbarPlacement Placement => EToolbarPlacement.Right; public override int Priority => (int)EToolbarPriority.Medium; private static bool IS_DIRTY = true; private static int SELECTED_INDEX = -1; private static string[] OPTIONS = new string[0]; private static string[] PATHS = new string[0]; private static void Initialize() { if (!IS_DIRTY) return; var listNames = new List(); var listPaths = new List(); InitializeBuildSettingsScenes(listNames, listPaths); InitializeRemainingScenes(listNames, listPaths); OPTIONS = listNames.ToArray(); PATHS = listPaths.ToArray(); Scene activeScene = SceneManager.GetActiveScene(); SELECTED_INDEX = listPaths.IndexOf(activeScene.path); IS_DIRTY = false; } private static void InitializeBuildSettingsScenes(List listNames, List listPaths) { EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes; for (var i = 0; i < scenes.Length; i++) { if (string.IsNullOrEmpty(scenes[i].path)) continue; listNames.Add($"{Path.GetFileNameWithoutExtension(scenes[i].path)}"); listPaths.Add(scenes[i].path); } } private static void InitializeRemainingScenes(List listNames, List listPaths) { List sortByAssetLabels = ToolbarScenePickerSettings.SceneAssetLabels; var assetLabelToScenes = new SceneSortElement[sortByAssetLabels.Count + 1]; string[] guids = AssetDatabase.FindAssets("t:scene"); for (var i = 0; i < guids.Length; i++) { string path = AssetDatabase.GUIDToAssetPath(guids[i]); if (listPaths.Contains(path) || !path.StartsWith("Assets")) continue; var scene = AssetDatabase.LoadAssetAtPath(path); if (scene == null) continue; string sceneName = path.Substring(7, path.Length - 13) .Replace('/', '\\'); string[] assetLabels = AssetDatabase.GetLabels(scene); int index = -1; for (var j = 0; j < assetLabels.Length; j++) { index = sortByAssetLabels.IndexOf(assetLabels[j]); if (index != -1) break; } if (index == -1) index = sortByAssetLabels.Count; if (assetLabelToScenes[index] == null) assetLabelToScenes[index] = new SceneSortElement(); assetLabelToScenes[index].names.Add(sceneName); assetLabelToScenes[index].paths.Add(path); } for (var i = 0; i < assetLabelToScenes.Length; i++) { SceneSortElement e = assetLabelToScenes[i]; if (e == null) continue; listNames.Add(string.Empty); listPaths.Add(string.Empty); listNames.AddRange(e.names); listPaths.AddRange(e.paths); } } public override void Update() { Initialize(); } protected override void Draw(Rect rect) { Initialize(); int temp = EditorGUI.Popup(rect, SELECTED_INDEX, OPTIONS, styles.popup); if (temp <= -1 || temp == SELECTED_INDEX || OPTIONS.Length == 0) return; if (string.IsNullOrEmpty(PATHS[temp])) return; try { Scene scene = EditorSceneManager.OpenScene(PATHS[temp], OpenSceneMode.Single); if (scene.isLoaded) SELECTED_INDEX = temp; } catch (Exception e) { Debug.LogWarningFormat("Failed to load scene ({0}), due to exception: {1}", PATHS[temp], e.Message); } } public override float CalculateWidth() { return 100.0f; } public static void SetAsDirty() { IS_DIRTY = true; } private sealed class SceneSortElement { public readonly List names = new List(); public readonly List paths = new List(); } } }