#if UNITY_EDITOR using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.UIElements; using System.Reflection; using System.Linq; using System.IO; using UnityEngine.SceneManagement; [InitializeOnLoad] public static class SceneSwitcherToolbar { private static string[] sceneNames = new string[0]; private static int selectedIndex = 0; private static string lastActiveScene = ""; private static VisualElement toolbarUI; private static float positionOffset = 180f; private static float dropdownBoxHeight = 20f; private static bool fetchAllScenes { get => EditorPrefs.GetBool("SceneSwitcher_FetchAllScenes", false); set => EditorPrefs.SetBool("SceneSwitcher_FetchAllScenes", value); } static SceneSwitcherToolbar() { RefreshSceneList(); SelectCurrentScene(); EditorSceneManager.activeSceneChangedInEditMode += (prev, current) => UpdateSceneSelection(); EditorApplication.playModeStateChanged += OnPlayModeChanged; EditorApplication.delayCall += AddToolbarUI; } static void AddToolbarUI() { var toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar"); if (toolbarType == null) return; var toolbars = Resources.FindObjectsOfTypeAll(toolbarType); if (toolbars.Length == 0) return; var toolbar = toolbars[0]; var rootField = toolbarType.GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance); if (rootField == null) return; var root = rootField.GetValue(toolbar) as VisualElement; if (root == null) return; var leftContainer = root.Q("ToolbarZoneLeftAlign"); if (leftContainer == null) return; if (toolbarUI != null) { leftContainer.Remove(toolbarUI); } toolbarUI = new IMGUIContainer(OnGUI); toolbarUI.style.marginLeft = positionOffset; leftContainer.Add(toolbarUI); } static void OnGUI() { CheckAndRefreshScenes(); if (selectedIndex >= sceneNames.Length) selectedIndex = 0; bool isPlaying = EditorApplication.isPlaying; GUILayout.BeginHorizontal(); // Fetch all scenes toggle button EditorGUI.BeginDisabledGroup(isPlaying); bool newFetchAllScenes = GUILayout.Toggle(fetchAllScenes, "All Scenes", "Button", GUILayout.Height(dropdownBoxHeight)); if (newFetchAllScenes != fetchAllScenes) { fetchAllScenes = newFetchAllScenes; RefreshSceneList(); SelectCurrentScene(); } EditorGUI.EndDisabledGroup(); // Add Scene button EditorGUI.BeginDisabledGroup(isPlaying || fetchAllScenes); if (GUILayout.Button("Add Scene", GUILayout.Height(dropdownBoxHeight))) { AddCurrentSceneToBuildSettings(); } EditorGUI.EndDisabledGroup(); // Scene dropdown EditorGUI.BeginDisabledGroup(isPlaying); GUIStyle popupStyle = new GUIStyle(EditorStyles.popup) { fixedHeight = dropdownBoxHeight }; int newIndex = EditorGUILayout.Popup(selectedIndex, sceneNames, popupStyle, GUILayout.Width(150), GUILayout.Height(dropdownBoxHeight)); if (newIndex != selectedIndex) { selectedIndex = newIndex; LoadScene(sceneNames[selectedIndex]); } EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); } static void AddCurrentSceneToBuildSettings() { string currentScenePath = EditorSceneManager.GetActiveScene().path; if (string.IsNullOrEmpty(currentScenePath)) { EditorUtility.DisplayDialog("Scene Not Saved", "Please save the scene before adding it to Build Settings.", "OK"); return; } // Check if scene is already in build settings var buildScenes = EditorBuildSettings.scenes.ToList(); bool sceneExists = buildScenes.Any(s => s.path == currentScenePath); if (sceneExists) { // Enable the scene if it was disabled var existingScene = buildScenes.Find(s => s.path == currentScenePath); if (!existingScene.enabled) { existingScene.enabled = true; EditorBuildSettings.scenes = buildScenes.ToArray(); Debug.Log($"Scene '{Path.GetFileNameWithoutExtension(currentScenePath)}' enabled in Build Settings."); RefreshSceneList(); SelectCurrentScene(); } else { Debug.Log($"Scene '{Path.GetFileNameWithoutExtension(currentScenePath)}' is already in Build Settings."); } } else { // Add new scene to build settings buildScenes.Add(new EditorBuildSettingsScene(currentScenePath, true)); EditorBuildSettings.scenes = buildScenes.ToArray(); Debug.Log($"Scene '{Path.GetFileNameWithoutExtension(currentScenePath)}' added to Build Settings."); RefreshSceneList(); SelectCurrentScene(); } } static void RefreshSceneList() { if (fetchAllScenes) { sceneNames = Directory.GetFiles("Assets", "*.unity", SearchOption.AllDirectories) .Select(path => Path.GetFileNameWithoutExtension(path)) .ToArray(); } else { sceneNames = EditorBuildSettings.scenes .Where(scene => scene.enabled) .Select(scene => Path.GetFileNameWithoutExtension(scene.path)) .ToArray(); } } static void CheckAndRefreshScenes() { string[] currentScenes; if (fetchAllScenes) { currentScenes = Directory.GetFiles("Assets", "*.unity", SearchOption.AllDirectories) .Select(path => Path.GetFileNameWithoutExtension(path)) .ToArray(); } else { currentScenes = EditorBuildSettings.scenes .Where(scene => scene.enabled) .Select(scene => Path.GetFileNameWithoutExtension(scene.path)) .ToArray(); } if (!currentScenes.SequenceEqual(sceneNames)) { sceneNames = currentScenes; SelectCurrentScene(); } } static void SelectCurrentScene() { string currentScene = Path.GetFileNameWithoutExtension(EditorSceneManager.GetActiveScene().path); int index = System.Array.IndexOf(sceneNames, currentScene); if (index != -1) { selectedIndex = index; lastActiveScene = currentScene; } else { string notInBuildName = currentScene + " (not in build index)"; sceneNames = new[] { notInBuildName }.Concat(sceneNames).ToArray(); selectedIndex = 0; lastActiveScene = currentScene; } } static void UpdateSceneSelection() { string currentScene = Path.GetFileNameWithoutExtension(EditorSceneManager.GetActiveScene().path); if (currentScene != lastActiveScene) { lastActiveScene = currentScene; sceneNames = sceneNames.Where(name => !name.EndsWith(" (not in build index)")).ToArray(); SelectCurrentScene(); } } static void LoadScene(string sceneName) { string scenePath; if (fetchAllScenes) { scenePath = Directory.GetFiles("Assets", "*.unity", SearchOption.AllDirectories) .FirstOrDefault(path => Path.GetFileNameWithoutExtension(path) == sceneName); } else { scenePath = EditorBuildSettings.scenes .FirstOrDefault(scene => scene.enabled && scene.path.Contains(sceneName))?.path; } if (!string.IsNullOrEmpty(scenePath)) { if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { EditorSceneManager.OpenScene(scenePath); } } else { Debug.LogError("Scene not found: " + sceneName); } } static void OnPlayModeChanged(PlayModeStateChange state) { if (state == PlayModeStateChange.EnteredPlayMode || state == PlayModeStateChange.ExitingPlayMode) { EditorApplication.delayCall += () => AddToolbarUI(); } } } #endif