The report window supports sorting

报告浏览窗口支持排序
pull/9/head
hevinci 2022-05-03 22:12:59 +08:00
parent 1c1bb078b1
commit f34078a604
7 changed files with 336 additions and 155 deletions

View File

@ -7,15 +7,31 @@ namespace YooAsset.Editor
[Serializable]
public class ReportAssetInfo
{
/// <summary>
/// 可寻址地址
/// </summary>
public string Address;
/// <summary>
/// 资源路径
/// </summary>
public string AssetPath;
/// <summary>
/// 资源GUID
/// 说明Meta文件记录的GUID
/// </summary>
public string AssetGUID;
/// <summary>
/// 所属资源包名称
/// </summary>
public string MainBundle;
public string MainBundleName;
/// <summary>
/// 所属资源包的大小
/// </summary>
public long MainBundleSize;
/// <summary>
/// 依赖的资源包名称列表

View File

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
@ -36,5 +37,13 @@ namespace YooAsset.Editor
/// Flags
/// </summary>
public int Flags;
public string GetTagsString()
{
if (Tags != null)
return String.Join(";", Tags);
else
return string.Empty;
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
namespace YooAsset.Editor
{
@ -62,8 +63,11 @@ namespace YooAsset.Editor
{
var mainBundle = patchManifest.BundleList[patchAsset.BundleID];
ReportAssetInfo reportAssetInfo = new ReportAssetInfo();
reportAssetInfo.Address = patchAsset.Address;
reportAssetInfo.AssetPath = patchAsset.AssetPath;
reportAssetInfo.MainBundle = mainBundle.BundleName;
reportAssetInfo.AssetGUID = AssetDatabase.AssetPathToGUID(patchAsset.AssetPath);
reportAssetInfo.MainBundleName = mainBundle.BundleName;
reportAssetInfo.MainBundleSize = mainBundle.SizeBytes;
reportAssetInfo.DependBundles = GetDependBundles(patchManifest, patchAsset);
reportAssetInfo.DependAssets = GetDependAssets(buildMapContext, mainBundle.BundleName, patchAsset.AssetPath);
buildReport.AssetInfos.Add(reportAssetInfo);

View File

@ -1,5 +1,5 @@
#if UNITY_2019_4_OR_NEWER
using System.IO;
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
@ -11,18 +11,26 @@ namespace YooAsset.Editor
{
internal class AssetListReporterViewer
{
private enum ESortMode
{
AssetPath,
BundleName
}
private VisualTreeAsset _visualAsset;
private TemplateContainer _root;
private ToolbarButton _topBar1;
private ToolbarButton _topBar2;
private ToolbarButton _topBar3;
private ToolbarButton _bottomBar1;
private ToolbarButton _bottomBar2;
private ToolbarButton _bottomBar3;
private ListView _assetListView;
private ListView _dependListView;
private BuildReport _buildReport;
private string _searchKeyWord;
private ESortMode _sortMode = ESortMode.AssetPath;
private bool _descendingSort = false;
/// <summary>
/// 初始化页面
@ -38,37 +46,41 @@ namespace YooAsset.Editor
Debug.LogError($"Not found {nameof(AssetListReporterViewer)}.uxml : {uxml}");
return;
}
try
{
_root = _visualAsset.CloneTree();
_root.style.flexGrow = 1f;
// 顶部按钮栏
_topBar1 = _root.Q<ToolbarButton>("TopBar1");
_topBar2 = _root.Q<ToolbarButton>("TopBar2");
_topBar3 = _root.Q<ToolbarButton>("TopBar3");
_topBar1.clicked += TopBar1_clicked;
_topBar2.clicked += TopBar2_clicked;
_topBar3.clicked += TopBar3_clicked;
// 底部按钮栏
_bottomBar1 = _root.Q<ToolbarButton>("BottomBar1");
_bottomBar2 = _root.Q<ToolbarButton>("BottomBar2");
_bottomBar3 = _root.Q<ToolbarButton>("BottomBar3");
// 资源列表
_assetListView = _root.Q<ListView>("TopListView");
_assetListView.makeItem = MakeAssetListViewItem;
_assetListView.bindItem = BindAssetListViewItem;
#if UNITY_2020_1_OR_NEWER
_assetListView.onSelectionChange += AssetListView_onSelectionChange;
#else
_assetListView.onSelectionChanged += AssetListView_onSelectionChange;
#endif
// 依赖列表
_dependListView = _root.Q<ListView>("BottomListView");
_dependListView.makeItem = MakeDependListViewItem;
_dependListView.bindItem = BindDependListViewItem;
}
catch (Exception e)
{
Debug.LogError(e.ToString());
}
}
/// <summary>
/// 填充页面数据
@ -76,25 +88,76 @@ namespace YooAsset.Editor
public void FillViewData(BuildReport buildReport, string searchKeyWord)
{
_buildReport = buildReport;
_searchKeyWord = searchKeyWord;
RefreshView();
}
private void RefreshView()
{
_assetListView.Clear();
_assetListView.ClearSelection();
_assetListView.itemsSource = FilterViewItems(buildReport, searchKeyWord);
_assetListView.itemsSource = FilterAndSortViewItems();
_assetListView.Rebuild();
_topBar1.text = $"Asset Path ({_assetListView.itemsSource.Count})";
RefreshSortingSymbol();
}
private List<ReportAssetInfo> FilterViewItems(BuildReport buildReport, string searchKeyWord)
private List<ReportAssetInfo> FilterAndSortViewItems()
{
List<ReportAssetInfo> result = new List<ReportAssetInfo>(buildReport.AssetInfos.Count);
foreach (var assetInfo in buildReport.AssetInfos)
List<ReportAssetInfo> result = new List<ReportAssetInfo>(_buildReport.AssetInfos.Count);
// 过滤列表
foreach (var assetInfo in _buildReport.AssetInfos)
{
if(string.IsNullOrEmpty(searchKeyWord) == false)
if (string.IsNullOrEmpty(_searchKeyWord) == false)
{
if (assetInfo.AssetPath.Contains(searchKeyWord) == false)
if (assetInfo.AssetPath.Contains(_searchKeyWord) == false)
continue;
}
result.Add(assetInfo);
}
return result;
// 排序列表
if (_sortMode == ESortMode.AssetPath)
{
if (_descendingSort)
return result.OrderByDescending(a => a.AssetPath).ToList();
else
return result.OrderBy(a => a.AssetPath).ToList();
}
else if (_sortMode == ESortMode.BundleName)
{
if (_descendingSort)
return result.OrderByDescending(a => a.MainBundleName).ToList();
else
return result.OrderBy(a => a.MainBundleName).ToList();
}
else
{
throw new System.NotImplementedException();
}
}
private void RefreshSortingSymbol()
{
// 刷新符号
_topBar1.text = $"Asset Path ({_assetListView.itemsSource.Count})";
_topBar2.text = "Main Bundle";
if (_sortMode == ESortMode.AssetPath)
{
if (_descendingSort)
_topBar1.text = $"Asset Path ({_assetListView.itemsSource.Count}) ↓";
else
_topBar1.text = $"Asset Path ({_assetListView.itemsSource.Count}) ↑";
}
else if (_sortMode == ESortMode.BundleName)
{
if (_descendingSort)
_topBar2.text = "Main Bundle ↓";
else
_topBar2.text = "Main Bundle ↑";
}
else
{
throw new System.NotImplementedException();
}
}
/// <summary>
@ -135,18 +198,8 @@ namespace YooAsset.Editor
label.name = "Label2";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 100;
element.Add(label);
}
{
var label = new Label();
label.name = "Label3";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = 1f;
label.style.width = 145;
label.style.width = 150;
element.Add(label);
}
@ -156,19 +209,15 @@ namespace YooAsset.Editor
{
var sourceData = _assetListView.itemsSource as List<ReportAssetInfo>;
var assetInfo = sourceData[index];
var bundleInfo = _buildReport.GetBundleInfo(assetInfo.MainBundle);
var bundleInfo = _buildReport.GetBundleInfo(assetInfo.MainBundleName);
// Asset Path
var label1 = element.Q<Label>("Label1");
label1.text = assetInfo.AssetPath;
// Size
var label2 = element.Q<Label>("Label2");
label2.text = GetAssetFileSize(assetInfo.AssetPath);
// Main Bundle
var label3 = element.Q<Label>("Label3");
label3.text = bundleInfo.BundleName;
var label2 = element.Q<Label>("Label2");
label2.text = bundleInfo.BundleName;
}
private void AssetListView_onSelectionChange(IEnumerable<object> objs)
{
@ -180,21 +229,40 @@ namespace YooAsset.Editor
}
private void TopBar1_clicked()
{
if (_sortMode != ESortMode.AssetPath)
{
_sortMode = ESortMode.AssetPath;
_descendingSort = false;
RefreshView();
}
else
{
_descendingSort = !_descendingSort;
RefreshView();
}
}
private void TopBar2_clicked()
{
}
private void TopBar3_clicked()
if (_sortMode != ESortMode.BundleName)
{
_sortMode = ESortMode.BundleName;
_descendingSort = false;
RefreshView();
}
else
{
_descendingSort = !_descendingSort;
RefreshView();
}
}
// 依赖列表相关
private void FillDependListView(ReportAssetInfo assetInfo)
{
List<ReportBundleInfo> bundles = new List<ReportBundleInfo>();
var mainBundle = _buildReport.GetBundleInfo(assetInfo.MainBundle);
var mainBundle = _buildReport.GetBundleInfo(assetInfo.MainBundleName);
bundles.Add(mainBundle);
foreach(string dependBundleName in assetInfo.DependBundles)
foreach (string dependBundleName in assetInfo.DependBundles)
{
var dependBundle = _buildReport.GetBundleInfo(dependBundleName);
bundles.Add(dependBundle);
@ -260,15 +328,6 @@ namespace YooAsset.Editor
var label3 = element.Q<Label>("Label3");
label3.text = bundleInfo.Hash;
}
private string GetAssetFileSize(string assetPath)
{
string fullPath = EditorTools.GetProjectPath() + "/" + assetPath;
if (File.Exists(fullPath) == false)
return "unknown";
else
return (EditorTools.GetFileSize(fullPath) / 1024f).ToString("f1") + " KB";
}
}
}
#endif

View File

@ -2,8 +2,7 @@
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
<uie:Toolbar name="TopBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
<uie:ToolbarButton text="Asset Path" display-tooltip-when-elided="true" name="TopBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="TopBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="Main Bundle" display-tooltip-when-elided="true" name="TopBar3" style="width: 145px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Main Bundle" display-tooltip-when-elided="true" name="TopBar2" style="width: 145px; -unity-text-align: middle-left; flex-grow: 1;" />
</uie:Toolbar>
<ui:ListView focusable="true" name="TopListView" item-height="18" virtualization-method="DynamicHeight" style="flex-grow: 1;" />
</ui:VisualElement>

View File

@ -1,4 +1,5 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
@ -11,6 +12,13 @@ namespace YooAsset.Editor
{
internal class BundleListReporterViewer
{
private enum ESortMode
{
BundleName,
BundleSize,
BundleTags
}
private VisualTreeAsset _visualAsset;
private TemplateContainer _root;
@ -18,13 +26,15 @@ namespace YooAsset.Editor
private ToolbarButton _topBar2;
private ToolbarButton _topBar3;
private ToolbarButton _topBar4;
private ToolbarButton _topBar5;
private ToolbarButton _bottomBar1;
private ToolbarButton _bottomBar2;
private ToolbarButton _bottomBar3;
private ListView _bundleListView;
private ListView _includeListView;
private BuildReport _buildReport;
private string _searchKeyWord;
private ESortMode _sortMode = ESortMode.BundleName;
private bool _descendingSort = false;
/// <summary>
/// 初始化页面
@ -40,6 +50,9 @@ namespace YooAsset.Editor
Debug.LogError($"Not found {nameof(BundleListReporterViewer)}.uxml : {uxml}");
return;
}
try
{
_root = _visualAsset.CloneTree();
_root.style.flexGrow = 1f;
@ -48,12 +61,13 @@ namespace YooAsset.Editor
_topBar2 = _root.Q<ToolbarButton>("TopBar2");
_topBar3 = _root.Q<ToolbarButton>("TopBar3");
_topBar4 = _root.Q<ToolbarButton>("TopBar4");
_topBar5 = _root.Q<ToolbarButton>("TopBar5");
_topBar1.clicked += TopBar1_clicked;
_topBar2.clicked += TopBar2_clicked;
_topBar3.clicked += TopBar3_clicked;
_topBar4.clicked += TopBar4_clicked;
// 底部按钮栏
_bottomBar1 = _root.Q<ToolbarButton>("BottomBar1");
_bottomBar2 = _root.Q<ToolbarButton>("BottomBar2");
_bottomBar3 = _root.Q<ToolbarButton>("BottomBar3");
// 资源包列表
_bundleListView = _root.Q<ListView>("TopListView");
@ -70,6 +84,11 @@ namespace YooAsset.Editor
_includeListView.makeItem = MakeIncludeListViewItem;
_includeListView.bindItem = BindIncludeListViewItem;
}
catch (Exception e)
{
Debug.LogError(e.ToString());
}
}
/// <summary>
/// 填充页面数据
@ -77,25 +96,92 @@ namespace YooAsset.Editor
public void FillViewData(BuildReport buildReport, string searchKeyWord)
{
_buildReport = buildReport;
_searchKeyWord = searchKeyWord;
RefreshView();
}
private void RefreshView()
{
_bundleListView.Clear();
_bundleListView.ClearSelection();
_bundleListView.itemsSource = FilterViewItems(buildReport, searchKeyWord);
_bundleListView.itemsSource = FilterAndSortViewItems();
_bundleListView.Rebuild();
_topBar1.text = $"Bundle Name ({_bundleListView.itemsSource.Count})";
RefreshSortingSymbol();
}
private List<ReportBundleInfo> FilterViewItems(BuildReport buildReport, string searchKeyWord)
private List<ReportBundleInfo> FilterAndSortViewItems()
{
List<ReportBundleInfo> result = new List<ReportBundleInfo>(buildReport.BundleInfos.Count);
foreach (var bundleInfo in buildReport.BundleInfos)
List<ReportBundleInfo> result = new List<ReportBundleInfo>(_buildReport.BundleInfos.Count);
// 过滤列表
foreach (var bundleInfo in _buildReport.BundleInfos)
{
if (string.IsNullOrEmpty(searchKeyWord) == false)
if (string.IsNullOrEmpty(_searchKeyWord) == false)
{
if (bundleInfo.BundleName.Contains(searchKeyWord) == false)
if (bundleInfo.BundleName.Contains(_searchKeyWord) == false)
continue;
}
result.Add(bundleInfo);
}
return result;
// 排序列表
if (_sortMode == ESortMode.BundleName)
{
if (_descendingSort)
return result.OrderByDescending(a => a.BundleName).ToList();
else
return result.OrderBy(a => a.BundleName).ToList();
}
else if (_sortMode == ESortMode.BundleSize)
{
if (_descendingSort)
return result.OrderByDescending(a => a.SizeBytes).ToList();
else
return result.OrderBy(a => a.SizeBytes).ToList();
}
else if (_sortMode == ESortMode.BundleTags)
{
if(_descendingSort)
return result.OrderByDescending(a => a.GetTagsString()).ToList();
else
return result.OrderBy(a => a.GetTagsString()).ToList();
}
else
{
throw new System.NotImplementedException();
}
}
private void RefreshSortingSymbol()
{
// 刷新符号
_topBar1.text = $"Bundle Name ({_bundleListView.itemsSource.Count})";
_topBar2.text = "Size";
_topBar3.text = "Hash";
_topBar4.text = "Tags";
if (_sortMode == ESortMode.BundleName)
{
if (_descendingSort)
_topBar1.text = $"Bundle Name ({_bundleListView.itemsSource.Count}) ↓";
else
_topBar1.text = $"Bundle Name ({_bundleListView.itemsSource.Count}) ↑";
}
else if (_sortMode == ESortMode.BundleSize)
{
if (_descendingSort)
_topBar2.text = "Size ↓";
else
_topBar2.text = "Size ↑";
}
else if(_sortMode == ESortMode.BundleTags)
{
if (_descendingSort)
_topBar4.text = "Tags ↓";
else
_topBar4.text = "Tags ↑";
}
else
{
throw new System.NotImplementedException();
}
}
/// <summary>
@ -182,7 +268,7 @@ namespace YooAsset.Editor
// Tags
var label5 = element.Q<Label>("Label5");
label5.text = GetTagsString(bundleInfo.Tags);
label5.text = bundleInfo.GetTagsString();
}
private void BundleListView_onSelectionChange(IEnumerable<object> objs)
{
@ -192,15 +278,60 @@ namespace YooAsset.Editor
FillIncludeListView(bundleInfo);
}
}
private void TopBar1_clicked()
{
if (_sortMode != ESortMode.BundleName)
{
_sortMode = ESortMode.BundleName;
_descendingSort = false;
RefreshView();
}
else
{
_descendingSort = !_descendingSort;
RefreshView();
}
}
private void TopBar2_clicked()
{
if (_sortMode != ESortMode.BundleSize)
{
_sortMode = ESortMode.BundleSize;
_descendingSort = false;
RefreshView();
}
else
{
_descendingSort = !_descendingSort;
RefreshView();
}
}
private void TopBar3_clicked()
{
}
private void TopBar4_clicked()
{
if (_sortMode != ESortMode.BundleTags)
{
_sortMode = ESortMode.BundleTags;
_descendingSort = false;
RefreshView();
}
else
{
_descendingSort = !_descendingSort;
RefreshView();
}
}
// 底部列表相关
private void FillIncludeListView(ReportBundleInfo bundleInfo)
{
List<string> containsList = new List<string>();
List<ReportAssetInfo> containsList = new List<ReportAssetInfo>();
foreach (var assetInfo in _buildReport.AssetInfos)
{
if (assetInfo.MainBundle == bundleInfo.BundleName)
containsList.Add(assetInfo.AssetPath);
if (assetInfo.MainBundleName == bundleInfo.BundleName)
containsList.Add(assetInfo);
}
_includeListView.Clear();
@ -229,16 +360,6 @@ namespace YooAsset.Editor
label.name = "Label2";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//assetSizeLabel.style.flexGrow = 1f;
label.style.width = 100;
element.Add(label);
}
{
var label = new Label();
label.name = "Label3";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 280;
element.Add(label);
@ -248,42 +369,16 @@ namespace YooAsset.Editor
}
private void BindIncludeListViewItem(VisualElement element, int index)
{
List<string> containsList = _includeListView.itemsSource as List<string>;
string assetPath = containsList[index];
List<ReportAssetInfo> containsList = _includeListView.itemsSource as List<ReportAssetInfo>;
ReportAssetInfo assetInfo = containsList[index];
// Asset Path
var label1 = element.Q<Label>("Label1");
label1.text = assetPath;
// Size
var label2 = element.Q<Label>("Label2");
label2.text = GetAssetFileSize(assetPath);
label1.text = assetInfo.AssetPath;
// GUID
var label3 = element.Q<Label>("Label3");
label3.text = AssetDatabase.AssetPathToGUID(assetPath);
}
private string GetAssetFileSize(string assetPath)
{
string fullPath = EditorTools.GetProjectPath() + "/" + assetPath;
if (File.Exists(fullPath) == false)
return "unknown";
else
return (EditorTools.GetFileSize(fullPath) / 1024f).ToString("f1") + " KB";
}
private string GetTagsString(string[] tags)
{
string result = string.Empty;
if (tags != null)
{
for (int i = 0; i < tags.Length; i++)
{
result += tags[i];
result += ";";
}
}
return result;
var label2 = element.Q<Label>("Label2");
label2.text = assetInfo.AssetGUID;
}
}
}

