Skip to content

v2.0 #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions Editor.meta

This file was deleted.

8 changes: 0 additions & 8 deletions Editor/SceneSwitcher.meta

This file was deleted.

19 changes: 19 additions & 0 deletions Editor/SceneSwitcher/AssetChangeListener.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using UnityEditor;

namespace RimuruDevUtils.SceneSwitcher
{
public class AssetChangeListener : AssetPostprocessor
{
public static event Action AssetsWereChanged;

private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets,
string[] movedFromAssetPaths)
{
if (importedAssets.Length != 0 || deletedAssets.Length != 0)
{
AssetsWereChanged?.Invoke();
}
}
}
}
304 changes: 245 additions & 59 deletions Editor/SceneSwitcher/SceneSwitcher.cs
Original file line number Diff line number Diff line change
@@ -1,113 +1,299 @@
// **************************************************************** //
//
// Copyright (c) RimuruDev. All rights reserved.
// Contact me:
// Contact me:
// - Gmail: [email protected]
// - LinkedIn: https://www.linkedin.com/in/rimuru/
// - Gists: https://gist.github.com/RimuruDev/af759ce6d9768a38f6838d8b7cc94fc8
// - GitHub: https://github.com/RimuruDev
// - GitHub Organizations: https://github.com/Rimuru-Dev
//
// **************************************************************** //

#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEditor.SceneManagement;
using UnityEngine;

namespace AbyssMoth.External.RimuruDevUtils.Editor.SceneSwitcher
namespace RimuruDevUtils.SceneSwitcher
{
public sealed class SceneSwitcher : EditorWindow
{
private const string CtrlF2 = "%#F2";
private const string FindAssets = "t:Scene";
private const string logFormat = "<color=yellow>{0}</color>";

private bool showAllScenes;
private bool autoSaveEnabled = true;
private bool settingsFoldout = true;
private bool showDebugLog;
private bool compactButtons;
private Vector2 scrollPosition;

[MenuItem("RimuruDev Tools/Scene Switcher " + CtrlF2)]
private const string SETTINGS_STORAGE_PATH = "Assets/Editor/SceneSwitcher/SceneSwitcherSettings.asset";
private const string SCENE_NAME_PLACE = "SCENE_NAME";

private const string EXIT_PLAY_MODE = "Exit Play Mode";
private const string RETURN_TO_PREVIOUS_BUTTON = " <- |Return| <- ";
private const string SETTINGS_BUTTON = "Open Settings";
private const string ENABLE_CUSTOM_PLAY_MODE_START_SCENE = " Enable Custom Play Mode Start Scene";
private const string DISABLE_CUSTOM_PLAY_MODE_START_SCENE = "Disable Custom Play Mode Start Scene";

private string[] scenes;
private string CurrentScene => EditorSceneManager.GetActiveScene().path;
private string Previous;

private SceneAsset customPlayModeStartScene;
private string customPlayModeStartScenePath;

private Settings CurrentSettings => settingsAsset.Settings;
private SceneSwitcherSettingsScriptableObject settingsAsset;

[MenuItem("Tools/Scene Switcher")]
private static void ShowWindow()
{
GetWindow<SceneSwitcher>();
GetWindow(typeof(SceneSwitcher));
}

private void Awake()
{
if (!LoadSettings())
{
CreateNewSettingsAsset();
LoadSettings();
}

CollectScenes();
}

private void OnGUI()
private void OnEnable()
{
GUILayout.Label("Scene Switcher", EditorStyles.boldLabel);
EditorBuildSettings.sceneListChanged += CollectScenes;
AssetChangeListener.AssetsWereChanged += CollectScenes;

settingsFoldout = EditorGUILayout.Foldout(settingsFoldout, "Settings");

if (settingsFoldout)
}

private void OnDisable()
{
EditorBuildSettings.sceneListChanged -= CollectScenes;
AssetChangeListener.AssetsWereChanged -= CollectScenes;
}

private void OnGUI()
{
if (EditorApplication.isPlaying)
{
EditorGUI.indentLevel++;
if (GUILayout.Button(EXIT_PLAY_MODE, GUILayout.Height(position.height), GUILayout.Width(position.width)))
{
showAllScenes = EditorGUILayout.Toggle("Show Absolutely All Scenes", showAllScenes);
autoSaveEnabled = EditorGUILayout.Toggle("Enable Auto Save", autoSaveEnabled);
showDebugLog = EditorGUILayout.Toggle("Show Debug Log", showDebugLog);
compactButtons = EditorGUILayout.Toggle("Compact Buttons", compactButtons);
EditorApplication.ExitPlaymode();
}
EditorGUI.indentLevel--;
return;
}

if(CurrentSettings.ShowReturnToPreviousButton)
{
DrawReturnToPrevious();
GUILayout.Space(CurrentSettings.SpaceAfterReturnButton);
}

DrawSceneButtons();
GUILayout.Space(CurrentSettings.SpaceAfterSceneButtons);

if(CurrentSettings.EnableCustomPlayModeStartSceneButton)
{
DrawCustomPlayModeStartSceneButtons();
}

scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, true, GUILayout.Width(350), GUILayout.Height(350));
DrawSettingsButton();
}

var scenePaths = showAllScenes
? GetAllScenePaths()
: GetScenePathsByBuildSettings();

var buttonWidth = compactButtons
? 200
: 300;
private void DrawReturnToPrevious()
{
if(Previous == "") return;

GUILayout.Space(10);

if(GUILayout.Button(RETURN_TO_PREVIOUS_BUTTON, GUILayout.Height(CurrentSettings.ReturnButtonHeight)))
{
SwitchTo(Previous);
}
}

foreach (var scenePath in scenePaths)
private void DrawSceneButtons()
{
if (scenes.Length == 0)
{
EditorGUILayout.HelpBox(" ZERO SCENES FOUND/SELECTED", MessageType.Info);
}

for (int i = 0; i < scenes.Length; i++)
{
string scenePath = scenes[i];

GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();

if (GUILayout.Button(Path.GetFileNameWithoutExtension(scenePath), GUILayout.Width(buttonWidth)))
string buttonText = Path.GetFileNameWithoutExtension(scenePath);

//add play mode start scene indicator
if (EditorSceneManager.playModeStartScene != null && scenePath == customPlayModeStartScenePath)
{
if (autoSaveEnabled && EditorSceneManager.SaveOpenScenes())
{
if (showDebugLog)
Debug.LogFormat(logFormat, "Scenes saved!");
}
buttonText = CurrentSettings.CustomStartSceneLabelFormatting.Replace(SCENE_NAME_PLACE, buttonText);
}
//add current scene indicator
if (scenePath == CurrentScene)
{
buttonText = CurrentSettings.CurrentSceneButtonFormatting.Replace(SCENE_NAME_PLACE, buttonText);
}

EditorSceneManager.OpenScene(scenePath);
if (GUILayout.Button(buttonText, GUILayout.Width(position.width),
GUILayout.Height(CurrentSettings.SceneButtonHeight)))
{
SwitchTo(scenePath);
}

GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();

if(i < scenes.Length - 1)
{
GUILayout.Space(CurrentSettings.SpaceBetweenSceneButtons);
}
}
}

GUILayout.EndScrollView();
private void DrawCustomPlayModeStartSceneButtons()
{
if (EditorSceneManager.playModeStartScene == null && GUILayout.Button(ENABLE_CUSTOM_PLAY_MODE_START_SCENE))
{
EditorSceneManager.playModeStartScene = customPlayModeStartScene;
}
else if (EditorSceneManager.playModeStartScene != null && GUILayout.Button(DISABLE_CUSTOM_PLAY_MODE_START_SCENE))
{
EditorSceneManager.playModeStartScene = null;
}
}

private static string[] GetScenePathsByBuildSettings()
private void DrawSettingsButton()
{
var scenes = EditorBuildSettings.scenes;
var paths = new string[scenes.Length];
if (GUILayout.Button(SETTINGS_BUTTON, GUILayout.Height(CurrentSettings.SettingButtonHeight)))
{
Selection.activeObject = settingsAsset;
}
}

private void CollectScenes()
{
customPlayModeStartScenePath = EditorBuildSettings.scenes[CurrentSettings.CustomPlayModeStartSceneBuildIndex].path;
customPlayModeStartScene = AssetDatabase.LoadAssetAtPath<SceneAsset>(customPlayModeStartScenePath);

switch(CurrentSettings.WhichScenesCollect)
{
case Settings.Collect.OnlyFromBuild:
scenes = new string[EditorBuildSettings.scenes.Length];
for (int i = 0; i < scenes.Length; i++)
{
scenes[i] = EditorBuildSettings.scenes[i].path;
}
break;

case Settings.Collect.CustomList:
//clear from nulls
CurrentSettings.CustomSceneList.RemoveAll((asset) => asset == null);
//clear from duplicates
CurrentSettings.CustomSceneList = CurrentSettings.CustomSceneList.Distinct().ToList();

for (var i = 0; i < scenes.Length; i++)
paths[i] = scenes[i].path;
scenes = new string[CurrentSettings.CustomSceneList.Count];
for (int i = 0; i < CurrentSettings.CustomSceneList.Count; i++)
{
var sceneAsset = CurrentSettings.CustomSceneList[i];
if(sceneAsset == null) continue;

return paths;
scenes[i] = AssetDatabase.GetAssetPath(sceneAsset);
}
break;
case Settings.Collect.All:
string[] guids = AssetDatabase.FindAssets("t:Scene");
scenes = new string[guids.Length];
for (int i = 0; i < guids.Length; i++)
{
scenes[i] = AssetDatabase.GUIDToAssetPath(guids[i]);
}
break;
default: throw new ArgumentOutOfRangeException();
}
}

private static string[] GetAllScenePaths()
private void SwitchTo(string path)
{
var guids = AssetDatabase.FindAssets(FindAssets);
var scenePaths = new string[guids.Length];
if(path == CurrentScene) return;

if (CurrentSettings.SaveSceneSwitch)
{
EditorSceneManager.SaveOpenScenes();
}

Previous = CurrentScene;
EditorSceneManager.OpenScene(path);
}

for (var i = 0; i < guids.Length; i++)
scenePaths[i] = AssetDatabase.GUIDToAssetPath(guids[i]);
private bool LoadSettings()
{
settingsAsset = AssetDatabase.LoadAssetAtPath<SceneSwitcherSettingsScriptableObject>(SETTINGS_STORAGE_PATH);
return settingsAsset != null;
}

return scenePaths;
private static void CreateNewSettingsAsset()
{
string[] slicedPath = Path.GetDirectoryName(SETTINGS_STORAGE_PATH)?.Split(Path.DirectorySeparatorChar);

if(slicedPath != null && slicedPath.Length <= 1)
{
Debug.LogError($"[SCENE SWITCHER] CANNOT CREATE SETTINGS ASSET. INVALID PATH: {SETTINGS_STORAGE_PATH}");
}

string currentDirectory = slicedPath[0];

for (int i = 1; i < slicedPath.Length; i++)
{
string folder = slicedPath[i];
string nextDirectory = Path.Join(currentDirectory, folder);

if (!AssetDatabase.IsValidFolder(nextDirectory))
{
AssetDatabase.CreateFolder(currentDirectory, folder);
}

currentDirectory = nextDirectory;
}

AssetDatabase.Refresh();

AssetDatabase.CreateAsset(CreateInstance<SceneSwitcherSettingsScriptableObject>(),SETTINGS_STORAGE_PATH);
Debug.Log($"[SCENE SWITCHER] CREATED NEW SCENE SWITCHER SETTINGS ASSET AT {Path.GetDirectoryName(SETTINGS_STORAGE_PATH)}");
}

[Serializable]
public class Settings
{
public Collect WhichScenesCollect = Collect.OnlyFromBuild;
public bool ShowReturnToPreviousButton = false;
public bool EnableCustomPlayModeStartSceneButton = false;

public int CustomPlayModeStartSceneBuildIndex = 0;
public bool SaveSceneSwitch = true;

public List<SceneAsset> CustomSceneList;

[Range(15, 50)] public int ReturnButtonHeight = 20;
[Range(15, 50)] public int SceneButtonHeight = 20;
[Range(15, 50)] public int SettingButtonHeight = 15;

[Range(0, 20)] public int SpaceAfterReturnButton = 10;
[Range(0, 20)] public int SpaceBetweenSceneButtons = 0;
[Range(0, 20)] public int SpaceAfterSceneButtons = 20;

public string CurrentSceneButtonFormatting = "> SCENE_NAME <";
public string CustomStartSceneLabelFormatting = "(PM) SCENE_NAME";

public enum Collect
{
OnlyFromBuild,
CustomList,
All
}
}
}
}
#endif
}
Loading