浏览代码

Improved Selection History (#71)

* Improved Selection History

* Manage Selection + Highlight / Removed System to simplify explicit references to UnityEngine.Object

* Added Open option for assets (instead of Focus)

* History is now tracked even if window is closed. Opens the window with Alt+H

* Added Object Type to label

* Got rid of Ignore Next Selection
/main
GitHub 2 年前
当前提交
3467fe16
共有 1 个文件被更改,包括 149 次插入105 次删除
  1. 254
      Editor/SelectionHistory/SelectionHistoryWindow.cs

254
Editor/SelectionHistory/SelectionHistoryWindow.cs


using System;
using System.Reflection;
public class SelectionHistoryWindow : EditorWindow
class SelectionHistoryWindow : EditorWindow
[MenuItem("Window/General/Selection History")]
public static SelectionHistoryWindow instance { get => s_Instance; }
public static SelectionHistoryWindow s_Instance;
[MenuItem("Window/General/Selection History &H")]
EditorWindow.GetWindow<SelectionHistoryWindow>();
s_Instance = EditorWindow.GetWindow<SelectionHistoryWindow>();
}
private void OnDestroy()
{
s_Instance = null;
}
Vector2 scrollPos = Vector2.zero;

titleContent = Contents.title;
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);

EditorGUILayout.EndScrollView();
}
void OnEnable()
{
lockedObjects = null;
selectionHistory = null;
}
void OnDisable()
{
lockedObjects = null;
selectionHistory = null;
}
List<GameObject> selectionHistory;
List<GameObject> lockedObjects;
int maxHistoryCount = 32;
bool ignoreNextSelection = false;
void OnSelectionChange()
{
if (ignoreNextSelection)
{
ignoreNextSelection = false;
return;
}
if (selectionHistory == null) selectionHistory = new List<GameObject>();
if (lockedObjects == null) lockedObjects = new List<GameObject>();
if (Selection.activeGameObject != null || Selection.gameObjects.Length > 0)
{
foreach(var go in Selection.gameObjects)
{
if (!selectionHistory.Contains(go))
selectionHistory.Add(go);
}
if (selectionHistory.Count > maxHistoryCount)
selectionHistory.Take(maxHistoryCount);
Repaint();
}
}
public bool CompareArray(GameObject[] a, GameObject[] b)
public bool CompareArray(Object[] a, Object[] b)
{
return a.SequenceEqual(b);
}

if (selectionHistory == null) selectionHistory = new List<GameObject>();
if (lockedObjects == null) lockedObjects = new List<GameObject>();
if (History.selectionHistory == null) History.selectionHistory = new List<Object>();
if (History.lockedObjects == null) History.lockedObjects = new List<Object>();
if (lockedObjects.Count > 0)
if (History.lockedObjects.Count > 0)
GUILayout.Label("Favorites", EditorStyles.boldLabel);
GUI.backgroundColor = new Color(0, 0, 0, 0.2f);
using (new GUILayout.HorizontalScope(EditorStyles.toolbar))
{
GUILayout.Label("Favorites", EditorStyles.boldLabel);
}
GUI.backgroundColor = Color.white;
foreach (var obj in lockedObjects)
foreach (var obj in History.lockedObjects)
if (GUILayout.Button("X", GUILayout.Width(24)))
if (GUILayout.Button("�", GUILayout.Width(16)))
{
toRemove = i;
}

