#24 Unity Hotkeys. L - lock inspector. D - debug inspector
using System;
using System.Reflection;
using UnityEditor;
using UnityEditor.ShortcutManagement;
using UnityEngine;
/// <summary>
/// L = lock last-focused Inspector;
/// D = toggle Debug mode in last-focused Inspector;
/// </summary>
[InitializeOnLoad]
public static class InspectorHotkeysEditor
{
private static EditorWindow s_lastFocusedInspector;
private static Type s_inspectorWindowType;
private static PropertyInfo s_isLockedProperty;
private static FieldInfo s_inspectorModeField;
private static MethodInfo s_setModeMethod;
static InspectorHotkeysEditor()
{
EditorApplication.update += OnUpdate;
}
private static void OnUpdate()
{
// Track last focused Inspector so L/D work even when another pane (e.g. Scene) has focus
var focused = EditorWindow.focusedWindow;
if (focused != null && IsInspectorWindow(focused))
s_lastFocusedInspector = focused;
}
private static bool IsGameViewFocused()
{
var w = EditorWindow.focusedWindow;
const string gameViewName = "GameView";
return w != null && w.GetType().Name == gameViewName;
}
private static bool IsSceneViewFocused()
{
var w = EditorWindow.focusedWindow;
const string sceneViewName = "SceneView";
return w != null && w.GetType().Name == sceneViewName;
}
/// <summary>L and D are only allowed when Inspector or Hierarchy has focus (not Scene or Game view).</summary>
private static bool AllowInspectorHotkeys()
{
if (IsGameViewFocused() || IsSceneViewFocused()) return false;
return true;
}
private static bool IsInspectorWindow(EditorWindow w)
{
const string inspectorWindowName = "InspectorWindow";
return w != null && w.GetType().Name == inspectorWindowName;
}
private static EditorWindow GetInspectorToActOn()
{
// Prefer the currently focused inspector, else the last focused one
var focused = EditorWindow.focusedWindow;
if (IsInspectorWindow(focused))
return focused;
return s_lastFocusedInspector;
}
private static void EnsureReflection()
{
const string inspectorWindowTypeName = "UnityEditor.InspectorWindow";
const string isLockedPropertyName = "isLocked";
const string inspectorModeFieldName = "m_InspectorMode";
const string setModeMethodName = "SetMode";
if (s_inspectorWindowType != null) return;
var asm = typeof(UnityEditor.Editor).Assembly;
s_inspectorWindowType = asm.GetType(inspectorWindowTypeName);
if (s_inspectorWindowType == null) return;
s_isLockedProperty = s_inspectorWindowType.GetProperty(isLockedPropertyName);
s_inspectorModeField = s_inspectorWindowType.GetField(inspectorModeFieldName, BindingFlags.NonPublic | BindingFlags.Instance);
s_setModeMethod = s_inspectorWindowType.GetMethod(setModeMethodName, BindingFlags.NonPublic | BindingFlags.Instance);
}
[Shortcut("Tools/Inspector Lock", KeyCode.L)]
private static void ToggleInspectorLock()
{
if (!AllowInspectorHotkeys()) return;
var inspector = GetInspectorToActOn();
if (inspector == null) return;
EnsureReflection();
if (s_inspectorWindowType == null || s_isLockedProperty == null) return;
if (!s_inspectorWindowType.IsInstanceOfType(inspector)) return;
try
{
bool current = (bool)s_isLockedProperty.GetValue(inspector, null);
s_isLockedProperty.SetValue(inspector, !current, null);
inspector.Repaint();
}
catch (Exception) { /* ignore */ }
}
[Shortcut("Tools/Inspector Toggle Debug", KeyCode.D)]
private static void ToggleInspectorDebug()
{
if (!AllowInspectorHotkeys()) return;
var inspector = GetInspectorToActOn();
if (inspector == null) return;
EnsureReflection();
if (s_inspectorWindowType == null || s_inspectorModeField == null || s_setModeMethod == null) return;
if (!s_inspectorWindowType.IsInstanceOfType(inspector)) return;
try
{
var mode = (InspectorMode)s_inspectorModeField.GetValue(inspector);
var next = mode == InspectorMode.Normal ? InspectorMode.Debug : InspectorMode.Normal;
s_setModeMethod.Invoke(inspector, new object[] { next });
inspector.Repaint();
}
catch (Exception) { /* ignore */ }
}
}