269 lines
8.5 KiB
C#
269 lines
8.5 KiB
C#
#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($"<color=green>Scene '{Path.GetFileNameWithoutExtension(currentScenePath)}' enabled in Build Settings.</color>");
|
|
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($"<color=green>Scene '{Path.GetFileNameWithoutExtension(currentScenePath)}' added to Build Settings.</color>");
|
|
|
|
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 |