{
bool highlight = Selection.gameObjects.Contains(obj);
Color backup = GUI.color;
if (highlight)
GUI.color = Styles.highlightColor;
bool highlight = Selection.objects.Contains(obj);
GUI.backgroundColor = highlight ? Styles.highlightColor : Color.white;
using (new EditorGUILayout.HorizontalScope())
using (new EditorGUILayout.HorizontalScope(Styles.historyLine))
if (GUILayout.Button(Contents.star, Styles.icon, GUILayout.Width(24)))
if (GUILayout.Button(Contents.star, Styles.icon, GUILayout.Width(16)))
{
toRemove = i;
}

string label = obj.name;
GUIContent label = EditorGUIUtility.ObjectContent(obj, obj.GetType());
string name = label.text;
label.text = string.Empty;
GUILayout.Label(label, Styles.icon);
if (GUILayout.Button($"{name} ({obj.GetType().Name})", Styles.historyItem))
{
Selection.activeObject = obj;
}
if (GUILayout.Button(label, EditorStyles.foldout))
if (obj is GameObject && !PrefabUtility.IsPartOfPrefabAsset(obj))
ignoreNextSelection = true;
Selection.activeObject = obj;
if (GUILayout.Button("Focus", Styles.historyButton, GUILayout.Width(48)))
{
Selection.activeObject = obj;
SceneView.lastActiveSceneView.FrameSelected();
}
if (GUILayout.Button("Focus", EditorStyles.miniButton, GUILayout.Width(40)))
else if (GUILayout.Button("Open", Styles.historyButton, GUILayout.Width(48)))
ignoreNextSelection = true;
Selection.activeObject = obj;
SceneView.lastActiveSceneView.FrameSelected();
AssetDatabase.OpenAsset(obj);
GUI.color = backup;
if (toRemove != -1) lockedObjects.RemoveAt(toRemove);
if (toRemove != -1) History.lockedObjects.RemoveAt(toRemove);
GUILayout.Space(8);
using (new EditorGUILayout.HorizontalScope())
GUI.backgroundColor = new Color(0, 0, 0, 0.2f);
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar))
if (GUILayout.Button("Clear", EditorStyles.miniButton))
if (GUILayout.Button("Clear", EditorStyles.toolbarButton))
selectionHistory.Clear();
History.selectionHistory.Clear();
GUILayout.Space(8);
var reversedHistory = selectionHistory.Reverse<GameObject>().ToArray();
GUI.backgroundColor = Color.white;
var reversedHistory = History.selectionHistory.Reverse<Object>().ToArray();
bool highlight = Selection.gameObjects.Contains(obj);
Color backup = GUI.color;
if (highlight)
GUI.color = Styles.highlightColor;
bool highlight = Selection.objects.Contains(obj);
GUI.backgroundColor = highlight ? Styles.highlightColor : Color.white;
using (new EditorGUILayout.HorizontalScope())
using (new EditorGUILayout.HorizontalScope(Styles.historyLine))
bool favorited = History.lockedObjects.Contains(obj);
if (GUILayout.Button(Contents.starDisabled, Styles.icon, GUILayout.Width(24)))
if (GUILayout.Button(favorited ? Contents.star : Contents.starDisabled, Styles.icon, GUILayout.Width(16)))
toAdd = i;
if (!favorited)
toAdd = i;
else
toRemove = i;
string label = obj.name;
if (GUILayout.Button(label, EditorStyles.foldout))
GUIContent label = EditorGUIUtility.ObjectContent(obj, obj.GetType());
string name = label.text;
label.text = string.Empty;
GUILayout.Label(label, Styles.icon);
if (GUILayout.Button($"{name} ({obj.GetType().Name})", Styles.historyItem))
ignoreNextSelection = true;
if (GUILayout.Button("Focus", Styles.historyButton, GUILayout.Width(40)))
if (obj is GameObject && !PrefabUtility.IsPartOfPrefabAsset(obj))
ignoreNextSelection = true;
Selection.activeObject = obj;
SceneView.lastActiveSceneView.FrameSelected();
if (GUILayout.Button("Focus", Styles.historyButton, GUILayout.Width(48)))
{
Selection.activeObject = obj;
SceneView.lastActiveSceneView.FrameSelected();
}
}
else if (GUILayout.Button("Open", Styles.historyButton, GUILayout.Width(48)))
{
AssetDatabase.OpenAsset(obj);
var rect = GUILayoutUtility.GetLastRect();
EditorGUI.DrawRect(rect, new Color(0.2f,0.2f,0.2f,0.5f));
GUI.color = backup;
}
i++;

lockedObjects.Add(reversedHistory[toAdd]);
History.lockedObjects.Add(reversedHistory[toAdd]);
selectionHistory.RemoveAt(toRemove);
History.lockedObjects.Remove(reversedHistory[toRemove]);
[InitializeOnLoad]
static class History
{
[SerializeField]
internal static List<Object> selectionHistory;
[SerializeField]
internal static List<Object> lockedObjects;
static History()
{
selectionHistory = new List<Object>();
lockedObjects = new List<Object>();
Selection.selectionChanged += OnSelectionChange;
}
static void OnSelectionChange()
{
if (selectionHistory == null) selectionHistory = new List<Object>();
if (lockedObjects == null) lockedObjects = new List<Object>();
if (Selection.activeObject != null || Selection.objects.Length > 0)
{
foreach (var obj in Selection.objects)
{
if (!selectionHistory.Contains(obj))
selectionHistory.Add(obj);
}
}
if (SelectionHistoryWindow.instance != null)
SelectionHistoryWindow.instance.Repaint();
}
}
public static GUIStyle historyLine;
public static GUIStyle historyItem;
public static Color highlightColor = new Color(2.0f, 2.0f, 2.0f);
public static Color highlightColor = new Color(1.0f, 1.5f, 2.0f);
historyLine = new GUIStyle(EditorStyles.toolbarButton);
historyItem = new GUIStyle(EditorStyles.foldout);
historyItem.active.background = Texture2D.blackTexture;
historyItem.onActive.background = Texture2D.blackTexture;
historyItem.focused.background = Texture2D.blackTexture;
historyItem.onFocused.background = Texture2D.blackTexture;
historyItem.hover.background = Texture2D.blackTexture;
historyItem.onHover.background = Texture2D.blackTexture;
historyItem.normal.background = Texture2D.blackTexture;
historyItem.onNormal.background = Texture2D.blackTexture;
historyItem.fixedHeight = 16;
historyItem.padding = new RectOffset();
highlight = new GUIStyle(EditorStyles.miniLabel);
highlight.onNormal.background = Texture2D.whiteTexture;
highlight.onHover.background = Texture2D.whiteTexture;

icon = new GUIStyle(EditorStyles.label);
icon.fixedHeight = 16;
icon.padding = new RectOffset(8,2,2,0);
icon.margin = new RectOffset();
icon.fixedWidth = 16;
icon.padding = new RectOffset();
icon.margin = new RectOffset(0,8,0,0);
}
}

public static GUIContent title = new GUIContent("Selection History");
public static GUIContent title;
static Contents()
{
title = EditorGUIUtility.IconContent("EventTrigger Icon");
title.text = "Selection History";
}
}
}
}
正在加载...
取消
保存