View File

@ -5,15 +5,14 @@
<uie:ToolbarButton text="Bundle Name" display-tooltip-when-elided="true" name="TopBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="TopBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="Hash" display-tooltip-when-elided="true" name="TopBar3" style="width: 280px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Tags" display-tooltip-when-elided="true" name="TopBar5" style="width: 80px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Tags" display-tooltip-when-elided="true" name="TopBar4" style="width: 80px; -unity-text-align: middle-left; flex-grow: 1;" />
</uie:Toolbar>
<ui:ListView focusable="true" name="TopListView" item-height="18" virtualization-method="DynamicHeight" style="flex-grow: 1;" />
</ui:VisualElement>
<ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex;">
<uie:Toolbar name="BottomBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
<uie:ToolbarButton text="Include Assets" display-tooltip-when-elided="true" name="BottomBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="BottomBar2" style="width: 100px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="GUID" display-tooltip-when-elided="true" name="BottomBar3" style="width: 280px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="GUID" display-tooltip-when-elided="true" name="BottomBar2" style="width: 280px; -unity-text-align: middle-left;" />
</uie:Toolbar>
<ui:ListView focusable="true" name="BottomListView" item-height="18" virtualization-method="DynamicHeight" style="flex-grow: 1;" />
</ui:VisualElement>