mirror of https://github.com/tuyoogame/YooAsset
parent
a38b76eb8f
commit
7cc985205a
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bdbb4647038dcc842802f546c2fedc83
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,577 @@
|
||||||
|
#if UNITY_2019_4_OR_NEWER
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor.UIElements;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
using UnityEngine.Tilemaps;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public class AssetArtReporterWindow : EditorWindow
|
||||||
|
{
|
||||||
|
[MenuItem("YooAsset/AssetArt Reporter", false, 302)]
|
||||||
|
public static AssetArtReporterWindow OpenWindow()
|
||||||
|
{
|
||||||
|
AssetArtReporterWindow window = GetWindow<AssetArtReporterWindow>("资源扫描报告", true, WindowsDefine.DockedWindowTypes);
|
||||||
|
window.minSize = new Vector2(800, 600);
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ElementTableData : DefaultTableData
|
||||||
|
{
|
||||||
|
public ReportElement Element;
|
||||||
|
}
|
||||||
|
private class PassesBtnCell : ITableCell, IComparable
|
||||||
|
{
|
||||||
|
public object CellValue { set; get; }
|
||||||
|
public string SearchTag { private set; get; }
|
||||||
|
public ReportElement Element
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (ReportElement)CellValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PassesBtnCell(string searchTag, ReportElement element)
|
||||||
|
{
|
||||||
|
SearchTag = searchTag;
|
||||||
|
CellValue = element;
|
||||||
|
}
|
||||||
|
public object GetDisplayObject()
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
public int CompareTo(object other)
|
||||||
|
{
|
||||||
|
if (other is PassesBtnCell cell)
|
||||||
|
{
|
||||||
|
return this.Element.Passes.CompareTo(cell.Element.Passes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private class WhiteListBtnCell : ITableCell, IComparable
|
||||||
|
{
|
||||||
|
public object CellValue { set; get; }
|
||||||
|
public string SearchTag { private set; get; }
|
||||||
|
public ReportElement Element
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (ReportElement)CellValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public WhiteListBtnCell(string searchTag, ReportElement element)
|
||||||
|
{
|
||||||
|
SearchTag = searchTag;
|
||||||
|
CellValue = element;
|
||||||
|
}
|
||||||
|
public object GetDisplayObject()
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
public int CompareTo(object other)
|
||||||
|
{
|
||||||
|
if (other is PassesBtnCell cell)
|
||||||
|
{
|
||||||
|
return this.Element.IsWhiteList.CompareTo(cell.Element.IsWhiteList);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ToolbarSearchField _searchField;
|
||||||
|
private Button _whiteVisibleBtn;
|
||||||
|
private Button _stateVisibleBtn;
|
||||||
|
private Label _titleLabel;
|
||||||
|
private Label _descLabel;
|
||||||
|
private TableView _elementTableView;
|
||||||
|
|
||||||
|
private ScanReportCombiner _reportCombiner;
|
||||||
|
private string _lastestOpenFolder;
|
||||||
|
private List<ITableData> _sourceDatas;
|
||||||
|
private bool _showWhiteElements = true;
|
||||||
|
private bool _showPassesElements = true;
|
||||||
|
|
||||||
|
|
||||||
|
public void CreateGUI()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
VisualElement root = this.rootVisualElement;
|
||||||
|
|
||||||
|
// 加载布局文件
|
||||||
|
var visualAsset = UxmlLoader.LoadWindowUXML<AssetArtReporterWindow>();
|
||||||
|
if (visualAsset == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
visualAsset.CloneTree(root);
|
||||||
|
|
||||||
|
// 导入按钮
|
||||||
|
var singleImportBtn = root.Q<Button>("SingleImportButton");
|
||||||
|
singleImportBtn.clicked += SingleImportBtn_clicked;
|
||||||
|
var multiImportBtn = root.Q<Button>("MultiImportButton");
|
||||||
|
multiImportBtn.clicked += MultiImportBtn_clicked;
|
||||||
|
|
||||||
|
// 修复按钮
|
||||||
|
var fixAllBtn = root.Q<Button>("FixAllButton");
|
||||||
|
fixAllBtn.clicked += FixAllBtn_clicked;
|
||||||
|
var fixSelectBtn = root.Q<Button>("FixSelectButton");
|
||||||
|
fixSelectBtn.clicked += FixSelectBtn_clicked;
|
||||||
|
|
||||||
|
// 白名单按钮
|
||||||
|
_whiteVisibleBtn = root.Q<Button>("WhiteVisibleButton");
|
||||||
|
_whiteVisibleBtn.clicked += WhiteVisibleBtn_clicked;
|
||||||
|
_stateVisibleBtn = root.Q<Button>("StateVisibleButton");
|
||||||
|
_stateVisibleBtn.clicked += StateVsibleBtn_clicked;
|
||||||
|
|
||||||
|
// 文件导出按钮
|
||||||
|
var exportFilesBtn = root.Q<Button>("ExportFilesButton");
|
||||||
|
exportFilesBtn.clicked += ExportFilesBtn_clicked;
|
||||||
|
|
||||||
|
// 搜索过滤
|
||||||
|
_searchField = root.Q<ToolbarSearchField>("SearchField");
|
||||||
|
_searchField.RegisterValueChangedCallback(OnSearchKeyWordChange);
|
||||||
|
|
||||||
|
// 标题和备注
|
||||||
|
_titleLabel = root.Q<Label>("ReportTitle");
|
||||||
|
_descLabel = root.Q<Label>("ReportDesc");
|
||||||
|
|
||||||
|
// 列表相关
|
||||||
|
_elementTableView = root.Q<TableView>("TopTableView");
|
||||||
|
_elementTableView.ClickTableDataEvent = OnClickListItem;
|
||||||
|
|
||||||
|
_lastestOpenFolder = EditorTools.GetProjectPath();
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void OnDestroy()
|
||||||
|
{
|
||||||
|
if (_reportCombiner != null)
|
||||||
|
_reportCombiner.SaveChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导入单个报告文件
|
||||||
|
/// </summary>
|
||||||
|
public void ImportSingleReprotFile(string filePath)
|
||||||
|
{
|
||||||
|
// 记录本次打开目录
|
||||||
|
_lastestOpenFolder = Path.GetDirectoryName(filePath);
|
||||||
|
_reportCombiner = new ScanReportCombiner();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var scanReport = ScanReportConfig.ImportJsonConfig(filePath);
|
||||||
|
_reportCombiner.Combine(scanReport);
|
||||||
|
|
||||||
|
// 刷新页面
|
||||||
|
RefreshToolbar();
|
||||||
|
FillTableView();
|
||||||
|
RebuildView();
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
_reportCombiner = null;
|
||||||
|
_titleLabel.text = "导入报告失败!";
|
||||||
|
_descLabel.text = e.Message;
|
||||||
|
UnityEngine.Debug.LogError(e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SingleImportBtn_clicked()
|
||||||
|
{
|
||||||
|
string selectFilePath = EditorUtility.OpenFilePanel("导入报告", _lastestOpenFolder, "json");
|
||||||
|
if (string.IsNullOrEmpty(selectFilePath))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImportSingleReprotFile(selectFilePath);
|
||||||
|
}
|
||||||
|
private void MultiImportBtn_clicked()
|
||||||
|
{
|
||||||
|
string selectFolderPath = EditorUtility.OpenFolderPanel("导入报告", _lastestOpenFolder, null);
|
||||||
|
if (string.IsNullOrEmpty(selectFolderPath))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 记录本次打开目录
|
||||||
|
_lastestOpenFolder = selectFolderPath;
|
||||||
|
_reportCombiner = new ScanReportCombiner();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] files = Directory.GetFiles(selectFolderPath);
|
||||||
|
foreach (string filePath in files)
|
||||||
|
{
|
||||||
|
string extension = System.IO.Path.GetExtension(filePath);
|
||||||
|
if (extension == ".json")
|
||||||
|
{
|
||||||
|
var scanReport = ScanReportConfig.ImportJsonConfig(filePath);
|
||||||
|
_reportCombiner.Combine(scanReport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新页面
|
||||||
|
RefreshToolbar();
|
||||||
|
FillTableView();
|
||||||
|
RebuildView();
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
_reportCombiner = null;
|
||||||
|
_titleLabel.text = "导入报告失败!";
|
||||||
|
_descLabel.text = e.Message;
|
||||||
|
UnityEngine.Debug.LogError(e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void FixAllBtn_clicked()
|
||||||
|
{
|
||||||
|
if (EditorUtility.DisplayDialog("提示", "修复全部资源(白名单除外)", "Yes", "No"))
|
||||||
|
{
|
||||||
|
if (_reportCombiner != null)
|
||||||
|
_reportCombiner.FixAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void FixSelectBtn_clicked()
|
||||||
|
{
|
||||||
|
if (EditorUtility.DisplayDialog("提示", "修复所有选中资源(白名单除外)", "Yes", "No"))
|
||||||
|
{
|
||||||
|
if (_reportCombiner != null)
|
||||||
|
_reportCombiner.FixSelect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void WhiteVisibleBtn_clicked()
|
||||||
|
{
|
||||||
|
_showWhiteElements = !_showWhiteElements;
|
||||||
|
RefreshToolbar();
|
||||||
|
RebuildView();
|
||||||
|
}
|
||||||
|
private void StateVsibleBtn_clicked()
|
||||||
|
{
|
||||||
|
_showPassesElements = !_showPassesElements;
|
||||||
|
RefreshToolbar();
|
||||||
|
RebuildView();
|
||||||
|
}
|
||||||
|
private void ExportFilesBtn_clicked()
|
||||||
|
{
|
||||||
|
string selectFolderPath = EditorUtility.OpenFolderPanel("导入所有选中资源", EditorTools.GetProjectPath(), string.Empty);
|
||||||
|
if (string.IsNullOrEmpty(selectFolderPath) == false)
|
||||||
|
{
|
||||||
|
if (_reportCombiner != null)
|
||||||
|
_reportCombiner.ExportFiles(selectFolderPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshToolbar()
|
||||||
|
{
|
||||||
|
if (_reportCombiner == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_titleLabel.text = _reportCombiner.ReportTitle;
|
||||||
|
_descLabel.text = _reportCombiner.ReportDesc;
|
||||||
|
|
||||||
|
if (_showWhiteElements)
|
||||||
|
_whiteVisibleBtn.style.backgroundColor = new StyleColor(new Color32(56, 147, 58, 255));
|
||||||
|
else
|
||||||
|
_whiteVisibleBtn.style.backgroundColor = new StyleColor(new Color32(100, 100, 100, 255));
|
||||||
|
|
||||||
|
if (_showPassesElements)
|
||||||
|
_stateVisibleBtn.style.backgroundColor = new StyleColor(new Color32(56, 147, 58, 255));
|
||||||
|
else
|
||||||
|
_stateVisibleBtn.style.backgroundColor = new StyleColor(new Color32(100, 100, 100, 255));
|
||||||
|
}
|
||||||
|
private void FillTableView()
|
||||||
|
{
|
||||||
|
if (_reportCombiner == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_elementTableView.ClearAll(true, true);
|
||||||
|
|
||||||
|
// 状态标题
|
||||||
|
{
|
||||||
|
var columnStyle = new ColumnStyle();
|
||||||
|
columnStyle.Width = 80;
|
||||||
|
columnStyle.MinWidth = 80;
|
||||||
|
columnStyle.MaxWidth = 80;
|
||||||
|
columnStyle.Stretchable = false;
|
||||||
|
columnStyle.Searchable = false;
|
||||||
|
columnStyle.Sortable = true;
|
||||||
|
var column = new TableColumn("状态", "状态", columnStyle);
|
||||||
|
|
||||||
|
column.MakeCell = () =>
|
||||||
|
{
|
||||||
|
var button = new Button();
|
||||||
|
button.text = "状态";
|
||||||
|
button.style.unityTextAlign = TextAnchor.MiddleCenter;
|
||||||
|
button.style.marginLeft = 3f;
|
||||||
|
button.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
|
||||||
|
button.style.width = columnStyle.Width;
|
||||||
|
button.style.maxWidth = columnStyle.MaxWidth;
|
||||||
|
button.style.minWidth = columnStyle.MinWidth;
|
||||||
|
return button;
|
||||||
|
};
|
||||||
|
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
|
||||||
|
{
|
||||||
|
Button button = element as Button;
|
||||||
|
var elementTableData = data as ElementTableData;
|
||||||
|
if (elementTableData.Element.Passes)
|
||||||
|
{
|
||||||
|
button.style.backgroundColor = new StyleColor(new Color32(56, 147, 58, 255));
|
||||||
|
button.text = "通过";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
button.style.backgroundColor = new StyleColor(new Color32(137, 0, 0, 255));
|
||||||
|
button.text = "失败";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_elementTableView.AddColumn(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 白名单标题
|
||||||
|
{
|
||||||
|
var columnStyle = new ColumnStyle();
|
||||||
|
columnStyle.Width = 80;
|
||||||
|
columnStyle.MinWidth = 80;
|
||||||
|
columnStyle.MaxWidth = 80;
|
||||||
|
columnStyle.Stretchable = false;
|
||||||
|
columnStyle.Searchable = false;
|
||||||
|
columnStyle.Sortable = true;
|
||||||
|
var column = new TableColumn("白名单", "白名单", columnStyle);
|
||||||
|
column.MakeCell = () =>
|
||||||
|
{
|
||||||
|
Button button = new Button();
|
||||||
|
button.text = "白名单";
|
||||||
|
button.style.unityTextAlign = TextAnchor.MiddleCenter;
|
||||||
|
button.style.marginLeft = 3f;
|
||||||
|
button.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
|
||||||
|
button.style.width = columnStyle.Width;
|
||||||
|
button.style.maxWidth = columnStyle.MaxWidth;
|
||||||
|
button.style.minWidth = columnStyle.MinWidth;
|
||||||
|
button.clickable.clickedWithEventInfo += OnClickWhitListButton;
|
||||||
|
return button;
|
||||||
|
};
|
||||||
|
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
|
||||||
|
{
|
||||||
|
Button button = element as Button;
|
||||||
|
button.userData = data;
|
||||||
|
var elementTableData = data as ElementTableData;
|
||||||
|
if (elementTableData.Element.IsWhiteList)
|
||||||
|
button.style.backgroundColor = new StyleColor(new Color32(56, 147, 58, 255));
|
||||||
|
else
|
||||||
|
button.style.backgroundColor = new StyleColor(new Color32(100, 100, 100, 255));
|
||||||
|
};
|
||||||
|
_elementTableView.AddColumn(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选中标题
|
||||||
|
{
|
||||||
|
var columnStyle = new ColumnStyle();
|
||||||
|
columnStyle.Width = 20;
|
||||||
|
columnStyle.MinWidth = 20;
|
||||||
|
columnStyle.MaxWidth = 20;
|
||||||
|
columnStyle.Stretchable = false;
|
||||||
|
columnStyle.Searchable = false;
|
||||||
|
columnStyle.Sortable = false;
|
||||||
|
var column = new TableColumn("选中框", string.Empty, columnStyle);
|
||||||
|
column.MakeCell = () =>
|
||||||
|
{
|
||||||
|
var toggle = new Toggle();
|
||||||
|
toggle.text = string.Empty;
|
||||||
|
toggle.style.unityTextAlign = TextAnchor.MiddleCenter;
|
||||||
|
toggle.style.marginLeft = 3f;
|
||||||
|
toggle.style.flexGrow = columnStyle.Stretchable ? 1f : 0f;
|
||||||
|
toggle.style.width = columnStyle.Width;
|
||||||
|
toggle.style.maxWidth = columnStyle.MaxWidth;
|
||||||
|
toggle.style.minWidth = columnStyle.MinWidth;
|
||||||
|
toggle.RegisterValueChangedCallback((evt) => { OnToggleValueChange(toggle, evt); });
|
||||||
|
return toggle;
|
||||||
|
};
|
||||||
|
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
|
||||||
|
{
|
||||||
|
var toggle = element as Toggle;
|
||||||
|
toggle.userData = data;
|
||||||
|
var tableData = data as ElementTableData;
|
||||||
|
toggle.SetValueWithoutNotify(tableData.Element.IsSelected);
|
||||||
|
};
|
||||||
|
_elementTableView.AddColumn(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义标题栏
|
||||||
|
foreach (var header in _reportCombiner.Headers)
|
||||||
|
{
|
||||||
|
var columnStyle = new ColumnStyle();
|
||||||
|
columnStyle.Width = header.Width;
|
||||||
|
columnStyle.MinWidth = header.MinWidth;
|
||||||
|
columnStyle.MaxWidth = header.MaxWidth;
|
||||||
|
columnStyle.Stretchable = header.Stretchable;
|
||||||
|
columnStyle.Searchable = header.Searchable;
|
||||||
|
columnStyle.Sortable = header.Sortable;
|
||||||
|
var column = new TableColumn(header.HeaderTitle, header.HeaderTitle, 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();
|
||||||
|
};
|
||||||
|
_elementTableView.AddColumn(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 填充数据源
|
||||||
|
_sourceDatas = new List<ITableData>(_reportCombiner.Elements.Count);
|
||||||
|
foreach (var element in _reportCombiner.Elements)
|
||||||
|
{
|
||||||
|
var tableData = new ElementTableData();
|
||||||
|
tableData.Element = element;
|
||||||
|
|
||||||
|
// 固定标题
|
||||||
|
tableData.AddCell(new PassesBtnCell("状态", element));
|
||||||
|
tableData.AddCell(new WhiteListBtnCell("白名单", element));
|
||||||
|
tableData.AddButtonCell("选中框");
|
||||||
|
|
||||||
|
// 自定义标题
|
||||||
|
foreach (var scanInfo in element.ScanInfos)
|
||||||
|
{
|
||||||
|
var header = _reportCombiner.GetHeader(scanInfo.HeaderTitle);
|
||||||
|
if (header.HeaderType == EHeaderType.AssetPath)
|
||||||
|
{
|
||||||
|
tableData.AddAssetPathCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);
|
||||||
|
}
|
||||||
|
else if (header.HeaderType == EHeaderType.StringValue)
|
||||||
|
{
|
||||||
|
tableData.AddStringValueCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);
|
||||||
|
}
|
||||||
|
else if (header.HeaderType == EHeaderType.LongValue)
|
||||||
|
{
|
||||||
|
long value = Convert.ToInt64(scanInfo.ScanInfo);
|
||||||
|
tableData.AddLongValueCell(scanInfo.HeaderTitle, value);
|
||||||
|
}
|
||||||
|
else if (header.HeaderType == EHeaderType.DoubleValue)
|
||||||
|
{
|
||||||
|
double value = Convert.ToDouble(scanInfo.ScanInfo);
|
||||||
|
tableData.AddDoubleValueCell(scanInfo.HeaderTitle, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotImplementedException(header.HeaderType.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_sourceDatas.Add(tableData);
|
||||||
|
}
|
||||||
|
_elementTableView.itemsSource = _sourceDatas;
|
||||||
|
}
|
||||||
|
private void RebuildView()
|
||||||
|
{
|
||||||
|
if (_reportCombiner == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string searchKeyword = _searchField.value;
|
||||||
|
|
||||||
|
// 搜索匹配
|
||||||
|
DefaultSearchSystem.Search(_sourceDatas, searchKeyword);
|
||||||
|
|
||||||
|
// 开关匹配
|
||||||
|
foreach (var tableData in _sourceDatas)
|
||||||
|
{
|
||||||
|
var elementTableData = tableData as ElementTableData;
|
||||||
|
if (_showPassesElements == false && elementTableData.Element.Passes)
|
||||||
|
{
|
||||||
|
tableData.Visible = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_showWhiteElements == false && elementTableData.Element.IsWhiteList)
|
||||||
|
{
|
||||||
|
tableData.Visible = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重建视图
|
||||||
|
_elementTableView.RebuildView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnClickListItem(PointerDownEvent evt, ITableData tableData)
|
||||||
|
{
|
||||||
|
// 双击后检视对应的资源
|
||||||
|
if (evt.clickCount == 2)
|
||||||
|
{
|
||||||
|
foreach (var cell in tableData.Cells)
|
||||||
|
{
|
||||||
|
if (cell is AssetPathCell assetPathCell)
|
||||||
|
{
|
||||||
|
if (assetPathCell.PingAssetObject())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void OnSearchKeyWordChange(ChangeEvent<string> e)
|
||||||
|
{
|
||||||
|
RebuildView();
|
||||||
|
}
|
||||||
|
private void OnToggleValueChange(Toggle toggle, ChangeEvent<bool> e)
|
||||||
|
{
|
||||||
|
// 处理自身
|
||||||
|
toggle.SetValueWithoutNotify(e.newValue);
|
||||||
|
var elementTableData = toggle.userData as ElementTableData;
|
||||||
|
elementTableData.Element.IsSelected = e.newValue;
|
||||||
|
|
||||||
|
// 处理多选目标
|
||||||
|
var selectedItems = _elementTableView.selectedItems;
|
||||||
|
foreach (var selectedItem in selectedItems)
|
||||||
|
{
|
||||||
|
var selectElement = selectedItem as ElementTableData;
|
||||||
|
selectElement.Element.IsSelected = e.newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重绘视图
|
||||||
|
RebuildView();
|
||||||
|
}
|
||||||
|
private void OnClickWhitListButton(EventBase evt)
|
||||||
|
{
|
||||||
|
// 刷新点击的按钮
|
||||||
|
Button button = evt.target as Button;
|
||||||
|
var elementTableData = button.userData as ElementTableData;
|
||||||
|
elementTableData.Element.IsWhiteList = !elementTableData.Element.IsWhiteList;
|
||||||
|
|
||||||
|
// 刷新框选的按钮
|
||||||
|
var selectedItems = _elementTableView.selectedItems;
|
||||||
|
if (selectedItems.Count() > 1)
|
||||||
|
{
|
||||||
|
foreach (var selectedItem in selectedItems)
|
||||||
|
{
|
||||||
|
var selectElement = selectedItem as ElementTableData;
|
||||||
|
selectElement.Element.IsWhiteList = selectElement.Element.IsWhiteList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RebuildView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4048f85b9ff1f424a89a9d6109e6faaf
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,19 @@
|
||||||
|
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
|
||||||
|
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row;">
|
||||||
|
<uie:ToolbarSearchField focusable="true" name="SearchField" style="flex-grow: 1;" />
|
||||||
|
<ui:Button text="显示通过元素" display-tooltip-when-elided="true" name="StateVisibleButton" style="width: 100px; background-color: rgb(56, 147, 58);" />
|
||||||
|
<ui:Button text="显示白名单元素" display-tooltip-when-elided="true" name="WhiteVisibleButton" style="width: 100px; background-color: rgb(56, 147, 58);" />
|
||||||
|
<ui:Button text="导出选中文件" display-tooltip-when-elided="true" name="ExportFilesButton" style="width: 80px; background-color: rgb(56, 147, 58);" />
|
||||||
|
<ui:Button text="修复选中" display-tooltip-when-elided="true" name="FixSelectButton" style="width: 60px; background-color: rgb(56, 147, 58);" />
|
||||||
|
<ui:Button text="修复所有" display-tooltip-when-elided="true" name="FixAllButton" style="width: 60px; background-color: rgb(56, 147, 58);" />
|
||||||
|
<ui:Button text="单个导入" display-tooltip-when-elided="true" name="SingleImportButton" style="width: 60px; background-color: rgb(56, 147, 58);" />
|
||||||
|
<ui:Button text="合并导入" display-tooltip-when-elided="true" name="MultiImportButton" style="width: 60px; background-color: rgb(56, 147, 58);" />
|
||||||
|
</uie:Toolbar>
|
||||||
|
<ui:VisualElement name="PublicContainer" style="background-color: rgb(79, 79, 79); flex-direction: column; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
|
||||||
|
<ui:Label text="标题" display-tooltip-when-elided="true" name="ReportTitle" style="height: 16px; -unity-font-style: bold; -unity-text-align: middle-center;" />
|
||||||
|
<ui:Label text="说明" display-tooltip-when-elided="true" name="ReportDesc" style="-unity-text-align: upper-left; -unity-font-style: bold; background-color: rgb(42, 42, 42); min-height: 50px; border-top-left-radius: 3px; border-bottom-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; white-space: normal;" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="AssetGroup" 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;">
|
||||||
|
<YooAsset.Editor.TableView name="TopTableView" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
</ui:UXML>
|
|
@ -0,0 +1,10 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b87fc70b750616849942173af3bdfd90
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public enum EHeaderType
|
||||||
|
{
|
||||||
|
AssetPath,
|
||||||
|
StringValue,
|
||||||
|
LongValue,
|
||||||
|
DoubleValue,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 97cd7d0d616708e42bc53ed7d88718c9
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class ReportElement
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// GUID(白名单存储对象)
|
||||||
|
/// </summary>
|
||||||
|
public string GUID;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描是否通过
|
||||||
|
/// </summary>
|
||||||
|
public bool Passes = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 反馈的信息列表
|
||||||
|
/// </summary>
|
||||||
|
public List<ReportScanInfo> ScanInfos = new List<ReportScanInfo>();
|
||||||
|
|
||||||
|
|
||||||
|
public ReportElement(string guid)
|
||||||
|
{
|
||||||
|
GUID = guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加扫描信息
|
||||||
|
/// </summary>
|
||||||
|
public void AddScanInfo(string headerTitle, string scanInfo)
|
||||||
|
{
|
||||||
|
var reportScanInfo = new ReportScanInfo(headerTitle, scanInfo);
|
||||||
|
ScanInfos.Add(reportScanInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取扫描信息
|
||||||
|
/// </summary>
|
||||||
|
public ReportScanInfo GetScanInfo(string headerTitle)
|
||||||
|
{
|
||||||
|
foreach (var scanInfo in ScanInfos)
|
||||||
|
{
|
||||||
|
if (scanInfo.HeaderTitle == headerTitle)
|
||||||
|
return scanInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnityEngine.Debug.LogWarning($"Not found {nameof(ReportScanInfo)} : {headerTitle}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 临时字段
|
||||||
|
/// <summary>
|
||||||
|
/// 是否在列表里选中
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSelected { set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否在白名单里
|
||||||
|
/// </summary>
|
||||||
|
public bool IsWhiteList { set; get; }
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d61f7ee1a8215bf438071055f0a9cb09
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,89 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class ReportHeader
|
||||||
|
{
|
||||||
|
public const int MaxValue = 8388608;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标题
|
||||||
|
/// </summary>
|
||||||
|
public string HeaderTitle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标题宽度
|
||||||
|
/// </summary>
|
||||||
|
public int Width;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单元列最小宽度
|
||||||
|
/// </summary>
|
||||||
|
public int MinWidth = 30;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单元列最大宽度
|
||||||
|
/// </summary>
|
||||||
|
public int MaxWidth = MaxValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可伸缩选项
|
||||||
|
/// </summary>
|
||||||
|
public bool Stretchable = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可搜索选项
|
||||||
|
/// </summary>
|
||||||
|
public bool Searchable = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可排序选项
|
||||||
|
/// </summary>
|
||||||
|
public bool Sortable = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数值类型
|
||||||
|
/// </summary>
|
||||||
|
public EHeaderType HeaderType = EHeaderType.StringValue;
|
||||||
|
|
||||||
|
|
||||||
|
public ReportHeader(string headerTitle, int width)
|
||||||
|
{
|
||||||
|
HeaderTitle = headerTitle;
|
||||||
|
Width = width;
|
||||||
|
}
|
||||||
|
public ReportHeader SetMinWidth(int value)
|
||||||
|
{
|
||||||
|
MinWidth = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ReportHeader SetMaxWidth(int value)
|
||||||
|
{
|
||||||
|
MaxWidth = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ReportHeader SetStretchable()
|
||||||
|
{
|
||||||
|
Stretchable = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ReportHeader SetSearchable()
|
||||||
|
{
|
||||||
|
Searchable = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ReportHeader SetSortable()
|
||||||
|
{
|
||||||
|
Sortable = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ReportHeader SetHeaderType(EHeaderType value)
|
||||||
|
{
|
||||||
|
HeaderType = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3be8b45a77bb720478379c26da3aa68a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class ReportScanInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标题
|
||||||
|
/// </summary>
|
||||||
|
public string HeaderTitle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描反馈的信息
|
||||||
|
/// </summary>
|
||||||
|
public string ScanInfo;
|
||||||
|
|
||||||
|
public ReportScanInfo(string headerTitle, string scanInfo)
|
||||||
|
{
|
||||||
|
HeaderTitle = headerTitle;
|
||||||
|
ScanInfo = scanInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 02caa7ae84ee8294a8904a5aaed420ee
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,65 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class ScanReport
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文件签名(自动填写)
|
||||||
|
/// </summary>
|
||||||
|
public string FileSign;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件版本(自动填写)
|
||||||
|
/// </summary>
|
||||||
|
public string FileVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模式类型(自动填写)
|
||||||
|
/// </summary>
|
||||||
|
public string SchemaType;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描器GUID(自动填写)
|
||||||
|
/// </summary>
|
||||||
|
public string ScannerGUID;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 报告标题
|
||||||
|
/// </summary>
|
||||||
|
public string ReportTitle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 报告介绍
|
||||||
|
/// </summary>
|
||||||
|
public string ReportDesc;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 报告的标题列表
|
||||||
|
/// </summary>
|
||||||
|
public List<ReportHeader> HeaderTitles = new List<ReportHeader>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描的元素列表
|
||||||
|
/// </summary>
|
||||||
|
public List<ReportElement> ReportElements = new List<ReportElement>();
|
||||||
|
|
||||||
|
|
||||||
|
public ScanReport(string reportTitle, string reportDesc)
|
||||||
|
{
|
||||||
|
ReportTitle = reportTitle;
|
||||||
|
ReportDesc = reportDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReportHeader AddHeader(string headerTitle, int width)
|
||||||
|
{
|
||||||
|
var reportHeader = new ReportHeader(headerTitle, width);
|
||||||
|
HeaderTitles.Add(reportHeader);
|
||||||
|
return reportHeader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 650e3e4af4ede2a4eb2471c30e7820bb
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,219 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 资源扫描报告合并器
|
||||||
|
/// 说明:相同类型的报告可以合并查看
|
||||||
|
/// </summary>
|
||||||
|
public class ScanReportCombiner
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 模式类型
|
||||||
|
/// </summary>
|
||||||
|
public string SchemaType { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 报告标题
|
||||||
|
/// </summary>
|
||||||
|
public string ReportTitle { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 报告介绍
|
||||||
|
/// </summary>
|
||||||
|
public string ReportDesc { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标题列表
|
||||||
|
/// </summary>
|
||||||
|
public List<ReportHeader> Headers = new List<ReportHeader>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描结果
|
||||||
|
/// </summary>
|
||||||
|
public readonly List<ReportElement> Elements = new List<ReportElement>(10000);
|
||||||
|
private readonly Dictionary<string, ScanReport> _combines = new Dictionary<string, ScanReport>(100);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 合并报告文件
|
||||||
|
/// 注意:模式不同的报告文件会合并失败!
|
||||||
|
/// </summary>
|
||||||
|
public bool Combine(ScanReport scanReport)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(scanReport.SchemaType))
|
||||||
|
{
|
||||||
|
Debug.LogError("Scan report schema type is null or empty !");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(SchemaType))
|
||||||
|
{
|
||||||
|
SchemaType = scanReport.SchemaType;
|
||||||
|
ReportTitle = scanReport.ReportTitle;
|
||||||
|
ReportDesc = scanReport.ReportDesc;
|
||||||
|
Headers = scanReport.HeaderTitles;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SchemaType != scanReport.SchemaType)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Scan report has different schema type!{scanReport.SchemaType} != {SchemaType}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_combines.ContainsKey(scanReport.ScannerGUID))
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Scan report has already existed : {scanReport.ScannerGUID}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_combines.Add(scanReport.ScannerGUID, scanReport);
|
||||||
|
CombineInternal(scanReport);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private void CombineInternal(ScanReport scanReport)
|
||||||
|
{
|
||||||
|
string scannerGUID = scanReport.ScannerGUID;
|
||||||
|
List<ReportElement> elements = scanReport.ReportElements;
|
||||||
|
|
||||||
|
// 设置白名单
|
||||||
|
var scanner = AssetArtScannerSettingData.GetScannerByGUID(scannerGUID);
|
||||||
|
if (scanner != null)
|
||||||
|
{
|
||||||
|
foreach (var element in elements)
|
||||||
|
{
|
||||||
|
if (scanner.CheckWhiteList(element.GUID))
|
||||||
|
element.IsWhiteList = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加到集合
|
||||||
|
Elements.AddRange(elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定的标题类
|
||||||
|
/// </summary>
|
||||||
|
public ReportHeader GetHeader(string headerTitle)
|
||||||
|
{
|
||||||
|
foreach (var header in Headers)
|
||||||
|
{
|
||||||
|
if (header.HeaderTitle == headerTitle)
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnityEngine.Debug.LogWarning($"Not found {nameof(ReportHeader)} : {headerTitle}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导出选中文件
|
||||||
|
/// </summary>
|
||||||
|
public void ExportFiles(string exportFolderPath)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(exportFolderPath))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var element in Elements)
|
||||||
|
{
|
||||||
|
if (element.IsSelected)
|
||||||
|
{
|
||||||
|
string assetPath = AssetDatabase.GUIDToAssetPath(element.GUID);
|
||||||
|
if (string.IsNullOrEmpty(assetPath) == false)
|
||||||
|
{
|
||||||
|
string destPath = Path.Combine(exportFolderPath, assetPath);
|
||||||
|
EditorTools.CopyFile(assetPath, destPath, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存改变数据
|
||||||
|
/// </summary>
|
||||||
|
public void SaveChange()
|
||||||
|
{
|
||||||
|
// 存储白名单
|
||||||
|
foreach (var scanReport in _combines.Values)
|
||||||
|
{
|
||||||
|
string scannerGUID = scanReport.ScannerGUID;
|
||||||
|
var elements = scanReport.ReportElements;
|
||||||
|
|
||||||
|
var scanner = AssetArtScannerSettingData.GetScannerByGUID(scannerGUID);
|
||||||
|
if (scanner != null)
|
||||||
|
{
|
||||||
|
List<string> whiteList = new List<string>(elements.Count);
|
||||||
|
foreach (var element in elements)
|
||||||
|
{
|
||||||
|
if (element.IsWhiteList)
|
||||||
|
whiteList.Add(element.GUID);
|
||||||
|
}
|
||||||
|
whiteList.Sort();
|
||||||
|
scanner.WhiteList = whiteList;
|
||||||
|
AssetArtScannerSettingData.SaveFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修复所有(排除白名单)
|
||||||
|
/// </summary>
|
||||||
|
public void FixAll()
|
||||||
|
{
|
||||||
|
foreach (var scanReport in _combines.Values)
|
||||||
|
{
|
||||||
|
string scannerGUID = scanReport.ScannerGUID;
|
||||||
|
var elements = scanReport.ReportElements;
|
||||||
|
|
||||||
|
List<ReportElement> fixList = new List<ReportElement>(elements.Count);
|
||||||
|
foreach (var element in elements)
|
||||||
|
{
|
||||||
|
if (element.Passes || element.IsWhiteList)
|
||||||
|
continue;
|
||||||
|
fixList.Add(element);
|
||||||
|
}
|
||||||
|
FixInternal(scannerGUID, fixList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修复选择项(包含白名单)
|
||||||
|
/// </summary>
|
||||||
|
public void FixSelect()
|
||||||
|
{
|
||||||
|
foreach (var scanReport in _combines.Values)
|
||||||
|
{
|
||||||
|
string scannerGUID = scanReport.ScannerGUID;
|
||||||
|
var elements = scanReport.ReportElements;
|
||||||
|
|
||||||
|
List<ReportElement> fixList = new List<ReportElement>(elements.Count);
|
||||||
|
foreach (var element in elements)
|
||||||
|
{
|
||||||
|
if (element.Passes)
|
||||||
|
continue;
|
||||||
|
if (element.IsSelected)
|
||||||
|
fixList.Add(element);
|
||||||
|
}
|
||||||
|
FixInternal(scannerGUID, fixList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixInternal(string scannerGUID, List<ReportElement> fixList)
|
||||||
|
{
|
||||||
|
AssetArtScanner scanner = AssetArtScannerSettingData.GetScannerByGUID(scannerGUID);
|
||||||
|
if (scanner != null)
|
||||||
|
{
|
||||||
|
var schema = scanner.LoadSchema();
|
||||||
|
if (schema != null)
|
||||||
|
{
|
||||||
|
schema.FixResult(fixList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8524c3deb9b27fe4e8e63f15b9ffaaa3
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public class ScanReportConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 导入JSON报告文件
|
||||||
|
/// </summary>
|
||||||
|
public static ScanReport ImportJsonConfig(string filePath)
|
||||||
|
{
|
||||||
|
if (File.Exists(filePath) == false)
|
||||||
|
throw new FileNotFoundException(filePath);
|
||||||
|
|
||||||
|
string jsonData = FileUtility.ReadAllText(filePath);
|
||||||
|
ScanReport report = JsonUtility.FromJson<ScanReport>(jsonData);
|
||||||
|
|
||||||
|
// 检测配置文件的签名
|
||||||
|
if (report.FileSign != ScannerDefine.ReportFileSign)
|
||||||
|
throw new Exception($"导入的报告文件无法识别 : {filePath}");
|
||||||
|
|
||||||
|
// 检测报告文件的版本
|
||||||
|
if (report.FileVersion != ScannerDefine.ReportFileVersion)
|
||||||
|
throw new Exception($"报告文件的版本不匹配 : {report.FileVersion} != {ScannerDefine.ReportFileVersion}");
|
||||||
|
|
||||||
|
// 检测标题数和内容是否匹配
|
||||||
|
foreach (var element in report.ReportElements)
|
||||||
|
{
|
||||||
|
if (element.ScanInfos.Count != report.HeaderTitles.Count)
|
||||||
|
{
|
||||||
|
throw new Exception($"报告的标题数和内容不匹配!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导出JSON报告文件
|
||||||
|
/// </summary>
|
||||||
|
public static void ExportJsonConfig(string savePath, ScanReport scanReport)
|
||||||
|
{
|
||||||
|
if (File.Exists(savePath))
|
||||||
|
File.Delete(savePath);
|
||||||
|
|
||||||
|
string json = JsonUtility.ToJson(scanReport, true);
|
||||||
|
FileUtility.WriteAllText(savePath, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 694cf47ade54f2b4fa6e618c1310c476
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9bc1ecc3b72dfc34782fb6926d679f92
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class AssetArtCollector
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描目录
|
||||||
|
/// </summary>
|
||||||
|
public string CollectPath = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6e7252b59455e5c45af0041ccd24b234
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,112 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class AssetArtScanner
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描器GUID
|
||||||
|
/// </summary>
|
||||||
|
public string ScannerGUID = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描器名称
|
||||||
|
/// </summary>
|
||||||
|
public string ScannerName = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描器描述
|
||||||
|
/// </summary>
|
||||||
|
public string ScannerDesc = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描模式
|
||||||
|
/// </summary>
|
||||||
|
public string ScannerSchema = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 存储目录
|
||||||
|
/// </summary>
|
||||||
|
public string SaveDirectory = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 收集列表
|
||||||
|
/// </summary>
|
||||||
|
public List<AssetArtCollector> Collectors = new List<AssetArtCollector>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 白名单
|
||||||
|
/// </summary>
|
||||||
|
public List<string> WhiteList = new List<string>();
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否在白名单里
|
||||||
|
/// </summary>
|
||||||
|
public bool CheckWhiteList(string guid)
|
||||||
|
{
|
||||||
|
return WhiteList.Contains(guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载扫描模式实例
|
||||||
|
/// </summary>
|
||||||
|
public ScannerSchema LoadSchema()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(ScannerSchema))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string filePath;
|
||||||
|
if (ScannerSchema.StartsWith("Assets/"))
|
||||||
|
{
|
||||||
|
filePath = ScannerSchema;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string guid = ScannerSchema;
|
||||||
|
filePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
var schema = AssetDatabase.LoadMainAssetAtPath(filePath) as ScannerSchema;
|
||||||
|
if (schema == null)
|
||||||
|
Debug.LogWarning($"Failed load scanner schema : {filePath}");
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 运行扫描器生成报告类
|
||||||
|
/// </summary>
|
||||||
|
public ScanReport RunScanner()
|
||||||
|
{
|
||||||
|
if (Collectors.Count == 0)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Scanner collector is empty : {ScannerName}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScannerSchema schema = LoadSchema();
|
||||||
|
if (schema == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var report = schema.RunScanner(this);
|
||||||
|
report.FileSign = ScannerDefine.ReportFileSign;
|
||||||
|
report.FileVersion = ScannerDefine.ReportFileVersion;
|
||||||
|
report.SchemaType = schema.GetType().FullName;
|
||||||
|
report.ScannerGUID = ScannerGUID;
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckKeyword(string keyword)
|
||||||
|
{
|
||||||
|
if (ScannerName.Contains(keyword) || ScannerDesc.Contains(keyword))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c63683b07b7a2454b93539ae6b9f32ea
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,85 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public class AssetArtScannerConfig
|
||||||
|
{
|
||||||
|
public class ConfigWrapper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文件签名
|
||||||
|
/// </summary>
|
||||||
|
public string FileSign;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件版本
|
||||||
|
/// </summary>
|
||||||
|
public string FileVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描器列表
|
||||||
|
/// </summary>
|
||||||
|
public List<AssetArtScanner> Scanners = new List<AssetArtScanner>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导入JSON配置文件
|
||||||
|
/// </summary>
|
||||||
|
public static void ImportJsonConfig(string filePath)
|
||||||
|
{
|
||||||
|
if (File.Exists(filePath) == false)
|
||||||
|
throw new FileNotFoundException(filePath);
|
||||||
|
|
||||||
|
string json = FileUtility.ReadAllText(filePath);
|
||||||
|
ConfigWrapper setting = JsonUtility.FromJson<ConfigWrapper>(json);
|
||||||
|
|
||||||
|
// 检测配置文件的签名
|
||||||
|
if (setting.FileSign != ScannerDefine.SettingFileSign)
|
||||||
|
throw new Exception($"导入的配置文件无法识别 : {filePath}");
|
||||||
|
|
||||||
|
// 检测配置文件的版本
|
||||||
|
if (setting.FileVersion != ScannerDefine.SettingFileVersion)
|
||||||
|
throw new Exception($"配置文件的版本不匹配 : {setting.FileVersion} != {ScannerDefine.SettingFileVersion}");
|
||||||
|
|
||||||
|
// 检测配置合法性
|
||||||
|
HashSet<string> scanGUIDs = new HashSet<string>();
|
||||||
|
foreach (var sacnner in setting.Scanners)
|
||||||
|
{
|
||||||
|
if (scanGUIDs.Contains(sacnner.ScannerGUID))
|
||||||
|
{
|
||||||
|
throw new Exception($"Scanner {sacnner.ScannerName} GUID is existed : {sacnner.ScannerGUID} ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scanGUIDs.Add(sacnner.ScannerGUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetArtScannerSettingData.Setting.Scanners = setting.Scanners;
|
||||||
|
AssetArtScannerSettingData.SaveFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导出JSON配置文件
|
||||||
|
/// </summary>
|
||||||
|
public static void ExportJsonConfig(string savePath)
|
||||||
|
{
|
||||||
|
if (File.Exists(savePath))
|
||||||
|
File.Delete(savePath);
|
||||||
|
|
||||||
|
ConfigWrapper wrapper = new ConfigWrapper();
|
||||||
|
wrapper.FileSign = ScannerDefine.SettingFileSign;
|
||||||
|
wrapper.FileVersion = ScannerDefine.SettingFileVersion;
|
||||||
|
wrapper.Scanners = AssetArtScannerSettingData.Setting.Scanners;
|
||||||
|
|
||||||
|
string json = JsonUtility.ToJson(wrapper, true);
|
||||||
|
FileUtility.WriteAllText(savePath, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bed1ef72d1c03e848a41d5ea115e9870
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public class AssetArtScannerSetting : ScriptableObject
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描器列表
|
||||||
|
/// </summary>
|
||||||
|
public List<AssetArtScanner> Scanners = new List<AssetArtScanner>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 84df5e62e3f1b6746a1263e076b003e1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,203 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public class AssetArtScannerSettingData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 配置数据是否被修改
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsDirty { private set; get; } = false;
|
||||||
|
|
||||||
|
|
||||||
|
static AssetArtScannerSettingData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AssetArtScannerSetting _setting = null;
|
||||||
|
public static AssetArtScannerSetting Setting
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_setting == null)
|
||||||
|
_setting = SettingLoader.LoadSettingData<AssetArtScannerSetting>();
|
||||||
|
return _setting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 存储配置文件
|
||||||
|
/// </summary>
|
||||||
|
public static void SaveFile()
|
||||||
|
{
|
||||||
|
if (Setting != null)
|
||||||
|
{
|
||||||
|
IsDirty = false;
|
||||||
|
EditorUtility.SetDirty(Setting);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
Debug.Log($"{nameof(AssetArtScannerSetting)}.asset is saved!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清空所有数据
|
||||||
|
/// </summary>
|
||||||
|
public static void ClearAll()
|
||||||
|
{
|
||||||
|
Setting.Scanners.Clear();
|
||||||
|
SaveFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描所有项
|
||||||
|
/// </summary>
|
||||||
|
public static void ScanAll()
|
||||||
|
{
|
||||||
|
foreach (var scanner in Setting.Scanners)
|
||||||
|
{
|
||||||
|
var scanResult = ScanInternal(scanner);
|
||||||
|
if (scanResult.Succeed == false)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Scanner {scanner.ScannerName} failed ! {scanResult.ErrorInfo}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描所有项
|
||||||
|
/// </summary>
|
||||||
|
public static void ScanAll(string keyword)
|
||||||
|
{
|
||||||
|
foreach (var scanner in Setting.Scanners)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(keyword) == false)
|
||||||
|
{
|
||||||
|
if (scanner.CheckKeyword(keyword) == false)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var scanResult = ScanInternal(scanner);
|
||||||
|
if (scanResult.Succeed == false)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Scanner {scanner.ScannerName} failed ! {scanResult.ErrorInfo}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描单项
|
||||||
|
/// </summary>
|
||||||
|
public static ScannerResult Scan(string scannerGUID)
|
||||||
|
{
|
||||||
|
AssetArtScanner scanner = GetScannerByGUID(scannerGUID);
|
||||||
|
var scanResult = ScanInternal(scanner);
|
||||||
|
if (scanResult.Succeed == false)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Scanner {scanner.ScannerName} failed ! {scanResult.ErrorInfo}");
|
||||||
|
}
|
||||||
|
return scanResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定的扫描器
|
||||||
|
/// </summary>
|
||||||
|
public static AssetArtScanner GetScannerByGUID(string scannerGUID)
|
||||||
|
{
|
||||||
|
foreach (var scanner in Setting.Scanners)
|
||||||
|
{
|
||||||
|
if (scanner.ScannerGUID == scannerGUID)
|
||||||
|
return scanner;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.LogWarning($"Not found scanner : {scannerGUID}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扫描器编辑相关
|
||||||
|
public static AssetArtScanner CreateScanner(string name, string desc)
|
||||||
|
{
|
||||||
|
AssetArtScanner scanner = new AssetArtScanner();
|
||||||
|
scanner.ScannerGUID = System.Guid.NewGuid().ToString();
|
||||||
|
scanner.ScannerName = name;
|
||||||
|
scanner.ScannerDesc = desc;
|
||||||
|
Setting.Scanners.Add(scanner);
|
||||||
|
IsDirty = true;
|
||||||
|
return scanner;
|
||||||
|
}
|
||||||
|
public static void RemoveScanner(AssetArtScanner scanner)
|
||||||
|
{
|
||||||
|
if (Setting.Scanners.Remove(scanner))
|
||||||
|
{
|
||||||
|
IsDirty = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Failed remove scanner : {scanner.ScannerName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void ModifyScanner(AssetArtScanner scanner)
|
||||||
|
{
|
||||||
|
if (scanner != null)
|
||||||
|
{
|
||||||
|
IsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 资源收集编辑相关
|
||||||
|
public static void CreateCollector(AssetArtScanner scanner, AssetArtCollector collector)
|
||||||
|
{
|
||||||
|
scanner.Collectors.Add(collector);
|
||||||
|
IsDirty = true;
|
||||||
|
}
|
||||||
|
public static void RemoveCollector(AssetArtScanner scanner, AssetArtCollector collector)
|
||||||
|
{
|
||||||
|
if (scanner.Collectors.Remove(collector))
|
||||||
|
{
|
||||||
|
IsDirty = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Failed remove collector : {collector.CollectPath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void ModifyCollector(AssetArtScanner scanner, AssetArtCollector collector)
|
||||||
|
{
|
||||||
|
if (scanner != null && collector != null)
|
||||||
|
{
|
||||||
|
IsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ScannerResult ScanInternal(AssetArtScanner scanner)
|
||||||
|
{
|
||||||
|
if (scanner == null)
|
||||||
|
return new ScannerResult("Scanner is null !");
|
||||||
|
|
||||||
|
string saveDirectory = "Assets/";
|
||||||
|
if (string.IsNullOrEmpty(scanner.SaveDirectory) == false)
|
||||||
|
{
|
||||||
|
saveDirectory = scanner.SaveDirectory;
|
||||||
|
if (Directory.Exists(saveDirectory) == false)
|
||||||
|
return new ScannerResult($"Scanner save directory is invalid : {saveDirectory}");
|
||||||
|
}
|
||||||
|
|
||||||
|
ScanReport report = scanner.RunScanner();
|
||||||
|
if (report != null)
|
||||||
|
{
|
||||||
|
string filePath = $"{saveDirectory}/{scanner.ScannerName}_{scanner.ScannerDesc}.json";
|
||||||
|
ScanReportConfig.ExportJsonConfig(filePath, report);
|
||||||
|
return new ScannerResult(filePath, report);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new ScannerResult($"Scanner run failed : {scanner.ScannerName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fda10f23f6f36bf498b54323fe4f680b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,481 @@
|
||||||
|
#if UNITY_2019_4_OR_NEWER
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor.UIElements;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public class AssetArtScannerWindow : EditorWindow
|
||||||
|
{
|
||||||
|
[MenuItem("YooAsset/AssetArt Scanner", false, 301)]
|
||||||
|
public static void OpenWindow()
|
||||||
|
{
|
||||||
|
AssetArtScannerWindow window = GetWindow<AssetArtScannerWindow>("资源扫描工具", true, WindowsDefine.DockedWindowTypes);
|
||||||
|
window.minSize = new Vector2(800, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button _saveButton;
|
||||||
|
private ListView _scannerListView;
|
||||||
|
private ToolbarSearchField _scannerSearchField;
|
||||||
|
private VisualElement _scannerContentContainer;
|
||||||
|
private Label _schemaGuideTxt;
|
||||||
|
private TextField _scannerNameTxt;
|
||||||
|
private TextField _scannerDescTxt;
|
||||||
|
private ObjectField _scanSchemaField;
|
||||||
|
private ObjectField _saveFolderField;
|
||||||
|
private ScrollView _collectorScrollView;
|
||||||
|
|
||||||
|
private int _lastModifyScannerIndex = 0;
|
||||||
|
|
||||||
|
|
||||||
|
public void CreateGUI()
|
||||||
|
{
|
||||||
|
Undo.undoRedoPerformed -= RefreshWindow;
|
||||||
|
Undo.undoRedoPerformed += RefreshWindow;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
VisualElement root = this.rootVisualElement;
|
||||||
|
|
||||||
|
// 加载布局文件
|
||||||
|
var visualAsset = UxmlLoader.LoadWindowUXML<AssetArtScannerWindow>();
|
||||||
|
if (visualAsset == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
visualAsset.CloneTree(root);
|
||||||
|
|
||||||
|
// 导入导出按钮
|
||||||
|
var exportBtn = root.Q<Button>("ExportButton");
|
||||||
|
exportBtn.clicked += ExportBtn_clicked;
|
||||||
|
var importBtn = root.Q<Button>("ImportButton");
|
||||||
|
importBtn.clicked += ImportBtn_clicked;
|
||||||
|
|
||||||
|
// 配置保存按钮
|
||||||
|
_saveButton = root.Q<Button>("SaveButton");
|
||||||
|
_saveButton.clicked += SaveBtn_clicked;
|
||||||
|
|
||||||
|
// 扫描按钮
|
||||||
|
var scanAllBtn = root.Q<Button>("ScanAllButton");
|
||||||
|
scanAllBtn.clicked += ScanAllBtn_clicked;
|
||||||
|
var scanBtn = root.Q<Button>("ScanBtn");
|
||||||
|
scanBtn.clicked += ScanBtn_clicked;
|
||||||
|
|
||||||
|
// 扫描列表相关
|
||||||
|
_scannerListView = root.Q<ListView>("ScannerListView");
|
||||||
|
_scannerListView.makeItem = MakeScannerListViewItem;
|
||||||
|
_scannerListView.bindItem = BindScannerListViewItem;
|
||||||
|
#if UNITY_2020_1_OR_NEWER
|
||||||
|
_scannerListView.onSelectionChange += ScannerListView_onSelectionChange;
|
||||||
|
#else
|
||||||
|
_scannerListView.onSelectionChanged += ScannerListView_onSelectionChange;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 扫描列表过滤
|
||||||
|
_scannerSearchField = root.Q<ToolbarSearchField>("ScannerSearchField");
|
||||||
|
_scannerSearchField.RegisterValueChangedCallback(OnSearchKeyWordChange);
|
||||||
|
|
||||||
|
// 扫描器添加删除按钮
|
||||||
|
var scannerAddContainer = root.Q("ScannerAddContainer");
|
||||||
|
{
|
||||||
|
var addBtn = scannerAddContainer.Q<Button>("AddBtn");
|
||||||
|
addBtn.clicked += AddScannerBtn_clicked;
|
||||||
|
var removeBtn = scannerAddContainer.Q<Button>("RemoveBtn");
|
||||||
|
removeBtn.clicked += RemoveScannerBtn_clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扫描器容器
|
||||||
|
_scannerContentContainer = root.Q("ScannerContentContainer");
|
||||||
|
|
||||||
|
// 扫描器指南
|
||||||
|
_schemaGuideTxt = root.Q<Label>("SchemaUserGuide");
|
||||||
|
|
||||||
|
// 扫描器名称
|
||||||
|
_scannerNameTxt = root.Q<TextField>("ScannerName");
|
||||||
|
_scannerNameTxt.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectScanner != null)
|
||||||
|
{
|
||||||
|
selectScanner.ScannerName = evt.newValue;
|
||||||
|
AssetArtScannerSettingData.ModifyScanner(selectScanner);
|
||||||
|
FillScannerListViewData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 扫描器备注
|
||||||
|
_scannerDescTxt = root.Q<TextField>("ScannerDesc");
|
||||||
|
_scannerDescTxt.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectScanner != null)
|
||||||
|
{
|
||||||
|
selectScanner.ScannerDesc = evt.newValue;
|
||||||
|
AssetArtScannerSettingData.ModifyScanner(selectScanner);
|
||||||
|
FillScannerListViewData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 扫描模式
|
||||||
|
_scanSchemaField = root.Q<ObjectField>("ScanSchema");
|
||||||
|
_scanSchemaField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectScanner != null)
|
||||||
|
{
|
||||||
|
string assetPath = AssetDatabase.GetAssetPath(evt.newValue);
|
||||||
|
_scanSchemaField.value.name = assetPath;
|
||||||
|
selectScanner.ScannerSchema = AssetDatabase.AssetPathToGUID(assetPath);
|
||||||
|
AssetArtScannerSettingData.ModifyScanner(selectScanner);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 存储目录
|
||||||
|
_saveFolderField = root.Q<ObjectField>("SaveFolder");
|
||||||
|
_saveFolderField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectScanner != null)
|
||||||
|
{
|
||||||
|
string assetPath = AssetDatabase.GetAssetPath(evt.newValue);
|
||||||
|
if (AssetDatabase.IsValidFolder(assetPath))
|
||||||
|
{
|
||||||
|
_saveFolderField.value.name = assetPath;
|
||||||
|
selectScanner.SaveDirectory = assetPath;
|
||||||
|
AssetArtScannerSettingData.ModifyScanner(selectScanner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Select asset object not folder ! {assetPath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 收集列表相关
|
||||||
|
_collectorScrollView = root.Q<ScrollView>("CollectorScrollView");
|
||||||
|
_collectorScrollView.style.height = new Length(100, LengthUnit.Percent);
|
||||||
|
_collectorScrollView.viewDataKey = "scrollView";
|
||||||
|
|
||||||
|
// 收集器创建按钮
|
||||||
|
var collectorAddContainer = root.Q("CollectorAddContainer");
|
||||||
|
{
|
||||||
|
var addBtn = collectorAddContainer.Q<Button>("AddBtn");
|
||||||
|
addBtn.clicked += AddCollectorBtn_clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新窗体
|
||||||
|
RefreshWindow();
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void OnDestroy()
|
||||||
|
{
|
||||||
|
// 注意:清空所有撤销操作
|
||||||
|
Undo.ClearAll();
|
||||||
|
|
||||||
|
if (AssetArtScannerSettingData.IsDirty)
|
||||||
|
AssetArtScannerSettingData.SaveFile();
|
||||||
|
}
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (_saveButton != null)
|
||||||
|
{
|
||||||
|
if (AssetArtScannerSettingData.IsDirty)
|
||||||
|
{
|
||||||
|
if (_saveButton.enabledSelf == false)
|
||||||
|
_saveButton.SetEnabled(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_saveButton.enabledSelf)
|
||||||
|
_saveButton.SetEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshWindow()
|
||||||
|
{
|
||||||
|
_scannerContentContainer.visible = false;
|
||||||
|
|
||||||
|
FillScannerListViewData();
|
||||||
|
}
|
||||||
|
private void ExportBtn_clicked()
|
||||||
|
{
|
||||||
|
string resultPath = EditorTools.OpenFolderPanel("Export JSON", "Assets/");
|
||||||
|
if (resultPath != null)
|
||||||
|
{
|
||||||
|
AssetArtScannerConfig.ExportJsonConfig($"{resultPath}/AssetArtScannerConfig.json");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void ImportBtn_clicked()
|
||||||
|
{
|
||||||
|
string resultPath = EditorTools.OpenFilePath("Import JSON", "Assets/", "json");
|
||||||
|
if (resultPath != null)
|
||||||
|
{
|
||||||
|
AssetArtScannerConfig.ImportJsonConfig(resultPath);
|
||||||
|
RefreshWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void SaveBtn_clicked()
|
||||||
|
{
|
||||||
|
AssetArtScannerSettingData.SaveFile();
|
||||||
|
}
|
||||||
|
private void ScanAllBtn_clicked()
|
||||||
|
{
|
||||||
|
string searchKeyWord = _scannerSearchField.value;
|
||||||
|
AssetArtScannerSettingData.ScanAll(searchKeyWord);
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
private void ScanBtn_clicked()
|
||||||
|
{
|
||||||
|
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectScanner == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScannerResult scannerResult = AssetArtScannerSettingData.Scan(selectScanner.ScannerGUID);
|
||||||
|
if (scannerResult.Succeed)
|
||||||
|
{
|
||||||
|
// 自动打开报告界面
|
||||||
|
scannerResult.OpenReportWindow();
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void OnSearchKeyWordChange(ChangeEvent<string> e)
|
||||||
|
{
|
||||||
|
_lastModifyScannerIndex = 0;
|
||||||
|
RefreshWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分组列表相关
|
||||||
|
private void FillScannerListViewData()
|
||||||
|
{
|
||||||
|
_scannerListView.Clear();
|
||||||
|
_scannerListView.ClearSelection();
|
||||||
|
_scannerListView.itemsSource = FilterScanners();
|
||||||
|
_scannerListView.Rebuild();
|
||||||
|
|
||||||
|
if (_lastModifyScannerIndex >= 0 && _lastModifyScannerIndex < _scannerListView.itemsSource.Count)
|
||||||
|
{
|
||||||
|
_scannerListView.selectedIndex = _lastModifyScannerIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private List<AssetArtScanner> FilterScanners()
|
||||||
|
{
|
||||||
|
string searchKeyWord = _scannerSearchField.value;
|
||||||
|
List<AssetArtScanner> result = new List<AssetArtScanner>(AssetArtScannerSettingData.Setting.Scanners.Count);
|
||||||
|
|
||||||
|
// 过滤列表
|
||||||
|
foreach (var scanner in AssetArtScannerSettingData.Setting.Scanners)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(searchKeyWord) == false)
|
||||||
|
{
|
||||||
|
if (scanner.CheckKeyword(searchKeyWord) == false)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.Add(scanner);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
private VisualElement MakeScannerListViewItem()
|
||||||
|
{
|
||||||
|
VisualElement element = new VisualElement();
|
||||||
|
|
||||||
|
{
|
||||||
|
var label = new Label();
|
||||||
|
label.name = "Label1";
|
||||||
|
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||||
|
label.style.flexGrow = 1f;
|
||||||
|
label.style.height = 20f;
|
||||||
|
element.Add(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
private void BindScannerListViewItem(VisualElement element, int index)
|
||||||
|
{
|
||||||
|
List<AssetArtScanner> sourceList = _scannerListView.itemsSource as List<AssetArtScanner>;
|
||||||
|
var scanner = sourceList[index];
|
||||||
|
var textField1 = element.Q<Label>("Label1");
|
||||||
|
if (string.IsNullOrEmpty(scanner.ScannerDesc))
|
||||||
|
textField1.text = scanner.ScannerName;
|
||||||
|
else
|
||||||
|
textField1.text = $"{scanner.ScannerName} ({scanner.ScannerDesc})";
|
||||||
|
}
|
||||||
|
private void ScannerListView_onSelectionChange(IEnumerable<object> objs)
|
||||||
|
{
|
||||||
|
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectScanner == null)
|
||||||
|
{
|
||||||
|
_scannerContentContainer.visible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_scannerContentContainer.visible = true;
|
||||||
|
_lastModifyScannerIndex = _scannerListView.selectedIndex;
|
||||||
|
_scannerNameTxt.SetValueWithoutNotify(selectScanner.ScannerName);
|
||||||
|
_scannerDescTxt.SetValueWithoutNotify(selectScanner.ScannerDesc);
|
||||||
|
|
||||||
|
// 显示Schema对象
|
||||||
|
var scanSchema = selectScanner.LoadSchema();
|
||||||
|
if (scanSchema == null)
|
||||||
|
{
|
||||||
|
_scanSchemaField.SetValueWithoutNotify(null);
|
||||||
|
_schemaGuideTxt.text = string.Empty;
|
||||||
|
Selection.activeObject = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_scanSchemaField.SetValueWithoutNotify(scanSchema);
|
||||||
|
_schemaGuideTxt.text = scanSchema.GetUserGuide();
|
||||||
|
Selection.activeObject = scanSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示存储目录
|
||||||
|
DefaultAsset saveFolder = AssetDatabase.LoadAssetAtPath<DefaultAsset>(selectScanner.SaveDirectory);
|
||||||
|
if (saveFolder == null)
|
||||||
|
{
|
||||||
|
_saveFolderField.SetValueWithoutNotify(null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_saveFolderField.SetValueWithoutNotify(saveFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
FillCollectorViewData();
|
||||||
|
}
|
||||||
|
private void AddScannerBtn_clicked()
|
||||||
|
{
|
||||||
|
Undo.RecordObject(AssetArtScannerSettingData.Setting, "YooAsset.AssetArtScannerWindow AddScanner");
|
||||||
|
AssetArtScannerSettingData.CreateScanner("Default Scanner", string.Empty);
|
||||||
|
FillScannerListViewData();
|
||||||
|
}
|
||||||
|
private void RemoveScannerBtn_clicked()
|
||||||
|
{
|
||||||
|
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectScanner == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Undo.RecordObject(AssetArtScannerSettingData.Setting, "YooAsset.AssetArtScannerWindow RemoveScanner");
|
||||||
|
AssetArtScannerSettingData.RemoveScanner(selectScanner);
|
||||||
|
FillScannerListViewData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集列表相关
|
||||||
|
private void FillCollectorViewData()
|
||||||
|
{
|
||||||
|
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectScanner == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 填充数据
|
||||||
|
_collectorScrollView.Clear();
|
||||||
|
for (int i = 0; i < selectScanner.Collectors.Count; i++)
|
||||||
|
{
|
||||||
|
VisualElement element = MakeCollectorListViewItem();
|
||||||
|
BindCollectorListViewItem(element, i);
|
||||||
|
_collectorScrollView.Add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private VisualElement MakeCollectorListViewItem()
|
||||||
|
{
|
||||||
|
VisualElement element = new VisualElement();
|
||||||
|
|
||||||
|
VisualElement elementTop = new VisualElement();
|
||||||
|
elementTop.style.flexDirection = FlexDirection.Row;
|
||||||
|
element.Add(elementTop);
|
||||||
|
|
||||||
|
VisualElement elementSpace = new VisualElement();
|
||||||
|
elementSpace.style.flexDirection = FlexDirection.Column;
|
||||||
|
element.Add(elementSpace);
|
||||||
|
|
||||||
|
// Top VisualElement
|
||||||
|
{
|
||||||
|
var button = new Button();
|
||||||
|
button.name = "Button1";
|
||||||
|
button.text = "-";
|
||||||
|
button.style.unityTextAlign = TextAnchor.MiddleCenter;
|
||||||
|
button.style.flexGrow = 0f;
|
||||||
|
elementTop.Add(button);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var objectField = new ObjectField();
|
||||||
|
objectField.name = "ObjectField1";
|
||||||
|
objectField.label = "Collector";
|
||||||
|
objectField.objectType = typeof(UnityEngine.Object);
|
||||||
|
objectField.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||||
|
objectField.style.flexGrow = 1f;
|
||||||
|
elementTop.Add(objectField);
|
||||||
|
var label = objectField.Q<Label>();
|
||||||
|
label.style.minWidth = 63;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Space VisualElement
|
||||||
|
{
|
||||||
|
var label = new Label();
|
||||||
|
label.style.height = 10;
|
||||||
|
elementSpace.Add(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
private void BindCollectorListViewItem(VisualElement element, int index)
|
||||||
|
{
|
||||||
|
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectScanner == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var collector = selectScanner.Collectors[index];
|
||||||
|
var collectObject = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(collector.CollectPath);
|
||||||
|
if (collectObject != null)
|
||||||
|
collectObject.name = collector.CollectPath;
|
||||||
|
|
||||||
|
// Remove Button
|
||||||
|
var removeBtn = element.Q<Button>("Button1");
|
||||||
|
removeBtn.clicked += () =>
|
||||||
|
{
|
||||||
|
RemoveCollectorBtn_clicked(collector);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Collector Path
|
||||||
|
var objectField1 = element.Q<ObjectField>("ObjectField1");
|
||||||
|
objectField1.SetValueWithoutNotify(collectObject);
|
||||||
|
objectField1.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
collector.CollectPath = AssetDatabase.GetAssetPath(evt.newValue);
|
||||||
|
objectField1.value.name = collector.CollectPath;
|
||||||
|
AssetArtScannerSettingData.ModifyCollector(selectScanner, collector);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private void AddCollectorBtn_clicked()
|
||||||
|
{
|
||||||
|
var selectSacnner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectSacnner == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Undo.RecordObject(AssetArtScannerSettingData.Setting, "YooAsset.AssetArtScannerWindow AddCollector");
|
||||||
|
AssetArtCollector collector = new AssetArtCollector();
|
||||||
|
AssetArtScannerSettingData.CreateCollector(selectSacnner, collector);
|
||||||
|
FillCollectorViewData();
|
||||||
|
}
|
||||||
|
private void RemoveCollectorBtn_clicked(AssetArtCollector selectCollector)
|
||||||
|
{
|
||||||
|
var selectSacnner = _scannerListView.selectedItem as AssetArtScanner;
|
||||||
|
if (selectSacnner == null)
|
||||||
|
return;
|
||||||
|
if (selectCollector == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Undo.RecordObject(AssetArtScannerSettingData.Setting, "YooAsset.AssetArtScannerWindow RemoveCollector");
|
||||||
|
AssetArtScannerSettingData.RemoveCollector(selectSacnner, selectCollector);
|
||||||
|
FillCollectorViewData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bff583b32bbeb7e498920bfdc84dba90
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,34 @@
|
||||||
|
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
|
||||||
|
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row-reverse;">
|
||||||
|
<ui:Button text="Save" display-tooltip-when-elided="true" name="SaveButton" style="width: 50px; background-color: rgb(56, 147, 58);" />
|
||||||
|
<ui:Button text="导出" display-tooltip-when-elided="true" name="ExportButton" style="width: 50px; background-color: rgb(56, 147, 58);" />
|
||||||
|
<ui:Button text="导入" display-tooltip-when-elided="true" name="ImportButton" style="width: 50px; background-color: rgb(56, 147, 58);" />
|
||||||
|
</uie:Toolbar>
|
||||||
|
<ui:VisualElement name="PublicContainer" style="background-color: rgb(79, 79, 79); flex-direction: column; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
|
||||||
|
<ui:Button text="Scan All" display-tooltip-when-elided="true" name="ScanAllButton" style="height: 25px; -unity-font-style: bold;" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="ContentContainer" style="flex-grow: 1; flex-direction: row;">
|
||||||
|
<ui:VisualElement name="ScannerListContainer" style="width: 250px; flex-grow: 0; background-color: rgb(67, 67, 67); border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
|
||||||
|
<ui:Label text="列表" display-tooltip-when-elided="true" name="ScannerListTitle" style="background-color: rgb(89, 89, 89); -unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 3px; border-right-width: 3px; border-top-width: 3px; border-bottom-width: 3px; font-size: 12px;" />
|
||||||
|
<uie:ToolbarSearchField focusable="true" name="ScannerSearchField" style="width: 230px;" />
|
||||||
|
<ui:ListView focusable="true" name="ScannerListView" item-height="20" virtualization-method="DynamicHeight" style="flex-grow: 1;" />
|
||||||
|
<ui:VisualElement name="ScannerAddContainer" style="justify-content: center; flex-direction: row; flex-shrink: 0;">
|
||||||
|
<ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" />
|
||||||
|
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="ScannerContentContainer" style="flex-grow: 1; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
|
||||||
|
<ui:Label text="扫描器" display-tooltip-when-elided="true" name="ScannerContentTitle" style="-unity-text-align: upper-center; -unity-font-style: bold; font-size: 12px; border-top-width: 3px; border-right-width: 3px; border-bottom-width: 3px; border-left-width: 3px; background-color: rgb(89, 89, 89);" />
|
||||||
|
<ui:Label display-tooltip-when-elided="true" name="SchemaUserGuide" style="-unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px; font-size: 12px; height: 40px;" />
|
||||||
|
<ui:TextField picking-mode="Ignore" label="Scanner Name" name="ScannerName" />
|
||||||
|
<ui:TextField picking-mode="Ignore" label="Scanner Desc" name="ScannerDesc" />
|
||||||
|
<uie:ObjectField label="Scan Schema" name="ScanSchema" type="YooAsset.Editor.ScannerSchema, YooAsset.Editor" />
|
||||||
|
<uie:ObjectField label="Save Folder" name="SaveFolder" type="UnityEditor.DefaultAsset, UnityEditor.CoreModule" />
|
||||||
|
<ui:VisualElement name="CollectorAddContainer" style="height: 20px; flex-direction: row-reverse;">
|
||||||
|
<ui:Button text="[ + ]" display-tooltip-when-elided="true" name="AddBtn" />
|
||||||
|
<ui:Button text="Scan" display-tooltip-when-elided="true" name="ScanBtn" style="width: 60px;" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:ScrollView name="CollectorScrollView" style="flex-grow: 1;" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
</ui:VisualElement>
|
||||||
|
</ui:UXML>
|
|
@ -0,0 +1,10 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5bbb873a7bee2924a86c876b67bb2cb4
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public class ScannerDefine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 报告文件签名
|
||||||
|
/// </summary>
|
||||||
|
public const string ReportFileSign = "596f6f4172745265706f7274";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置文件签名
|
||||||
|
/// </summary>
|
||||||
|
public const string SettingFileSign = "596f6f41727453657474696e67";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 报告文件的版本
|
||||||
|
/// </summary>
|
||||||
|
public const string ReportFileVersion = "1.0";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置文件的版本
|
||||||
|
/// </summary>
|
||||||
|
public const string SettingFileVersion = "1.0";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ed658bfc32cbfc44caf262a741a7c387
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public class ScannerResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 生成的报告文件路径
|
||||||
|
/// </summary>
|
||||||
|
public string ReprotFilePath { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 报告对象
|
||||||
|
/// </summary>
|
||||||
|
public ScanReport Report { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 错误信息
|
||||||
|
/// </summary>
|
||||||
|
public string ErrorInfo { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否成功
|
||||||
|
/// </summary>
|
||||||
|
public bool Succeed
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(ErrorInfo))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ScannerResult(string error)
|
||||||
|
{
|
||||||
|
ErrorInfo = error;
|
||||||
|
}
|
||||||
|
public ScannerResult(string filePath, ScanReport report)
|
||||||
|
{
|
||||||
|
ReprotFilePath = filePath;
|
||||||
|
Report = report;
|
||||||
|
ErrorInfo = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 打开报告窗口
|
||||||
|
/// </summary>
|
||||||
|
public void OpenReportWindow()
|
||||||
|
{
|
||||||
|
if (Succeed)
|
||||||
|
{
|
||||||
|
var reproterWindow = AssetArtReporterWindow.OpenWindow();
|
||||||
|
reproterWindow.ImportSingleReprotFile(ReprotFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e10cdab189d80b142ad5903d12956c59
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public abstract class ScannerSchema : ScriptableObject
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取用户指南信息
|
||||||
|
/// </summary>
|
||||||
|
public abstract string GetUserGuide();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 运行生成扫描报告
|
||||||
|
/// </summary>
|
||||||
|
public abstract ScanReport RunScanner(AssetArtScanner scanner);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修复扫描结果
|
||||||
|
/// </summary>
|
||||||
|
public abstract void FixResult(List<ReportElement> fixList);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: eb6a587c72ccecc4ab6d386063cf0736
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue