update asset bundle reporter

pull/455/head
何冠峰 2025-01-20 17:14:47 +08:00
parent 7c435f6dc0
commit 9add447566
5 changed files with 553 additions and 591 deletions

View File

@ -112,16 +112,16 @@ namespace YooAsset.Editor
string jsonData = FileUtility.ReadAllText(_reportFilePath);
_buildReport = BuildReport.Deserialize(jsonData);
_summaryViewer.FillViewData(_buildReport);
_assetListViewer.FillViewData(_buildReport, _searchKeyWord);
_bundleListViewer.FillViewData(_buildReport, _reportFilePath, _searchKeyWord);
_assetListViewer.FillViewData(_buildReport, _reportFilePath);
_bundleListViewer.FillViewData(_buildReport, _reportFilePath);
}
private void OnSearchKeyWordChange(ChangeEvent<string> e)
{
_searchKeyWord = e.newValue;
if (_buildReport != null)
{
_assetListViewer.FillViewData(_buildReport, _searchKeyWord);
_bundleListViewer.FillViewData(_buildReport, _reportFilePath, _searchKeyWord);
_assetListViewer.RebuildView(_searchKeyWord);
_bundleListViewer.RebuildView(_searchKeyWord);
}
}
private void ViewModeMenuAction0(DropdownMenuAction action)

View File

@ -6,30 +6,30 @@ using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
using System.IO;
namespace YooAsset.Editor
{
internal class ReporterAssetListViewer
{
private enum ESortMode
private class AssetTableData : DefaultTableData
{
AssetPath,
BundleName
public ReportAssetInfo AssetInfo;
}
private class DependTableData : DefaultTableData
{
public ReportBundleInfo BundleInfo;
}
private VisualTreeAsset _visualAsset;
private TemplateContainer _root;
private ToolbarButton _topBar1;
private ToolbarButton _topBar2;
private ToolbarButton _bottomBar1;
private ListView _assetListView;
private ListView _dependListView;
private TableView _assetTableView;
private TableView _dependTableView;
private BuildReport _buildReport;
private string _searchKeyWord;
private ESortMode _sortMode = ESortMode.AssetPath;
private bool _descendingSort = false;
private string _reportFilePath;
private List<ITableData> _sourceDatas;
/// <summary>
@ -45,113 +45,200 @@ namespace YooAsset.Editor
_root = _visualAsset.CloneTree();
_root.style.flexGrow = 1f;
// 顶部按钮栏
_topBar1 = _root.Q<ToolbarButton>("TopBar1");
_topBar2 = _root.Q<ToolbarButton>("TopBar2");
_topBar1.clicked += TopBar1_clicked;
_topBar2.clicked += TopBar2_clicked;
// 底部按钮栏
_bottomBar1 = _root.Q<ToolbarButton>("BottomBar1");
// 资源列表
_assetListView = _root.Q<ListView>("TopListView");
_assetListView.makeItem = MakeAssetListViewItem;
_assetListView.bindItem = BindAssetListViewItem;
#if UNITY_2022_3_OR_NEWER
_assetListView.selectionChanged += AssetListView_onSelectionChange;
#elif UNITY_2020_1_OR_NEWER
_assetListView.onSelectionChange += AssetListView_onSelectionChange;
#else
_assetListView.onSelectionChanged += AssetListView_onSelectionChange;
#endif
_assetTableView = _root.Q<TableView>("TopTableView");
_assetTableView.SelectionChangedEvent = OnAssetTableViewSelectionChanged;
_assetTableView.ClickTableDataEvent = OnClickAssetTableView;
CreateAssetTableViewColumns();
// 依赖列表
_dependListView = _root.Q<ListView>("BottomListView");
_dependListView.makeItem = MakeDependListViewItem;
_dependListView.bindItem = BindDependListViewItem;
_dependTableView = _root.Q<TableView>("BottomTableView");
_dependTableView.ClickTableDataEvent = OnClickBundleTableView;
CreateDependTableViewColumns();
#if UNITY_2020_3_OR_NEWER
SplitView.Adjuster(_root);
#endif
}
private void CreateAssetTableViewColumns()
{
// AssetPath
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 300;
columnStyle.Stretchable = true;
columnStyle.Searchable = true;
columnStyle.Sortable = true;
var column = new TableColumn("AssetPath", "AssetPath", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_assetTableView.AddColumn(column);
}
//MainBundle
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 150;
columnStyle.Stretchable = true;
columnStyle.Searchable = true;
columnStyle.Sortable = true;
var column = new TableColumn("MainBundle", "MainBundle", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_assetTableView.AddColumn(column);
}
}
private void CreateDependTableViewColumns()
{
// DependBundles
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 280;
columnStyle.Stretchable = true;
columnStyle.Searchable = true;
columnStyle.Sortable = true;
var column = new TableColumn("DependBundles", "DependBundles", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_dependTableView.AddColumn(column);
}
// FileSize
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 100;
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = true;
var column = new TableColumn("FileSize", "FileSize", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
long fileSize = (long)cell.CellValue;
infoLabel.text = EditorUtility.FormatBytes(fileSize);
};
_dependTableView.AddColumn(column);
}
// FileHash
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 250;
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = false;
var column = new TableColumn("FileHash", "FileHash", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_dependTableView.AddColumn(column);
}
}
/// <summary>
/// 填充页面数据
/// </summary>
public void FillViewData(BuildReport buildReport, string searchKeyWord)
public void FillViewData(BuildReport buildReport, string reprotFilePath)
{
_buildReport = buildReport;
_searchKeyWord = searchKeyWord;
RefreshView();
}
private void RefreshView()
{
_assetListView.Clear();
_assetListView.ClearSelection();
_assetListView.itemsSource = FilterAndSortViewItems();
_assetListView.Rebuild();
RefreshSortingSymbol();
}
private List<ReportAssetInfo> FilterAndSortViewItems()
{
List<ReportAssetInfo> result = new List<ReportAssetInfo>(_buildReport.AssetInfos.Count);
_reportFilePath = reprotFilePath;
// 过滤列表
// 清空旧数据
_assetTableView.ClearAll(false, true);
_dependTableView.ClearAll(false, true);
// 填充数据源
_sourceDatas = new List<ITableData>(_buildReport.AssetInfos.Count);
foreach (var assetInfo in _buildReport.AssetInfos)
{
if (string.IsNullOrEmpty(_searchKeyWord) == false)
{
if (assetInfo.AssetPath.Contains(_searchKeyWord) == false)
continue;
}
result.Add(assetInfo);
var rowData = new AssetTableData();
rowData.AssetInfo = assetInfo;
rowData.AddAssetPathCell("AssetPath", assetInfo.AssetPath);
rowData.AddStringValueCell("MainBundle", assetInfo.MainBundleName);
_sourceDatas.Add(rowData);
}
_assetTableView.itemsSource = _sourceDatas;
// 排序列表
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();
}
// 重建视图
RebuildView(null);
}
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>
/// 重建视图
/// </summary>
public void RebuildView(string searchKeyWord)
{
// 搜索匹配
DefaultSearchSystem.Search(_sourceDatas, searchKeyWord);
// 重建视图
_assetTableView.RebuildView();
}
/// <summary>
@ -170,157 +257,65 @@ namespace YooAsset.Editor
_root.RemoveFromHierarchy();
}
// 资源列表相关
private VisualElement MakeAssetListViewItem()
private void OnAssetTableViewSelectionChanged(ITableData data)
{
VisualElement element = new VisualElement();
element.style.flexDirection = FlexDirection.Row;
var assetTableData = data as AssetTableData;
ReportAssetInfo assetInfo = assetTableData.AssetInfo;
{
var label = new Label();
label.name = "Label1";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = 1f;
label.style.width = 280;
element.Add(label);
}
{
var label = new Label();
label.name = "Label2";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = 1f;
label.style.width = 150;
element.Add(label);
}
return element;
}
private void BindAssetListViewItem(VisualElement element, int index)
{
var sourceData = _assetListView.itemsSource as List<ReportAssetInfo>;
var assetInfo = sourceData[index];
var bundleInfo = _buildReport.GetBundleInfo(assetInfo.MainBundleName);
// Asset Path
var label1 = element.Q<Label>("Label1");
label1.text = assetInfo.AssetPath;
// Main Bundle
var label2 = element.Q<Label>("Label2");
label2.text = bundleInfo.BundleName;
}
private void AssetListView_onSelectionChange(IEnumerable<object> objs)
{
foreach (var item in objs)
{
ReportAssetInfo assetInfo = item as ReportAssetInfo;
FillDependListView(assetInfo);
}
}
private void TopBar1_clicked()
{
if (_sortMode != ESortMode.AssetPath)
{
_sortMode = ESortMode.AssetPath;
_descendingSort = false;
RefreshView();
}
else
{
_descendingSort = !_descendingSort;
RefreshView();
}
}
private void TopBar2_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.MainBundleName);
bundles.Add(mainBundle);
var sourceDatas = new List<ITableData>(mainBundle.DependBundles.Count);
foreach (string dependBundleName in mainBundle.DependBundles)
{
var dependBundle = _buildReport.GetBundleInfo(dependBundleName);
bundles.Add(dependBundle);
var rowData = new DependTableData();
rowData.BundleInfo = dependBundle;
rowData.AddStringValueCell("DependBundles", dependBundle.BundleName);
rowData.AddLongValueCell("FileSize", dependBundle.FileSize);
rowData.AddStringValueCell("FileHash", dependBundle.FileHash);
sourceDatas.Add(rowData);
}
_dependTableView.itemsSource = sourceDatas;
_dependTableView.RebuildView();
_dependListView.Clear();
_dependListView.ClearSelection();
_dependListView.itemsSource = bundles;
_dependListView.Rebuild();
_bottomBar1.text = $"Depend Bundles ({bundles.Count})";
// 刷新标题
string headerTitle = $"DependBundles ({mainBundle.DependBundles.Count})";
_dependTableView.SetHeaderTitle("DependBundles", headerTitle);
}
private VisualElement MakeDependListViewItem()
private void OnClickAssetTableView(PointerDownEvent evt, ITableData data)
{
VisualElement element = new VisualElement();
element.style.flexDirection = FlexDirection.Row;
// 鼠标双击后检视
if (evt.clickCount != 2)
return;
foreach (var cell in data.Cells)
{
var label = new Label();
label.name = "Label1";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = 1f;
label.style.width = 280;
element.Add(label);
if (cell is AssetPathCell assetPathCell)
{
if (assetPathCell.PingAssetObject())
break;
}
}
{
var label = new Label();
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 = 280;
element.Add(label);
}
return element;
}
private void BindDependListViewItem(VisualElement element, int index)
private void OnClickBundleTableView(PointerDownEvent evt, ITableData data)
{
List<ReportBundleInfo> bundles = _dependListView.itemsSource as List<ReportBundleInfo>;
ReportBundleInfo bundleInfo = bundles[index];
// 鼠标双击后检视
if (evt.clickCount != 2)
return;
// Bundle Name
var label1 = element.Q<Label>("Label1");
label1.text = bundleInfo.BundleName;
var dependTableData = data as DependTableData;
if (dependTableData.BundleInfo.Encrypted)
return;
// Size
var label2 = element.Q<Label>("Label2");
label2.text = EditorUtility.FormatBytes(bundleInfo.FileSize);
// Hash
var label3 = element.Q<Label>("Label3");
label3.text = bundleInfo.FileHash;
if (_buildReport.Summary.BuildBundleType == (int)EBuildBundleType.AssetBundle)
{
string rootDirectory = Path.GetDirectoryName(_reportFilePath);
string filePath = $"{rootDirectory}/{dependTableData.BundleInfo.FileName}";
if (File.Exists(filePath))
Selection.activeObject = AssetBundleRecorder.GetAssetBundle(filePath);
else
Selection.activeObject = null;
}
}
}
}

View File

@ -1,17 +1,8 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<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="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; flex-basis: 60px;" />
<YooAsset.Editor.TableView name="TopTableView" />
</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="Depend Bundles" display-tooltip-when-elided="true" name="BottomBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="File Size" display-tooltip-when-elided="true" name="BottomBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="File Hash" display-tooltip-when-elided="true" name="BottomBar3" 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;" />
<YooAsset.Editor.TableView name="BottomTableView" />
</ui:VisualElement>
</ui:UXML>

View File

@ -12,29 +12,25 @@ namespace YooAsset.Editor
{
internal class ReporterBundleListViewer
{
private enum ESortMode
private class BundleTableData : DefaultTableData
{
BundleName,
BundleSize,
BundleTags
public ReportBundleInfo BundleInfo;
}
private class IncludeTableData : DefaultTableData
{
public ReportAssetInfo AssetInfo;
}
private VisualTreeAsset _visualAsset;
private TemplateContainer _root;
private ToolbarButton _topBar1;
private ToolbarButton _topBar2;
private ToolbarButton _topBar3;
private ToolbarButton _topBar5;
private ToolbarButton _bottomBar1;
private ListView _bundleListView;
private ListView _includeListView;
private TableView _bundleTableView;
private TableView _includeTableView;
private BuildReport _buildReport;
private string _reportFilePath;
private string _searchKeyWord;
private ESortMode _sortMode = ESortMode.BundleName;
private bool _descendingSort = false;
private List<ITableData> _sourceDatas;
/// <summary>
/// 初始化页面
@ -49,134 +45,285 @@ namespace YooAsset.Editor
_root = _visualAsset.CloneTree();
_root.style.flexGrow = 1f;
// 顶部按钮栏
_topBar1 = _root.Q<ToolbarButton>("TopBar1");
_topBar2 = _root.Q<ToolbarButton>("TopBar2");
_topBar3 = _root.Q<ToolbarButton>("TopBar3");
_topBar5 = _root.Q<ToolbarButton>("TopBar5");
_topBar1.clicked += TopBar1_clicked;
_topBar2.clicked += TopBar2_clicked;
_topBar3.clicked += TopBar3_clicked;
_topBar5.clicked += TopBar4_clicked;
// 底部按钮栏
_bottomBar1 = _root.Q<ToolbarButton>("BottomBar1");
// 资源包列表
_bundleListView = _root.Q<ListView>("TopListView");
_bundleListView.makeItem = MakeBundleListViewItem;
_bundleListView.bindItem = BindBundleListViewItem;
#if UNITY_2022_3_OR_NEWER
_bundleListView.selectionChanged += BundleListView_onSelectionChange;
#elif UNITY_2020_1_OR_NEWER
_bundleListView.onSelectionChange += BundleListView_onSelectionChange;
#else
_bundleListView.onSelectionChanged += BundleListView_onSelectionChange;
#endif
_bundleTableView = _root.Q<TableView>("TopTableView");
_bundleTableView.ClickTableDataEvent = OnClickBundleTableView;
_bundleTableView.SelectionChangedEvent = OnBundleTableViewSelectionChanged;
CreateBundleTableViewColumns();
// 包含列表
_includeListView = _root.Q<ListView>("BottomListView");
_includeListView.makeItem = MakeIncludeListViewItem;
_includeListView.bindItem = BindIncludeListViewItem;
_includeTableView = _root.Q<TableView>("BottomTableView");
_includeTableView.ClickTableDataEvent = OnClickIncludeTableView;
CreateIncludeTableViewColumns();
#if UNITY_2020_3_OR_NEWER
SplitView.Adjuster(_root);
#endif
}
private void CreateBundleTableViewColumns()
{
//BundleName
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 300;
columnStyle.Stretchable = true;
columnStyle.Searchable = true;
columnStyle.Sortable = true;
var column = new TableColumn("BundleName", "BundleName", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_bundleTableView.AddColumn(column);
}
// FileSize
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 100;
columnStyle.Stretchable = false;
columnStyle.Searchable = true;
columnStyle.Sortable = true;
var column = new TableColumn("FileSize", "FileSize", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
long fileSize = (long)cell.CellValue;
infoLabel.text = EditorUtility.FormatBytes(fileSize);
};
_bundleTableView.AddColumn(column);
}
// FileHash
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 250;
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = false;
var column = new TableColumn("FileHash", "FileHash", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_bundleTableView.AddColumn(column);
}
//Encrypted
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 100;
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = true;
var column = new TableColumn("Encrypted", "Encrypted", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
bool encrypted = (bool)cell.CellValue;
infoLabel.text = encrypted.ToString();
};
_bundleTableView.AddColumn(column);
}
//Tags
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 150;
columnStyle.Stretchable = true;
columnStyle.Searchable = true;
columnStyle.Sortable = true;
var column = new TableColumn("Tags", "Tags", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_bundleTableView.AddColumn(column);
}
}
private void CreateIncludeTableViewColumns()
{
//IncludeAssets
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 300;
columnStyle.Stretchable = true;
columnStyle.Searchable = true;
columnStyle.Sortable = true;
var column = new TableColumn("IncludeAssets", "IncludeAssets", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_includeTableView.AddColumn(column);
}
//AssetSource
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 100;
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = false;
var column = new TableColumn("AssetSource", "AssetSource", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_includeTableView.AddColumn(column);
}
//AssetGUID
{
var columnStyle = new ColumnStyle();
columnStyle.Width = 250;
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = false;
var column = new TableColumn("AssetGUID", "AssetGUID", columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
label.style.width = columnStyle.Width;
label.style.maxWidth = columnStyle.MaxWidth;
label.style.minWidth = columnStyle.MinWidth;
return label;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
};
_includeTableView.AddColumn(column);
}
}
/// <summary>
/// 填充页面数据
/// </summary>
public void FillViewData(BuildReport buildReport, string reprotFilePath, string searchKeyWord)
public void FillViewData(BuildReport buildReport, string reprotFilePath)
{
_buildReport = buildReport;
_reportFilePath = reprotFilePath;
_searchKeyWord = searchKeyWord;
RefreshView();
}
private void RefreshView()
{
_bundleListView.Clear();
_bundleListView.ClearSelection();
_bundleListView.itemsSource = FilterAndSortViewItems();
_bundleListView.Rebuild();
RefreshSortingSymbol();
}
private List<ReportBundleInfo> FilterAndSortViewItems()
{
List<ReportBundleInfo> result = new List<ReportBundleInfo>(_buildReport.BundleInfos.Count);
// 过滤列表
// 清空旧数据
_bundleTableView.ClearAll(false, true);
_includeTableView.ClearAll(false, true);
// 填充数据源
_sourceDatas = new List<ITableData>(_buildReport.BundleInfos.Count);
foreach (var bundleInfo in _buildReport.BundleInfos)
{
if (string.IsNullOrEmpty(_searchKeyWord) == false)
{
if (bundleInfo.BundleName.Contains(_searchKeyWord) == false)
continue;
}
result.Add(bundleInfo);
var rowData = new BundleTableData();
rowData.BundleInfo = bundleInfo;
rowData.AddStringValueCell("BundleName", bundleInfo.BundleName);
rowData.AddLongValueCell("FileSize", bundleInfo.FileSize);
rowData.AddStringValueCell("FileHash", bundleInfo.FileHash);
rowData.AddBoolValueCell("Encrypted", bundleInfo.Encrypted);
rowData.AddStringValueCell("Tags", string.Join(";", bundleInfo.Tags));
_sourceDatas.Add(rowData);
}
_bundleTableView.itemsSource = _sourceDatas;
// 排序列表
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.FileSize).ToList();
else
return result.OrderBy(a => a.FileSize).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();
}
// 重建视图
RebuildView(null);
}
private void RefreshSortingSymbol()
{
// 刷新符号
_topBar1.text = $"Bundle Name ({_bundleListView.itemsSource.Count})";
_topBar2.text = "Size";
_topBar3.text = "Hash";
_topBar5.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)
_topBar5.text = "Tags ↓";
else
_topBar5.text = "Tags ↑";
}
else
{
throw new System.NotImplementedException();
}
/// <summary>
/// 重建视图
/// </summary>
public void RebuildView(string searchKeyWord)
{
// 搜索匹配
DefaultSearchSystem.Search(_sourceDatas, searchKeyWord);
// 重建视图
_bundleTableView.RebuildView();
}
/// <summary>
@ -195,241 +342,82 @@ namespace YooAsset.Editor
_root.RemoveFromHierarchy();
}
// 顶部列表相关
private VisualElement MakeBundleListViewItem()
private void OnBundleTableViewSelectionChanged(ITableData data)
{
VisualElement element = new VisualElement();
element.style.flexDirection = FlexDirection.Row;
var bundleTableData = data as BundleTableData;
var bundleInfo = bundleTableData.BundleInfo;
{
var label = new Label();
label.name = "Label1";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = 1f;
label.style.width = 280;
element.Add(label);
}
{
var label = new Label();
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 = 280;
element.Add(label);
}
{
var label = new Label();
label.name = "Label5";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 150;
element.Add(label);
}
{
var label = new Label();
label.name = "Label6";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = 1f;
label.style.width = 80;
element.Add(label);
}
return element;
}
private void BindBundleListViewItem(VisualElement element, int index)
{
var sourceData = _bundleListView.itemsSource as List<ReportBundleInfo>;
var bundleInfo = sourceData[index];
// Bundle Name
var label1 = element.Q<Label>("Label1");
label1.text = bundleInfo.BundleName;
// Size
var label2 = element.Q<Label>("Label2");
label2.text = EditorUtility.FormatBytes(bundleInfo.FileSize);
// Hash
var label3 = element.Q<Label>("Label3");
label3.text = bundleInfo.FileHash;
// Encrypted
var label5 = element.Q<Label>("Label5");
label5.text = bundleInfo.Encrypted.ToString();
// Tags
var label6 = element.Q<Label>("Label6");
label6.text = bundleInfo.GetTagsString();
}
private void BundleListView_onSelectionChange(IEnumerable<object> objs)
{
foreach (var item in objs)
{
ReportBundleInfo bundleInfo = item as ReportBundleInfo;
FillIncludeListView(bundleInfo);
ShowAssetBundleInspector(bundleInfo);
break;
}
}
private void ShowAssetBundleInspector(ReportBundleInfo bundleInfo)
{
if (_buildReport.Summary.BuildPipeline == nameof(EBuildPipeline.RawFileBuildPipeline))
return;
string rootDirectory = Path.GetDirectoryName(_reportFilePath);
string filePath = $"{rootDirectory}/{bundleInfo.FileName}";
if (File.Exists(filePath))
Selection.activeObject = AssetBundleRecorder.GetAssetBundle(filePath);
else
Selection.activeObject = null;
}
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<ReportAssetInfo> containsList = new List<ReportAssetInfo>();
HashSet<string> mainAssetDic = new HashSet<string>();
// 填充包含数据
var sourceDatas = new List<ITableData>();
var mainAssetDic = new HashSet<string>();
foreach (var assetInfo in _buildReport.AssetInfos)
{
if (assetInfo.MainBundleName == bundleInfo.BundleName)
{
mainAssetDic.Add(assetInfo.AssetPath);
containsList.Add(assetInfo);
var rowData = new IncludeTableData();
rowData.AssetInfo = assetInfo;
rowData.AddAssetPathCell("IncludeAssets", assetInfo.AssetPath);
rowData.AddStringValueCell("AssetSource", "MainAsset");
rowData.AddStringValueCell("AssetGUID", assetInfo.AssetGUID);
sourceDatas.Add(rowData);
}
}
foreach (string assetPath in bundleInfo.AllBuiltinAssets)
{
if (mainAssetDic.Contains(assetPath) == false)
{
var assetInfo = new ReportAssetInfo();
assetInfo.AssetPath = assetPath;
assetInfo.AssetGUID = "--";
containsList.Add(assetInfo);
var rowData = new IncludeTableData();
rowData.AssetInfo = null;
rowData.AddAssetPathCell("IncludeAssets", assetPath);
rowData.AddStringValueCell("AssetSource", "BuiltinAsset");
rowData.AddStringValueCell("AssetGUID", "--");
sourceDatas.Add(rowData);
}
}
_includeListView.Clear();
_includeListView.ClearSelection();
_includeListView.itemsSource = containsList;
_includeListView.Rebuild();
_bottomBar1.text = $"Include Assets ({containsList.Count})";
_includeTableView.itemsSource = sourceDatas;
_includeTableView.RebuildView();
// 刷新标题
string headerTitle = $"IncludeAssets ({sourceDatas.Count})";
_includeTableView.SetHeaderTitle("IncludeAssets", headerTitle);
}
private VisualElement MakeIncludeListViewItem()
private void OnClickBundleTableView(PointerDownEvent evt, ITableData data)
{
VisualElement element = new VisualElement();
element.style.flexDirection = FlexDirection.Row;
// 鼠标双击后检视
if (evt.clickCount != 2)
return;
var bundleTableData = data as BundleTableData;
if (bundleTableData.BundleInfo.Encrypted)
return;
if (_buildReport.Summary.BuildBundleType == (int)EBuildBundleType.AssetBundle)
{
var label = new Label();
label.name = "Label1";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
label.style.flexGrow = 1f;
label.style.width = 280;
element.Add(label);
string rootDirectory = Path.GetDirectoryName(_reportFilePath);
string filePath = $"{rootDirectory}/{bundleTableData.BundleInfo.FileName}";
if (File.Exists(filePath))
Selection.activeObject = AssetBundleRecorder.GetAssetBundle(filePath);
else
Selection.activeObject = null;
}
{
var label = new Label();
label.name = "Label3";
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 = "Label2";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 280;
element.Add(label);
}
return element;
}
private void BindIncludeListViewItem(VisualElement element, int index)
private void OnClickIncludeTableView(PointerDownEvent evt, ITableData data)
{
List<ReportAssetInfo> containsList = _includeListView.itemsSource as List<ReportAssetInfo>;
ReportAssetInfo assetInfo = containsList[index];
// 鼠标双击后检视
if (evt.clickCount != 2)
return;
// Asset Path
var label1 = element.Q<Label>("Label1");
label1.text = assetInfo.AssetPath;
// Asset Source
var label3 = element.Q<Label>("Label3");
label3.text = assetInfo.AssetGUID != "--" ? "Main Asset" : "Builtin Asset";
// GUID
var label2 = element.Q<Label>("Label2");
label2.text = assetInfo.AssetGUID;
foreach (var cell in data.Cells)
{
if (cell is AssetPathCell assetPathCell)
{
if (assetPathCell.PingAssetObject())
break;
}
}
}
}
}

View File

@ -1,20 +1,8 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<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="Bundle Name" display-tooltip-when-elided="true" name="TopBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="File Size" display-tooltip-when-elided="true" name="TopBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="File Hash" display-tooltip-when-elided="true" name="TopBar3" style="width: 280px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Encrypted" display-tooltip-when-elided="true" name="TopBar4" style="width: 150px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="Tags" display-tooltip-when-elided="true" name="TopBar5" 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; flex-basis: 60px;" />
<YooAsset.Editor.TableView name="TopTableView" />
</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="Asset Source" display-tooltip-when-elided="true" name="BottomBar3" style="width: 100px; -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;" />
<YooAsset.Editor.TableView name="BottomTableView" />
</ui:VisualElement>
</ui:UXML>