237 lines
9.8 KiB
C#
237 lines
9.8 KiB
C#
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEditorInternal;
|
|
using UnityEngine;
|
|
|
|
namespace HeurekaGames.AssetHunterPRO
|
|
{
|
|
public class AH_DuplicatesWindow : EditorWindow
|
|
{
|
|
private static readonly string WINDOWNAME = "AH Duplicates";
|
|
private static AH_DuplicatesWindow window;
|
|
private AH_DuplicateDataManager duplicateDataManager;
|
|
private Vector2 scrollPosition;
|
|
private int scrollStartIndex;
|
|
private GUIContent guiContentRefresh;
|
|
private GUIContent buttonSelectContent;
|
|
private GUIContent labelBtnContent;
|
|
private GUIStyle labelBtnStyle;
|
|
private List<float> scrollviewPositionList = new List<float>();
|
|
private Rect scrollArea;
|
|
private int scrollEndIndex;
|
|
|
|
//Add menu named "Dependency Graph" to the window menu
|
|
[UnityEditor.MenuItem("Tools/Asset Hunter PRO/Find Duplicates")]
|
|
[UnityEditor.MenuItem("Window/Heureka/Asset Hunter PRO/Find Duplicates")]
|
|
public static void OpenDuplicatesView()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
//Selection.selectionChanged += OnSelectionChanged;
|
|
EditorApplication.projectChanged += EditorApplication_projectChanged;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
EditorApplication.projectChanged -= EditorApplication_projectChanged;
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
initIfNeeded();
|
|
doHeader();
|
|
|
|
if (duplicateDataManager != null)
|
|
{
|
|
//If window has no cached data
|
|
if (!duplicateDataManager.HasCache)
|
|
{
|
|
Heureka_WindowStyler.DrawCenteredMessage(window, AH_EditorData.Instance.DuplicateWhiteIcon.Icon, 240f, 110f, "No data" + Environment.NewLine + "Find duplicates");
|
|
EditorGUILayout.BeginVertical();
|
|
GUILayout.FlexibleSpace();
|
|
Color origClr = GUI.backgroundColor;
|
|
|
|
GUI.backgroundColor = Color.red;
|
|
if (GUILayout.Button("Find Duplicates", GUILayout.Height(40)))
|
|
{
|
|
duplicateDataManager.RefreshData();
|
|
}
|
|
GUI.backgroundColor = origClr;
|
|
EditorGUILayout.EndVertical();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (!duplicateDataManager.HasDuplicates())
|
|
{
|
|
Heureka_WindowStyler.DrawCenteredMessage(window, AH_EditorData.Instance.DuplicateWhiteIcon.Icon, 240f, 110f, "Hurray" + Environment.NewLine + "No duplicates assets" + Environment.NewLine + "in project :)");
|
|
GUILayout.FlexibleSpace();
|
|
}
|
|
else
|
|
doBody();
|
|
}
|
|
}
|
|
doFooter();
|
|
}
|
|
|
|
public static void Init()
|
|
{
|
|
window = AH_DuplicatesWindow.GetWindow<AH_DuplicatesWindow>(WINDOWNAME, true);
|
|
if (window.duplicateDataManager == null)
|
|
window.duplicateDataManager = AH_DuplicateDataManager.instance;
|
|
|
|
window.initializeGUIContent();
|
|
}
|
|
|
|
public static void Init(Docker.DockPosition dockPosition = Docker.DockPosition.Right)
|
|
{
|
|
Init();
|
|
|
|
AH_Window[] mainWindows = Resources.FindObjectsOfTypeAll<AH_Window>();
|
|
if (mainWindows.Length != 0)
|
|
{
|
|
HeurekaGames.Docker.Dock(mainWindows[0], window, dockPosition);
|
|
}
|
|
}
|
|
|
|
private void initIfNeeded()
|
|
{
|
|
if (!duplicateDataManager || !window)
|
|
Init();
|
|
|
|
//This is an (ugly) fix to make sure we dotn loose our icons due to some singleton issues after play/stop
|
|
if (guiContentRefresh.image == null)
|
|
initializeGUIContent();
|
|
}
|
|
|
|
private void initializeGUIContent()
|
|
{
|
|
titleContent = new GUIContent(WINDOWNAME, AH_EditorData.Instance.DuplicateIcon.Icon);
|
|
guiContentRefresh = new GUIContent(AH_EditorData.Instance.RefreshIcon.Icon, "Refresh data");
|
|
|
|
buttonSelectContent = new GUIContent() { };
|
|
|
|
labelBtnStyle = new GUIStyle(EditorStyles.label);
|
|
labelBtnStyle.border = new RectOffset(0, 0, 0, 0);
|
|
|
|
labelBtnContent = new GUIContent();
|
|
}
|
|
|
|
private void EditorApplication_projectChanged()
|
|
{
|
|
duplicateDataManager.IsDirty = true;
|
|
}
|
|
|
|
private void doHeader()
|
|
{
|
|
Heureka_WindowStyler.DrawGlobalHeader(Heureka_WindowStyler.clr_Red, WINDOWNAME);
|
|
}
|
|
private void doBody()
|
|
{
|
|
if(duplicateDataManager.RequiresScrollviewRebuild)
|
|
scrollviewPositionList = new List<float>();
|
|
|
|
using (EditorGUILayout.ScrollViewScope scrollview = new EditorGUILayout.ScrollViewScope(scrollPosition))
|
|
{
|
|
scrollPosition = scrollview.scrollPosition;
|
|
|
|
//Bunch of stuff to figure which guielements we want to draw inside scrollview (We dont want to draw every single element, only the ones that are infact inside scrollview)
|
|
if (Event.current.type == EventType.Layout)
|
|
{
|
|
scrollStartIndex = scrollviewPositionList.FindLastIndex(x => x < scrollPosition.y);
|
|
if (scrollStartIndex == -1) scrollStartIndex = 0;
|
|
|
|
float scrollMaxY = scrollPosition.y + scrollArea.height;
|
|
scrollEndIndex = scrollviewPositionList.FindLastIndex(x => x <= scrollMaxY) + 1; //Add one since we want to make sure the entire height of the guielement is shown
|
|
if (scrollEndIndex > scrollviewPositionList.Count - 1)
|
|
scrollEndIndex = scrollviewPositionList.Count >= 1 ? scrollviewPositionList.Count - 1 : duplicateDataManager.Entries.Count - 1; //Dont want out of bounds
|
|
}
|
|
|
|
//Insert empty space in the BEGINNING of scrollview
|
|
if (scrollStartIndex >= 0 && scrollviewPositionList.Count>0)
|
|
GUILayout.Space(scrollviewPositionList[scrollStartIndex]);
|
|
|
|
int counter = -1;
|
|
foreach (var kvPair in duplicateDataManager.Entries)
|
|
{
|
|
counter++;
|
|
if (counter < scrollStartIndex)
|
|
{
|
|
continue;
|
|
}
|
|
else if (counter > scrollEndIndex)
|
|
{
|
|
break;
|
|
}
|
|
|
|
using (var hScope = new EditorGUILayout.HorizontalScope("box"))
|
|
{
|
|
Rect hScopeSize = hScope.rect;
|
|
buttonSelectContent.image = kvPair.Value.Preview;
|
|
|
|
if (GUILayout.Button(buttonSelectContent, EditorStyles.boldLabel, GUILayout.Width(64), GUILayout.MaxHeight(64)))
|
|
{
|
|
var assets = kvPair.Value.Paths.Select(x => AssetDatabase.LoadMainAssetAtPath(x)).ToArray();
|
|
Selection.objects = assets;
|
|
}
|
|
|
|
//EditorGUILayout.LabelField(kvPair.Key);
|
|
using (var vScope = new EditorGUILayout.VerticalScope("box"))
|
|
{
|
|
foreach (var path in kvPair.Value.Paths)
|
|
{
|
|
using (new EditorGUI.DisabledGroupScope(Selection.objects.Any(x => AssetDatabase.GetAssetPath(x) == path)))
|
|
{
|
|
int charCount = (int)vScope.rect.width / 7;
|
|
labelBtnContent.text = AH_Utils.ShrinkPathEnd(path.Remove(0, 7), charCount);
|
|
labelBtnContent.tooltip = path;
|
|
|
|
if (GUILayout.Button(labelBtnContent, labelBtnStyle))
|
|
Selection.activeObject = AssetDatabase.LoadMainAssetAtPath(path);
|
|
}
|
|
}
|
|
}
|
|
if (duplicateDataManager.RequiresScrollviewRebuild && Event.current.type == EventType.Repaint)
|
|
{
|
|
scrollviewPositionList.Add(hScope.rect.y); //Store Y position of guielement rect
|
|
}
|
|
}
|
|
}
|
|
//We have succesfully rebuild the scrollview position list
|
|
if (duplicateDataManager.RequiresScrollviewRebuild && Event.current.type == EventType.Repaint)
|
|
{
|
|
duplicateDataManager.RequiresScrollviewRebuild = false;
|
|
}
|
|
|
|
//Insert empty space at the END of scrollview
|
|
if (scrollEndIndex < scrollviewPositionList.Count - 1)
|
|
GUILayout.Space(scrollviewPositionList.Last() - scrollviewPositionList[scrollEndIndex]);
|
|
}
|
|
if (Event.current.type == EventType.Repaint)
|
|
scrollArea = GUILayoutUtility.GetLastRect();
|
|
}
|
|
|
|
private void doFooter()
|
|
{
|
|
GUIContent RefreshGUIContent = new GUIContent(guiContentRefresh);
|
|
Color origColor = GUI.color;
|
|
if (duplicateDataManager.IsDirty)
|
|
{
|
|
GUI.color = Heureka_WindowStyler.clr_Red;
|
|
RefreshGUIContent.tooltip = String.Format("{0}{1}", RefreshGUIContent.tooltip, " (Project has changed which means that data is out of sync)");
|
|
}
|
|
|
|
if (AH_UIUtilities.DrawSelectionButton(RefreshGUIContent))
|
|
duplicateDataManager.RefreshData();
|
|
|
|
GUI.color = origColor;
|
|
}
|
|
}
|
|
} |