309 lines
11 KiB
C#
309 lines
11 KiB
C#
using CaoCao.XAsset;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using UnityEditor;
|
|
using UnityEditor.IMGUI.Controls;
|
|
using UnityEngine;
|
|
|
|
namespace CaoCao.Editor
|
|
{
|
|
public class ManifestsWindow : EditorWindow
|
|
{
|
|
private const int k_SearchHeight = 20;
|
|
[SerializeField] private MultiColumnHeaderState multiColumnHeaderState;
|
|
[SerializeField] private TreeViewState treeViewState;
|
|
public bool reloadSelectedNow;
|
|
|
|
[MenuItem("Window/CaoCao/XAsset/Manifests")]
|
|
public static void OpenManifests()
|
|
{
|
|
EditorWindow.GetWindow<ManifestsWindow>(false, "Manifests");
|
|
}
|
|
|
|
public ulong sizeInBytes;
|
|
private readonly GUIContent typeModule = new GUIContent("模块");
|
|
|
|
private readonly List<string> types = new List<string>();
|
|
private readonly Dictionary<string, List<string>> typeWithAssets = new Dictionary<string, List<string>>();
|
|
|
|
private readonly GUIContent versionName = new GUIContent("模块");
|
|
|
|
private Manifest _manifest;
|
|
|
|
private Versions _versions;
|
|
|
|
private bool reloadAssets;
|
|
private bool reloadNow = true;
|
|
|
|
private SearchField searchField;
|
|
|
|
private int selected;
|
|
|
|
private AssetTreeView treeView;
|
|
private int selectedType { get; set; }
|
|
|
|
private void OnEnable()
|
|
{
|
|
reloadNow = true;
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
if (reloadNow)
|
|
{
|
|
Reload();
|
|
reloadNow = false;
|
|
reloadSelectedNow = true;
|
|
}
|
|
|
|
if (_versions.data.Count == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("请先打包", MessageType.Info);
|
|
return;
|
|
}
|
|
|
|
if (reloadSelectedNow)
|
|
{
|
|
selectedType = 0;
|
|
sizeInBytes = 0;
|
|
var version = _versions.data[selected];
|
|
typeWithAssets.Clear();
|
|
types.Clear();
|
|
var all = new List<string>();
|
|
typeWithAssets.Add("All", all);
|
|
types.Add("All");
|
|
_manifest = CaoCao.XAsset.Utility.LoadFromFile<Manifest>(Settings.GetDataPath(version.file));
|
|
foreach (var bundle in _manifest.bundles) sizeInBytes += bundle.size;
|
|
foreach (var asset in _manifest.assets)
|
|
{
|
|
if (!File.Exists(asset.path))
|
|
{
|
|
CaoCao.XAsset.Logger.W($"File not found: {asset}");
|
|
continue;
|
|
}
|
|
|
|
var type = AssetDatabase.GetMainAssetTypeAtPath(asset.path);
|
|
if (!typeWithAssets.TryGetValue(type.Name, out var assets))
|
|
{
|
|
assets = new List<string>();
|
|
typeWithAssets.Add(type.Name, assets);
|
|
types.Add(type.Name);
|
|
}
|
|
|
|
assets.Add(asset.path);
|
|
all.Add(asset.path);
|
|
}
|
|
|
|
reloadSelectedNow = false;
|
|
reloadAssets = true;
|
|
}
|
|
|
|
if (reloadAssets)
|
|
{
|
|
var set = new HashSet<ManifestBundle>();
|
|
foreach (var asset in GetSelectedAssets())
|
|
{
|
|
var bundle = _manifest.GetBundle(asset);
|
|
set.Add(bundle);
|
|
}
|
|
|
|
selectedTypeSize = 0;
|
|
foreach (var bundle in set)
|
|
{
|
|
selectedTypeSize += bundle.size;
|
|
}
|
|
|
|
if (treeView != null)
|
|
{
|
|
treeView.SetAssets(this);
|
|
reloadAssets = false;
|
|
}
|
|
}
|
|
|
|
|
|
if (_versions == null || _versions.data.Count == 0)
|
|
{
|
|
GUILayout.Label("没有加载到当前平台的打包数据,请在打包后再打开此界面");
|
|
return;
|
|
}
|
|
|
|
if (treeView == null)
|
|
{
|
|
if (treeViewState == null) treeViewState = new TreeViewState();
|
|
|
|
var headerState =
|
|
AssetTreeView.CreateDefaultMultiColumnHeaderState(); // multiColumnTreeViewRect.width);
|
|
if (MultiColumnHeaderState.CanOverwriteSerializedFields(multiColumnHeaderState, headerState))
|
|
MultiColumnHeaderState.OverwriteSerializedFields(multiColumnHeaderState, headerState);
|
|
|
|
multiColumnHeaderState = headerState;
|
|
treeView = new AssetTreeView(treeViewState, multiColumnHeaderState);
|
|
treeView.Reload();
|
|
}
|
|
|
|
|
|
if (searchField == null)
|
|
{
|
|
searchField = new SearchField();
|
|
searchField.downOrUpArrowKeyPressed += treeView.SetFocusAndEnsureSelectedItem;
|
|
}
|
|
|
|
var rect = new Rect(0, 0, position.width, position.height);
|
|
DrawTree(rect);
|
|
DrawToolbar(new Rect(rect.xMin, rect.yMin, rect.width, k_SearchHeight));
|
|
}
|
|
|
|
|
|
private void Reload()
|
|
{
|
|
_versions = Settings.GetDefaultVersions();
|
|
}
|
|
|
|
|
|
private void DrawManifest()
|
|
{
|
|
versionName.text = $"{_versions.data[selected].name}({CaoCao.XAsset.Utility.FormatBytes(sizeInBytes)})";
|
|
var rect = GUILayoutUtility.GetRect(versionName, EditorStyles.toolbarDropDown);
|
|
if (EditorGUI.DropdownButton(rect, versionName, FocusType.Keyboard,
|
|
EditorStyles.toolbarDropDown))
|
|
{
|
|
var menu = new GenericMenu();
|
|
for (var index = 0; index < _versions.data.Count; index++)
|
|
{
|
|
var version = _versions.data[index];
|
|
menu.AddItem(new GUIContent(version.name), selected == index,
|
|
data =>
|
|
{
|
|
selected = (int) data;
|
|
reloadSelectedNow = true;
|
|
}, index);
|
|
}
|
|
|
|
menu.DropDown(rect);
|
|
}
|
|
}
|
|
|
|
private ulong selectedTypeSize;
|
|
|
|
private void DrawTypes()
|
|
{
|
|
typeModule.text = $"{types[selectedType]}({CaoCao.XAsset.Utility.FormatBytes(selectedTypeSize)})";
|
|
var rect = GUILayoutUtility.GetRect(typeModule, EditorStyles.toolbarDropDown);
|
|
if (!EditorGUI.DropdownButton(rect, typeModule, FocusType.Keyboard,
|
|
EditorStyles.toolbarDropDown))
|
|
return;
|
|
|
|
var menu = new GenericMenu();
|
|
for (var index = 0; index < types.Count; index++)
|
|
{
|
|
var type = types[index];
|
|
menu.AddItem(new GUIContent(type), selectedType == index,
|
|
data =>
|
|
{
|
|
selectedType = (int) data;
|
|
reloadAssets = true;
|
|
}, index);
|
|
}
|
|
|
|
menu.DropDown(rect);
|
|
}
|
|
|
|
public List<string> GetSelectedAssets()
|
|
{
|
|
return selectedType < types.Count ? typeWithAssets[types[selectedType]] : new List<string>();
|
|
}
|
|
|
|
private void DrawToolbar(Rect toolbarPos)
|
|
{
|
|
GUILayout.BeginArea(new Rect(0, 0, toolbarPos.width, k_SearchHeight * 2));
|
|
GUILayout.BeginHorizontal(EditorStyles.toolbar);
|
|
{
|
|
treeView.searchString = searchField.OnToolbarGUI(treeView.searchString);
|
|
DrawManifest();
|
|
DrawTypes();
|
|
GUILayout.FlexibleSpace();
|
|
if (GUILayout.Button("Save", EditorStyles.toolbarButton)) SaveSelected();
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
GUILayout.EndArea();
|
|
}
|
|
|
|
private void SaveSelected()
|
|
{
|
|
var path = EditorUtility.SaveFilePanel("Save File", "",
|
|
$"DependenciesWith{_manifest.name}For{types[selectedType]}Assets",
|
|
"txt");
|
|
if (string.IsNullOrEmpty(path)) return;
|
|
|
|
ShowNotification(new GUIContent("Save Success!"));
|
|
var assets = GetSelectedAssets();
|
|
assets.Sort((a, b) => GetBundlesSize(b, out _).CompareTo(GetBundlesSize(a, out _)));
|
|
var sb = new StringBuilder();
|
|
foreach (var asset in assets)
|
|
{
|
|
var size = GetBundlesSize(asset, out var bundles);
|
|
sb.AppendLine($"{asset}({CaoCao.XAsset.Utility.FormatBytes(size)})");
|
|
sb.AppendLine(" - Bundles:" + CaoCao.XAsset.Utility.FormatBytes(size));
|
|
bundles.Sort((a, b) => b.size.CompareTo(a.size));
|
|
foreach (var bundle in bundles)
|
|
sb.AppendLine(
|
|
$" - {bundle.file}({CaoCao.XAsset.Utility.FormatBytes(bundle.size)})");
|
|
|
|
sb.AppendLine(" - Dependencies:");
|
|
var dependencies = new List<string>();
|
|
foreach (var dependency in AssetDatabase.GetDependencies(asset))
|
|
{
|
|
if (asset == dependency || !_manifest.TryGetAsset(dependency, out _)) continue;
|
|
|
|
dependencies.Add(dependency);
|
|
}
|
|
|
|
dependencies.Sort((a, b) => GetBundlesSize(b, out _).CompareTo(GetBundlesSize(a, out _)));
|
|
foreach (var dependency in dependencies)
|
|
sb.AppendLine(
|
|
$" - {dependency}({CaoCao.XAsset.Utility.FormatBytes(GetBundlesSize(dependency, out _))})");
|
|
}
|
|
|
|
File.WriteAllText(path, sb.ToString());
|
|
EditorUtility.OpenWithDefaultApp(path);
|
|
}
|
|
|
|
|
|
public ulong GetBundlesSize(string asset, out List<ManifestBundle> bundles)
|
|
{
|
|
var manifest = _manifest;
|
|
bundles = new List<ManifestBundle>();
|
|
var bundlesSize = 0UL;
|
|
var bundle = manifest.GetBundle(asset);
|
|
bundlesSize += bundle.size;
|
|
bundles.Add(bundle);
|
|
var dependencies = manifest.GetDependencies(bundle);
|
|
if (dependencies == null) return bundlesSize;
|
|
|
|
foreach (var dependency in dependencies)
|
|
{
|
|
bundlesSize += dependency.size;
|
|
bundles.Add(dependency);
|
|
}
|
|
|
|
return bundlesSize;
|
|
}
|
|
|
|
private void DrawTree(Rect rect)
|
|
{
|
|
const int toolbarHeight = k_SearchHeight + 4;
|
|
var treeRect = new Rect(
|
|
rect.xMin,
|
|
rect.yMin + toolbarHeight,
|
|
rect.width,
|
|
rect.height - toolbarHeight);
|
|
treeView.OnGUI(treeRect);
|
|
}
|
|
|
|
public Manifest GetManifest()
|
|
{
|
|
return _manifest;
|
|
}
|
|
}
|
|
} |