318 lines
11 KiB
C#
318 lines
11 KiB
C#
#if UNITY_EDITOR
|
|
using NotInvited.QuickSceneWindow.Utils;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEngine;
|
|
|
|
namespace NotInvited.QuickSceneWindow
|
|
{
|
|
public class QuickSceneEditorWindow : EditorWindow
|
|
{
|
|
private string searchName = "";
|
|
private int searchSelected = -1;
|
|
|
|
private int lastCursorIndex = 0;
|
|
private int currentSceneIndex;
|
|
|
|
private int newSceneIndexAsked;
|
|
|
|
private static bool showOnlyOnBuild = false;
|
|
|
|
private List<string> sceneNames = new List<string>();
|
|
private List<string> scenePaths = new List<string>();
|
|
|
|
private bool sceneFetch = false;
|
|
|
|
private List<string> allScenePaths = new List<string>();
|
|
private List<string> onlyBuildScenePaths = new List<string>();
|
|
|
|
private Vector2 scrollViewPosition = Vector2.zero;
|
|
|
|
[MenuItem("Window/📋 Quick Scenes Loader", false, 1000)]
|
|
[MenuItem("Tools/Quick Scene Window/📋 Open", priority = 300)]
|
|
public static void ShowWindow()
|
|
{
|
|
showOnlyOnBuild = EditorPrefs.GetBool("QuickSceneWindow_showOnlyOnBuild");
|
|
GetWindow(typeof(QuickSceneEditorWindow), false, "Quick Scene");
|
|
}
|
|
|
|
void OnGUI()
|
|
{
|
|
if (sceneFetch == false)
|
|
{
|
|
FetchScenes();
|
|
}
|
|
|
|
scenePaths = showOnlyOnBuild ? onlyBuildScenePaths : allScenePaths;
|
|
sceneNames = scenePaths.Select(x => Path.GetFileNameWithoutExtension(x)).ToList();
|
|
|
|
var actualScenePath = EditorSceneManager.GetActiveScene().path.Replace("/", "\\"); ;
|
|
|
|
currentSceneIndex = newSceneIndexAsked = scenePaths.FindIndex(x => x == actualScenePath);
|
|
|
|
DrawOpenSceneBar();
|
|
|
|
scrollViewPosition = GUILayout.BeginScrollView(scrollViewPosition);
|
|
DrawAllSceneButtons();
|
|
GUILayout.EndScrollView();
|
|
|
|
Rect allwindow = new Rect(Vector2.zero, position.size);
|
|
if (GUI.Button(allwindow, "", GUIStyle.none))
|
|
{
|
|
GUI.FocusControl(null);
|
|
}
|
|
}
|
|
|
|
private void FetchScenes()
|
|
{
|
|
EditorUtility.DisplayProgressBar("Searching", $"Searching all scenes on the project", 0f);
|
|
|
|
onlyBuildScenePaths = EditorBuildSettings.scenes.OrderBy(x => Path.GetFileNameWithoutExtension(x.path)).Select(x => x.path.Replace("/", "\\")).ToList();
|
|
allScenePaths = GetAllScenePath().OrderBy(x => Path.GetFileNameWithoutExtension(x)).ToList();
|
|
sceneFetch = true;
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
}
|
|
|
|
private void DrawDropDown()
|
|
{
|
|
newSceneIndexAsked = EditorGUILayout.Popup(currentSceneIndex, sceneNames.ToArray(), GUI.skin.FindStyle("toolbarDropDown"));
|
|
if (currentSceneIndex != newSceneIndexAsked)
|
|
{
|
|
currentSceneIndex = newSceneIndexAsked;
|
|
OpenScene(newSceneIndexAsked);
|
|
}
|
|
}
|
|
|
|
private void DrawAllSceneButtons()
|
|
{
|
|
int visibleIndex = 0;
|
|
for (int i = 0; i < sceneNames.Count; i++)
|
|
{
|
|
if (IsSceneButtonShow(sceneNames[i]))
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
|
|
GUIContent name = IsSceneInBuild(i) ? new GUIContent(sceneNames[i], EditorGUIUtility.FindTexture("BuildSettings.Standalone.Small")) : new GUIContent($" {sceneNames[i]}");
|
|
|
|
var style = new GUIStyle(EditorStyles.toolbarButton);
|
|
style.alignment = TextAnchor.MiddleLeft;
|
|
bool selected = this.currentSceneIndex == i;
|
|
var standardColor = GUI.backgroundColor;
|
|
bool selectStyle = false;
|
|
if (selected)
|
|
{
|
|
GUI.backgroundColor = CustomGUIUtils.BlueColor;
|
|
}
|
|
if (visibleIndex == searchSelected)
|
|
{
|
|
selectStyle = true;
|
|
}
|
|
if (GUILayout.Toggle(selectStyle, name, style) && selected == false && selectStyle == false)
|
|
{
|
|
this.currentSceneIndex = newSceneIndexAsked = i;
|
|
OpenScene(i);
|
|
}
|
|
if (visibleIndex == searchSelected && selected == false)
|
|
{
|
|
GUILayout.Button("Enter to load", EditorStyles.toolbarButton, GUILayout.MaxWidth(80f));
|
|
}
|
|
GUI.backgroundColor = standardColor;
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
visibleIndex++;
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool IsSceneInBuild(int i)
|
|
{
|
|
var path = scenePaths[i];
|
|
if (onlyBuildScenePaths.Contains(path))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
private bool IsSceneButtonShow(string sceneName)
|
|
{
|
|
if (string.IsNullOrEmpty(searchName))
|
|
return true;
|
|
else
|
|
{
|
|
if (sceneName.ToLower().Contains(searchName.ToLower()))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
private int SceneButtonShowCount()
|
|
{
|
|
return sceneNames.Count(x => IsSceneButtonShow(x));
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Display a search bar and handle the search
|
|
/// </summary>
|
|
private void DrawOpenSceneBar()
|
|
{
|
|
//
|
|
GUILayout.BeginHorizontal(GUI.skin.FindStyle("Toolbar"));
|
|
DrawDropDown();
|
|
GUILayout.FlexibleSpace();
|
|
DrawOnlyOnBuildButton();
|
|
DrawRefreshButton();
|
|
GUILayout.FlexibleSpace();
|
|
GUI.SetNextControlName("searchScene");
|
|
|
|
TextEditor editor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
|
|
var nowCursorIndex = editor.cursorIndex;
|
|
if (nowCursorIndex > lastCursorIndex)
|
|
{
|
|
lastCursorIndex = editor.cursorIndex;
|
|
}
|
|
|
|
searchName = GUILayout.TextField(searchName, GUI.skin.FindStyle("ToolbarSeachTextField"), GUILayout.MaxWidth(200f));
|
|
|
|
if (string.IsNullOrEmpty(searchName))
|
|
{
|
|
searchSelected = -1;
|
|
}
|
|
else if (searchSelected < 0)
|
|
{
|
|
searchSelected = 0;
|
|
}
|
|
else
|
|
{
|
|
searchSelected = Mathf.Clamp(searchSelected, 0, SceneButtonShowCount() - 1);
|
|
}
|
|
|
|
|
|
if (GUI.GetNameOfFocusedControl() == "searchScene")
|
|
{
|
|
Event evt = Event.current;
|
|
var keyCode = evt.keyCode;
|
|
if (evt.type == EventType.KeyUp)
|
|
{
|
|
switch (keyCode)
|
|
{
|
|
case KeyCode.Return:
|
|
LoadFirstScene();
|
|
Repaint();
|
|
GUIUtility.ExitGUI();
|
|
break;
|
|
case KeyCode.Escape:
|
|
ClearSearchBar(false);
|
|
Repaint();
|
|
GUIUtility.ExitGUI();
|
|
break;
|
|
case KeyCode.UpArrow:
|
|
EditorGUIUtility.editingTextField = false;
|
|
searchSelected = Mathf.Clamp(searchSelected - 1, 0, SceneButtonShowCount() - 1);
|
|
editor.cursorIndex = editor.selectIndex = editor.text.Length;
|
|
evt.Use();
|
|
Repaint();
|
|
break;
|
|
case KeyCode.DownArrow:
|
|
EditorGUIUtility.editingTextField = false;
|
|
searchSelected = Mathf.Clamp(searchSelected + 1, 0, SceneButtonShowCount() - 1);
|
|
editor.cursorIndex = editor.selectIndex = editor.text.Length;
|
|
evt.Use();
|
|
Repaint();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (GUILayout.Button("", GUI.skin.FindStyle("ToolbarSeachCancelButton")))
|
|
{
|
|
ClearSearchBar();
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
}
|
|
|
|
private void DrawOnlyOnBuildButton()
|
|
{
|
|
GUIContent onlyBuildModeContent = EditorGUIUtility.TrIconContent("BuildSettings.Standalone.Small", "When toggled on, filter only scenes who are in the actual build.");
|
|
var newShowOnlyOnBuild = GUILayout.Toggle(showOnlyOnBuild, onlyBuildModeContent, EditorStyles.toolbarButton);
|
|
|
|
if(newShowOnlyOnBuild != showOnlyOnBuild)
|
|
{
|
|
showOnlyOnBuild = newShowOnlyOnBuild;
|
|
EditorPrefs.SetBool("QuickSceneWindow_showOnlyOnBuild", true);
|
|
}
|
|
}
|
|
|
|
private void DrawRefreshButton()
|
|
{
|
|
GUIContent refreshContent = EditorGUIUtility.TrIconContent("Refresh", "Get all scenes from the Assets folder");
|
|
if (GUILayout.Button(refreshContent, EditorStyles.toolbarButton))
|
|
{
|
|
sceneFetch = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clear the search bar and loose focus if parameter say true
|
|
/// </summary>
|
|
/// <param name="looseFocus"></param>
|
|
private void ClearSearchBar(bool looseFocus = true)
|
|
{
|
|
if (looseFocus)
|
|
GUI.FocusControl(null);
|
|
searchSelected = -1;
|
|
searchName = "";
|
|
}
|
|
|
|
private void LoadFirstScene()
|
|
{
|
|
var scenes = sceneNames.Where(x => IsSceneButtonShow(x)).ToList();
|
|
if (scenes.Count == 1)
|
|
{
|
|
ClearSearchBar();
|
|
OpenScene(sceneNames.IndexOf(scenes.FirstOrDefault()));
|
|
}
|
|
else if (scenes.Count > 1)
|
|
{
|
|
var sceneToOpen = scenes[searchSelected];
|
|
int normalListIndex = sceneNames.IndexOf(sceneToOpen);
|
|
if (normalListIndex != currentSceneIndex)
|
|
OpenScene(normalListIndex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open a specific scene by giving the _buildScenes index
|
|
/// </summary>
|
|
/// <param name="index"></param>
|
|
private void OpenScene(int index)
|
|
{
|
|
EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
|
|
EditorSceneManager.OpenScene(scenePaths[index]);
|
|
GUIUtility.ExitGUI();
|
|
}
|
|
|
|
private List<string> GetAllScenePath()
|
|
{
|
|
List<string> scenePaths = new List<string>();
|
|
string folderName = Application.dataPath.Replace("/", "\\");
|
|
var dirInfo = new DirectoryInfo(folderName);
|
|
var allFileInfos = dirInfo.GetFiles("*.unity", SearchOption.AllDirectories);
|
|
|
|
foreach (var fileInfo in allFileInfos)
|
|
{
|
|
var testPath = Path.Combine(fileInfo.FullName, "");
|
|
var relativePath = testPath.Replace(folderName, "Assets");
|
|
scenePaths.Add(relativePath);
|
|
}
|
|
return scenePaths;
|
|
}
|
|
}
|
|
}
|
|
#endif |