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 = 3 2 ;
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 ( 2 4 ) ) )
if ( GUILayout . Button ( "�" , GUILayout . Width ( 1 6 ) ) )
{
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 ( 2 4 ) ) )
if ( GUILayout . Button ( Contents . star , Styles . icon , GUILayout . Width ( 1 6 ) ) )
{
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 ( 4 8 ) ) )
{
Selection . activeObject = obj ;
SceneView . lastActiveSceneView . FrameSelected ( ) ;
}
if ( GUILayout . Button ( "Focus" , EditorStyles . miniButton , GUILayout . Width ( 4 0 ) ) )
else if ( GUILayout . Button ( "Open" , Styles . historyButton , GUILayout . Width ( 4 8 ) ) )
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 ( 2 4 ) ) )
if ( GUILayout . Button ( favorited ? Contents . star : Contents . starDisabled , Styles . icon , GUILayout . Width ( 1 6 ) ) )
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 ( 4 0 ) ) )
if ( obj is GameObject & & ! PrefabUtility . IsPartOfPrefabAsset ( obj ) )
ignoreNextSelection = true ;
Selection . activeObject = obj ;
SceneView . lastActiveSceneView . FrameSelected ( ) ;
if ( GUILayout . Button ( "Focus" , Styles . historyButton , GUILayout . Width ( 4 8 ) ) )
{
Selection . activeObject = obj ;
SceneView . lastActiveSceneView . FrameSelected ( ) ;
}
}
else if ( GUILayout . Button ( "Open" , Styles . historyButton , GUILayout . Width ( 4 8 ) ) )
{
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 = 1 6 ;
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 = 1 6 ;
icon . padding = new RectOffset ( 8 , 2 , 2 , 0 ) ;
icon . margin = new RectOffset ( ) ;
icon . fixedWidth = 1 6 ;
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" ;
}
}
}
}