370 lines
15 KiB
C#
Executable File
370 lines
15 KiB
C#
Executable File
using System;
|
||
using System.Collections.Generic;
|
||
using System.Reflection;
|
||
using System.Runtime.Serialization.Formatters.Binary;
|
||
using UnityEngine;
|
||
using UnityEditor;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using Object = UnityEngine.Object;
|
||
|
||
namespace ReferenceViewer
|
||
{
|
||
public class ReferenceViewer : EditorWindow
|
||
{
|
||
private List<Item> items = new List<Item>();
|
||
private Vector2 pos = Vector2.zero;
|
||
private int selectedFilter;
|
||
|
||
static Dictionary<string, List<GUIContent>> sceneReference = new Dictionary<string, List<GUIContent>>();
|
||
|
||
static Dictionary<string, bool> foldouts = new Dictionary<string, bool>();
|
||
|
||
[MenuItem("Window/ReferenceViewer")]
|
||
private static void Open()
|
||
{
|
||
GetWindow<ReferenceViewer>();
|
||
}
|
||
|
||
[MenuItem("Assets/Find References In Project", true)]
|
||
private static bool FindValidate()
|
||
{
|
||
return Selection.objects.Length != 0;
|
||
}
|
||
|
||
[MenuItem("Assets/Find References In Project")]
|
||
private static void Find()
|
||
{
|
||
sceneReference.Clear();
|
||
var path = "build/ReferenceViewer/data.dat";
|
||
|
||
var selectedObjects = Selection.objects;
|
||
|
||
Action find = () =>
|
||
{
|
||
var data = UnityEditorInternal.InternalEditorUtility.LoadSerializedFileAndForget(path)[0] as Data;
|
||
Find(data, selectedObjects);
|
||
};
|
||
|
||
if (File.Exists(path))
|
||
{
|
||
find();
|
||
}
|
||
else
|
||
{
|
||
if (EditorUtility.DisplayDialog("必要なデータがありません", "データを作成します。\nデータ作成に時間がかかりますがよろしいですか?", "はい", "いいえ"))
|
||
{
|
||
Creator.Build(find);
|
||
}
|
||
}
|
||
}
|
||
|
||
private static void Find(Data data, params Object[] selectedObjects)
|
||
{
|
||
var items = new List<Item>();
|
||
var guids = new List<string>();
|
||
foreach (var selectedObject in selectedObjects)
|
||
{
|
||
var guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(selectedObject));
|
||
if (AssetDatabase.IsSubAsset(selectedObject))
|
||
{
|
||
var item = new Item
|
||
{
|
||
searchedGUIContent = GetGUIContent(selectedObject),
|
||
type = selectedObject.GetType()
|
||
};
|
||
|
||
foreach (var assetData in data.assetData)
|
||
{
|
||
foreach (var subAssetData in assetData.subAssets)
|
||
{
|
||
var type = Assembly.Load("UnityEngine.dll").GetType(subAssetData.typeName);
|
||
|
||
if (subAssetData.guid == guid && type == selectedObject.GetType())
|
||
{
|
||
item.referencedGUIContents.Add(GetGUIContent(assetData.guid));
|
||
}
|
||
}
|
||
}
|
||
item.referencedGUIContents = item.referencedGUIContents.Distinct(
|
||
new CompareSelector<GUIContent, string>(i => i.tooltip))
|
||
.ToList();
|
||
|
||
items.Add(item);
|
||
}
|
||
else
|
||
{
|
||
guids.Add(guid);
|
||
|
||
foreach (var assetData in data.assetData.Where(assetData => guid == assetData.guid))
|
||
{
|
||
foreach (var subAssetData in assetData.subAssets)
|
||
{
|
||
var type = Assembly.Load("UnityEngine.dll").GetType(subAssetData.typeName);
|
||
var tex = AssetPreview.GetMiniTypeThumbnail(type);
|
||
|
||
var item =
|
||
items.FirstOrDefault(
|
||
_item => _item.searchedGUIContent.tooltip == GetGUIContent(selectedObject).tooltip);
|
||
if (item == null)
|
||
{
|
||
item = new Item {searchedGUIContent = GetGUIContent(selectedObject)};
|
||
items.Add(item);
|
||
}
|
||
item.type = type;
|
||
item.referenceGUIContents.Add(new GUIContent(subAssetData.name, tex,
|
||
AssetDatabase.GUIDToAssetPath(subAssetData.guid)));
|
||
item.referenceGUIContents = item.referenceGUIContents.Distinct(
|
||
new CompareSelector<GUIContent, string>(i => i.text))
|
||
.ToList();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
items.AddRange(guids
|
||
.Select(guid => new
|
||
{
|
||
type = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), typeof(Object)).GetType(),
|
||
searched = GetGUIContent(guid),
|
||
referenced =
|
||
data.assetData.Where(assetData => assetData.reference.Contains(guid))
|
||
.Select(assetData => GetGUIContent(assetData.guid))
|
||
.Where(c => c != null)
|
||
.Where(c => c.image && guid != AssetDatabase.AssetPathToGUID(c.tooltip))
|
||
.OrderBy(c => c.image.name)
|
||
.ToList(),
|
||
reference =
|
||
data.assetData.Find(item => item.guid == guid)
|
||
.reference.Where(g => g != guid)
|
||
.Select(g => GetGUIContent(g))
|
||
.Where(c => c != null)
|
||
.Where(c => c.image)
|
||
.OrderBy(c => c.image.name)
|
||
.ToList()
|
||
})
|
||
.Where(item => (item.referenced.Count != 0 || item.reference.Count != 0) && item.searched.image)
|
||
.OrderBy(item => item.searched.image.name)
|
||
.Select(item => new Item
|
||
{
|
||
type = item.type,
|
||
searchedGUIContent = item.searched,
|
||
referencedGUIContents = item.referenced,
|
||
referenceGUIContents = item.reference
|
||
})
|
||
.ToList());
|
||
items.Distinct(new CompareSelector<Item, string>(i => i.searchedGUIContent.tooltip));
|
||
|
||
foreach (var item in items)
|
||
{
|
||
foreach (var i in item.referencedGUIContents)
|
||
{
|
||
if (Path.GetExtension(i.tooltip) == ".unity")
|
||
{
|
||
var d = data.assetData.Find(asset => asset.assetPath == i.tooltip).sceneData;
|
||
var key = item.searchedGUIContent.tooltip + " - " + i.tooltip;
|
||
if (sceneReference.ContainsKey(key))
|
||
{
|
||
sceneReference[key]
|
||
.AddRange(d.Select(s => new GUIContent(s.name, AssetDatabase.GUIDToAssetPath(s.guid)))
|
||
.ToList());
|
||
}
|
||
else
|
||
{
|
||
sceneReference.Add(key,
|
||
d.Select(s => new GUIContent(s.name, AssetDatabase.GUIDToAssetPath(s.guid))).ToList());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
var window = GetWindow<ReferenceViewer>();
|
||
window.selectedFilter = 0;
|
||
window.Results(items);
|
||
}
|
||
|
||
|
||
private void Results(List<Item> items)
|
||
{
|
||
this.items = items;
|
||
}
|
||
|
||
private void OnGUI()
|
||
{
|
||
EditorGUILayout.BeginHorizontal();
|
||
|
||
if (GUILayout.Button("Update", EditorStyles.toolbarButton))
|
||
{
|
||
Creator.Build();
|
||
EditorGUIUtility.ExitGUI();
|
||
}
|
||
|
||
EditorGUI.BeginChangeCheck();
|
||
var types = items.Select(item => item.type).ToArray();
|
||
|
||
var display = types.Select(t => t.Name).ToArray();
|
||
for (var i = 0; i < display.Length; i++)
|
||
{
|
||
switch (display[i])
|
||
{
|
||
case "Object":
|
||
display[i] = "Scene";
|
||
break;
|
||
case "GameObject":
|
||
display[i] = "Prefab";
|
||
break;
|
||
}
|
||
}
|
||
ArrayUtility.Insert(ref display, 0, "All");
|
||
var selected = EditorGUILayout.Popup(selectedFilter, display, EditorStyles.toolbarPopup);
|
||
if (EditorGUI.EndChangeCheck())
|
||
{
|
||
selectedFilter = selected;
|
||
}
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
if (items.Count == 0) return;
|
||
|
||
pos = EditorGUILayout.BeginScrollView(pos);
|
||
|
||
var groupBy = items.GroupBy(item => item.searchedGUIContent.tooltip);
|
||
foreach (var group in groupBy)
|
||
{
|
||
var enumerator = @group.GetEnumerator();
|
||
var item = new Item();
|
||
while (enumerator.MoveNext())
|
||
{
|
||
item.type = enumerator.Current.type;
|
||
item.searchedGUIContent = enumerator.Current.searchedGUIContent;
|
||
item.referenceGUIContents.AddRange(enumerator.Current.referenceGUIContents);
|
||
item.referencedGUIContents.AddRange(enumerator.Current.referencedGUIContents);
|
||
}
|
||
|
||
if (selectedFilter != 0 && item.type != types[selectedFilter - 1])
|
||
{
|
||
continue;
|
||
}
|
||
|
||
EditorGUILayout.BeginHorizontal("box", GUILayout.Width(position.width * 0.96f));
|
||
DrawGUIContents(item.searchedGUIContent, item.referenceGUIContents);
|
||
var iconSize = EditorGUIUtility.GetIconSize();
|
||
EditorGUIUtility.SetIconSize(Vector2.one * 32);
|
||
GUILayout.Label(item.searchedGUIContent, GUILayout.Width(position.width * 0.3f),
|
||
GUILayout.ExpandWidth(false));
|
||
EditorGUIUtility.SetIconSize(iconSize);
|
||
PingObjectIfOnMouseDown(item.searchedGUIContent.tooltip);
|
||
|
||
DrawGUIContents(item.searchedGUIContent, item.referencedGUIContents);
|
||
EditorGUILayout.EndHorizontal();
|
||
EditorGUILayout.Space();
|
||
}
|
||
EditorGUILayout.EndScrollView();
|
||
}
|
||
|
||
private void DrawGUIContents(GUIContent searched, List<GUIContent> contents)
|
||
{
|
||
if (contents.Count != 0)
|
||
{
|
||
EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.3f));
|
||
|
||
foreach (var content in contents)
|
||
{
|
||
if (IsScene(content))
|
||
{
|
||
var key = searched.tooltip + " - " + content.tooltip;
|
||
|
||
if (!foldouts.ContainsKey(key))
|
||
{
|
||
foldouts.Add(key, false);
|
||
}
|
||
|
||
foldouts[key] = EditorGUILayout.Foldout(foldouts[key], content);
|
||
|
||
if (foldouts[key])
|
||
{
|
||
if (sceneReference.ContainsKey(key))
|
||
{
|
||
EditorGUI.indentLevel++;
|
||
foreach (var sceneData in sceneReference[key])
|
||
{
|
||
if (searched.tooltip == sceneData.tooltip)
|
||
EditorGUILayout.LabelField(sceneData, EditorStyles.miniLabel,
|
||
GUILayout.Width(position.width * 0.3f), GUILayout.ExpandWidth(true));
|
||
}
|
||
EditorGUI.indentLevel--;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
EditorGUILayout.LabelField(content, GUILayout.Width(position.width * 0.3f),
|
||
GUILayout.ExpandWidth(true));
|
||
}
|
||
|
||
PingObjectIfOnMouseDown(content.tooltip);
|
||
}
|
||
EditorGUILayout.EndVertical();
|
||
}
|
||
else
|
||
{
|
||
GUILayout.Space(position.width * 0.3f + 16);
|
||
}
|
||
}
|
||
|
||
|
||
private static bool IsScene(GUIContent content)
|
||
{
|
||
return Path.GetExtension(content.tooltip) == ".unity";
|
||
}
|
||
|
||
private static void PingObjectIfOnMouseDown(string path)
|
||
{
|
||
if (Event.current.type != EventType.MouseDown) return;
|
||
if (!GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition)) return;
|
||
|
||
var obj = AssetDatabase.LoadAssetAtPath(path, typeof(Object));
|
||
Selection.activeObject = obj;
|
||
EditorGUIUtility.PingObject(obj);
|
||
}
|
||
|
||
private static GUIContent GetGUIContent(string guidOrAssetPath)
|
||
{
|
||
var assetPath = File.Exists(guidOrAssetPath)
|
||
? guidOrAssetPath
|
||
: AssetDatabase.GUIDToAssetPath(guidOrAssetPath);
|
||
|
||
var asset = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Object));
|
||
return asset ? GetGUIContent(asset) : null;
|
||
}
|
||
|
||
private static GUIContent GetGUIContent(Object obj)
|
||
{
|
||
if (!obj) return new GUIContent();
|
||
return new GUIContent(EditorGUIUtility.ObjectContent(obj, obj.GetType()))
|
||
{
|
||
tooltip = AssetDatabase.GetAssetPath(obj)
|
||
};
|
||
}
|
||
|
||
private static T ByteArrayToObject<T>(byte[] arrBytes)
|
||
{
|
||
T obj;
|
||
using (var memStream = new MemoryStream())
|
||
{
|
||
var binForm = new BinaryFormatter();
|
||
memStream.Write(arrBytes, 0, arrBytes.Length);
|
||
memStream.Seek(0, SeekOrigin.Begin);
|
||
obj = (T) binForm.Deserialize(memStream);
|
||
}
|
||
|
||
return obj;
|
||
}
|
||
|
||
private class Item
|
||
{
|
||
public Type type;
|
||
public GUIContent searchedGUIContent;
|
||
public List<GUIContent> referencedGUIContents = new List<GUIContent>();
|
||
public List<GUIContent> referenceGUIContents = new List<GUIContent>();
|
||
}
|
||
}
|
||
} |