Skip to content

Instantly share code, notes, and snippets.

@badscotsman
Created August 30, 2024 11:21
Show Gist options
  • Save badscotsman/903ad9b0a0003fb986b461bb65db1841 to your computer and use it in GitHub Desktop.
Save badscotsman/903ad9b0a0003fb986b461bb65db1841 to your computer and use it in GitHub Desktop.
A simple Scene selector Overlay
using UnityEngine;
namespace SceneSelector
{
[CreateAssetMenu(fileName = "SceneSelectorConfig", menuName = "Editor/Scene Selector Configuration", order = 1)]
public class SceneSelectorConfigSO : ScriptableObject
{
public string SceneFilter = "t:Scene";
public string[] SceneNames;
public string[] PreferredScenePaths;
}
}
using System.IO;
using UnityEditor;
using UnityEditor.Overlays;
using UnityEditor.SceneManagement;
using UnityEditor.Toolbars;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace SceneSelector
{
[Overlay(typeof(SceneView), "Scene Selector")]
[Icon(ICON_PATH)]
public class SceneSelectorOverlay : ToolbarOverlay
{
public static SceneSelectorConfigSO Config;
// The path to the configuration asset must be updated per project - it must exist.
public const string CONFIG_PATH = "Assets/Editor/SceneSelectorOverlay/Settings/SceneSelectorConfig.asset";
// The path to the icon for the overlay must be updated per project - it must exist.
public const string ICON_PATH = "Assets/Editor/SceneSelectorOverlay/SceneSelectorIcon.png";
private SceneSelectorOverlay() : base(SceneDropdownToggle.ID)
{
Config = AssetDatabase.LoadAssetAtPath<SceneSelectorConfigSO>(CONFIG_PATH);
if (Config == null)
{
Debug.LogWarning("Scene Selector Overlay configuration is not set up!");
}
}
[EditorToolbarElement(ID, typeof(SceneView))]
private class SceneDropdownToggle : EditorToolbarDropdownToggle, IAccessContainerWindow
{
public const string ID = "SceneSelectorOverlay/SceneDropdownToggle";
public EditorWindow containerWindow { get; set; }
private SceneDropdownToggle()
{
text = "Scenes";
tooltip = "Select a Scene to Load";
icon = AssetDatabase.LoadAssetAtPath<Texture2D>(ICON_PATH);
dropdownClicked += ShowSceneMenu;
}
private void ShowSceneMenu()
{
var menu = new GenericMenu();
var currentScene = SceneManager.GetActiveScene();
if (Config != null && Config.SceneNames.Length > 0)
{
foreach (var sceneName in Config.SceneNames)
{
if (Config.PreferredScenePaths != null && Config.PreferredScenePaths.Length > 0)
{
PopulateMenuWithScenePaths(menu, sceneName, currentScene);
}
else
{
PopulateMenuWithSceneName(menu, sceneName, currentScene);
}
}
}
else if (Config != null)
{
PopulateMenuWithFilter(menu, Config.SceneFilter, currentScene);
}
menu.ShowAsContext();
}
private void PopulateMenuWithFilter(GenericMenu menu, string filter, Scene currentScene)
{
string[] sceneGuids = AssetDatabase.FindAssets(filter);
foreach (var guid in sceneGuids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var name = Path.GetFileNameWithoutExtension(path);
menu.AddItem(
new GUIContent(name),
string.Compare(currentScene.name, name) == 0,
() => OpenScene(currentScene, path));
}
}
private void PopulateMenuWithScenePaths(GenericMenu menu, string sceneName, Scene currentScene)
{
foreach (var possiblePath in Config.PreferredScenePaths)
{
string[] guids = AssetDatabase.FindAssets($"t:Scene {sceneName}", new[] { possiblePath });
AddItems(guids, sceneName, currentScene, menu);
}
}
private void PopulateMenuWithSceneName(GenericMenu menu, string sceneName, Scene currentScene)
{
string[] guids = AssetDatabase.FindAssets($"t:Scene {sceneName}");
AddItems(guids, sceneName, currentScene, menu);
}
private void AddItems(string[] guids, string sceneName, Scene currentScene, GenericMenu menu)
{
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
if (Path.GetFileNameWithoutExtension(path).Equals(sceneName, System.StringComparison.OrdinalIgnoreCase))
{
menu.AddItem(
new GUIContent(sceneName),
string.Compare(currentScene.name, sceneName, System.StringComparison.OrdinalIgnoreCase) == 0,
() => OpenScene(currentScene, path));
}
}
}
}
private static void OpenScene(Scene currentScene, string path)
{
if (!currentScene.isDirty)
{
EditorSceneManager.OpenScene(path);
return;
}
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
EditorSceneManager.OpenScene(path);
}
}
}
}
@badscotsman
Copy link
Author

badscotsman commented Aug 30, 2024

Icon image to use for 'SceneSelectorIcon.png' :)
SceneSelectorIcon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment