152 lines
6.4 KiB
C#
152 lines
6.4 KiB
C#
using UnityEngine;
|
|
using UnityEditor;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
namespace DreadScripts.NoAutoGame
|
|
{
|
|
internal static class NoAutoGame
|
|
{
|
|
#region Constants
|
|
private const string GAME_WINDOW_TYPE_ASSEMBLY_FULL_NAME = "UnityEditor.GameView, UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
|
|
private const string GAME_WINDOW_OPEN_SESS_KEY = "NoAutoGameWindowWasOpen";
|
|
private const string LAST_WINDOWS_SESS_KEY = "NoAutoGameLastWindowsIDs";
|
|
|
|
private const string CLOSE_GAME_WINDOW_PREF_KEY = "NoAutoGameCloseGameWindow";
|
|
private const string UNFOCUS_GAME_WINDOW_PREF_KEY = "NoAutoGameUnfocusGameView";
|
|
private const int GAME_WINDOW_HANDLE_DELAY = 100;
|
|
#endregion
|
|
|
|
private static Type _gameWindowType;
|
|
private static Type gameWindowType => _gameWindowType ?? (_gameWindowType = Type.GetType(GAME_WINDOW_TYPE_ASSEMBLY_FULL_NAME));
|
|
private static readonly PropertyInfo hasFocusProperty = typeof(EditorWindow).GetProperty("hasFocus", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
|
|
|
private static CancellationTokenSource cts;
|
|
|
|
private static bool closeGameWindow;
|
|
private static bool unfocusGameWindow;
|
|
private static EditorWindow[] previouslyFocusedWindows;
|
|
private static void HandlePlaymodeChange(PlayModeStateChange change)
|
|
{
|
|
cts?.Cancel();
|
|
|
|
switch (change)
|
|
{
|
|
case PlayModeStateChange.ExitingEditMode:
|
|
RememberWindows();
|
|
break;
|
|
case PlayModeStateChange.EnteredPlayMode:
|
|
try
|
|
{
|
|
cts = new CancellationTokenSource();
|
|
_ = HandleGameWindow(cts.Token);
|
|
}
|
|
catch(OperationCanceledException){}
|
|
break;
|
|
case PlayModeStateChange.EnteredEditMode:
|
|
SessionState.EraseString(LAST_WINDOWS_SESS_KEY);
|
|
if (!closeGameWindow && unfocusGameWindow && !SessionState.GetBool(GAME_WINDOW_OPEN_SESS_KEY, true))
|
|
{
|
|
var gameWindows = (EditorWindow[])Resources.FindObjectsOfTypeAll(gameWindowType);
|
|
if (gameWindows.Any() && !gameWindows.Any(w => previouslyFocusedWindows.Contains(w)))
|
|
foreach(var w in gameWindows)
|
|
w.Close();
|
|
}
|
|
|
|
previouslyFocusedWindows = null;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static void RememberWindows()
|
|
{
|
|
if (unfocusGameWindow && hasFocusProperty != null)
|
|
{
|
|
var idList = string.Join(",", Resources.FindObjectsOfTypeAll<EditorWindow>()
|
|
.Where(w => (bool) hasFocusProperty.GetValue(w))
|
|
.Select(w => w.GetInstanceID().ToString()));
|
|
|
|
SessionState.SetString(LAST_WINDOWS_SESS_KEY, idList);
|
|
}
|
|
|
|
if (gameWindowType == null) return;
|
|
var gameWindows = Resources.FindObjectsOfTypeAll(gameWindowType);
|
|
SessionState.SetBool(GAME_WINDOW_OPEN_SESS_KEY, gameWindows.Length > 0); }
|
|
|
|
private static async Task HandleGameWindow(CancellationToken ct)
|
|
{
|
|
if (!closeGameWindow && !unfocusGameWindow) return;
|
|
var gameWindowWasOpen = SessionState.GetBool(GAME_WINDOW_OPEN_SESS_KEY, true);
|
|
await Task.Delay(GAME_WINDOW_HANDLE_DELAY, ct);
|
|
|
|
if (closeGameWindow && !gameWindowWasOpen)
|
|
{
|
|
var windows = Resources.FindObjectsOfTypeAll(gameWindowType);
|
|
foreach (var w in windows)
|
|
{
|
|
var ew = (EditorWindow)w;
|
|
ew.Close();
|
|
}
|
|
} else if (unfocusGameWindow)
|
|
{
|
|
var previousWindowsFocusList = SessionState.GetString(LAST_WINDOWS_SESS_KEY, string.Empty);
|
|
if (string.IsNullOrWhiteSpace(previousWindowsFocusList)) return;
|
|
|
|
previouslyFocusedWindows = previousWindowsFocusList
|
|
.Split(',').Select(int.Parse)
|
|
.Select(EditorUtility.InstanceIDToObject)
|
|
.OfType<EditorWindow>().Where(w => w != null).ToArray();
|
|
foreach (var w in previouslyFocusedWindows)
|
|
w.Focus();
|
|
}
|
|
}
|
|
|
|
|
|
#region Initialization
|
|
[InitializeOnLoadMethod]
|
|
private static void Initialize() => LoadVariables();
|
|
private static void LoadVariables()
|
|
{
|
|
closeGameWindow = EditorPrefs.GetBool(CLOSE_GAME_WINDOW_PREF_KEY, false);
|
|
unfocusGameWindow = EditorPrefs.GetBool(UNFOCUS_GAME_WINDOW_PREF_KEY, true);
|
|
RefreshHook();
|
|
}
|
|
|
|
private static void RefreshHook()
|
|
{
|
|
EditorApplication.playModeStateChanged -= HandlePlaymodeChange;
|
|
if (closeGameWindow || unfocusGameWindow)
|
|
EditorApplication.playModeStateChanged += HandlePlaymodeChange;
|
|
}
|
|
#endregion
|
|
|
|
#region Menu Items
|
|
[MenuItem("DreadTools/Utility/NoAutoGame/AutoUnfocus")]
|
|
private static void ToggleUnfocusGameWindow()
|
|
{
|
|
bool newValue = !EditorPrefs.GetBool(UNFOCUS_GAME_WINDOW_PREF_KEY, true);
|
|
EditorPrefs.SetBool(UNFOCUS_GAME_WINDOW_PREF_KEY, newValue);
|
|
Debug.Log($"[NoAutoGame] AutoUnfocus is now {(newValue ? "enabled" : "disabled")}.");
|
|
unfocusGameWindow = newValue;
|
|
RefreshHook();
|
|
}
|
|
|
|
[MenuItem("DreadTools/Utility/NoAutoGame/AutoClose")]
|
|
private static void ToggleCloseGameWindow()
|
|
{
|
|
bool newValue = !EditorPrefs.GetBool(CLOSE_GAME_WINDOW_PREF_KEY, false);
|
|
EditorPrefs.SetBool(CLOSE_GAME_WINDOW_PREF_KEY, newValue);
|
|
Debug.Log($"[NoAutoGame] AutoClose is now {(newValue ? "enabled" : "disabled")}.");
|
|
closeGameWindow = newValue;
|
|
RefreshHook();
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
|
|
|
|
}
|