首次提交

This commit is contained in:
Bob.Song
2026-03-05 18:07:55 +08:00
commit e125bb869e
4534 changed files with 563920 additions and 0 deletions

View File

@@ -0,0 +1,283 @@
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace NBC.Asset.Editor
{
public class HistoryWindow : EditorWindow
{
[MenuItem(Language.HistoryWindowNameMenuPath, false, 4)]
public static void ShowWindow()
{
var s = string.Empty;
HistoryWindow wnd = GetWindow<HistoryWindow>(Language.HistoryWindowName, true, Defs.DockedWindowTypes);
wnd.minSize = new Vector2(Defs.DefWindowWidth, Defs.DefWindowHeight);
}
const int _splitterThickness = 2;
public VersionHistoryData SelectVersion;
/// <summary>
/// 选中需要比较的版本
/// </summary>
public VersionHistoryData SelectCompareVersion;
readonly VerticalSplitter _verticalSplitter = new VerticalSplitter(0.7f, 0.7f, 0.8f);
readonly HorizontalSplitter _horizontalSplitter = new HorizontalSplitter(0.3f, 0.3f, 0.4f);
private HistoryVersionTreeEditor _versionList;
private HistoryBundleTreeEditor _bundleTreeEditor;
private List<VersionHistoryData> _versionHistory = new List<VersionHistoryData>();
public List<VersionHistoryData> ShowVersionHistory => _versionHistory;
public void UpdateCompareSelectedVersion(string name)
{
if (!string.IsNullOrEmpty(name))
{
foreach (var version in _versionHistory)
{
if (version.ShowName != name) continue;
SelectCompareVersion = version;
}
}
else
{
SelectCompareVersion = null;
}
_versionList?.Reload();
}
public void UpdateSelectedVersion(string name)
{
if (!string.IsNullOrEmpty(name))
{
foreach (var version in _versionHistory)
{
if (version.ShowName != name) continue;
SelectVersion = version;
}
}
else
{
SelectVersion = null;
}
_bundleTreeEditor?.Reload();
}
public void ReloadVersions()
{
_versionHistory = HistoryUtil.GetHistoryVersions();
if (SelectCompareVersion == null && _versionHistory.Count > 1)
{
SelectCompareVersion = _versionHistory[1];
}
}
public void Refresh()
{
ReloadVersions();
UpdateSelectedVersion(string.Empty);
}
protected void OnEnable()
{
SelectVersion = null;
SelectCompareVersion = null;
ReloadVersions();
Styles.Initialize();
}
protected void OnGUI()
{
var barHeight = _splitterThickness;
Rect contentRect = new Rect(_splitterThickness, barHeight, position.width - _splitterThickness * 4,
position.height - _splitterThickness);
var resizingPackage = _horizontalSplitter.OnGUI(contentRect, out var bundleRect, out var infoRect);
DrawVersionList(bundleRect);
bool resizingVer = _verticalSplitter.OnGUI(infoRect, out var top, out var bot);
DrawBundleList(top);
DrawCompareInfo(bot);
if (resizingPackage || resizingVer)
Repaint();
}
void DrawVersionList(Rect rect)
{
if (_versionList == null)
{
_versionList = new HistoryVersionTreeEditor(new TreeViewState(), this,
HistoryVersionTreeEditor.CreateDefaultMultiColumnHeaderState());
}
_versionList.OnGUI(rect);
}
void DrawBundleList(Rect rect)
{
if (_bundleTreeEditor == null)
{
_bundleTreeEditor = new HistoryBundleTreeEditor(new TreeViewState(), this,
HistoryBundleTreeEditor.CreateDefaultMultiColumnHeaderState());
}
_bundleTreeEditor.OnGUI(rect);
}
void DrawCompareInfo(Rect rect)
{
if (SelectVersion == null)
{
return;
}
GUILayout.BeginArea(rect);
if (SelectCompareVersion == null)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField(Language.NoSelectHistoryCompareVersion);
}
else if (SelectCompareVersion == SelectVersion)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField(Language.NoSelectHistoryCompareOneVersion);
}
else
{
DrawCompareDetails();
}
GUILayout.EndArea();
}
void DrawCompareDetails()
{
EditorGUILayout.Space();
var compareInfo = HistoryUtil.CompareVersion(SelectVersion, SelectCompareVersion);
var simpleData = compareInfo.SimpleChangeData;
GUILayout.BeginHorizontal();
var strAdd = GetPackageChangeInfo(simpleData.PackageAddBundle);
EditorGUILayout.TextField(Language.HistoryAddBundleCount, strAdd);
if (GUILayout.Button(Language.Copy, GUILayout.Width(50)))
{
EditUtil.CopyToClipBoard(strAdd);
}
GUILayout.EndHorizontal();
EditorGUILayout.Space();
GUILayout.BeginHorizontal();
var strChange = GetPackageChangeInfo(simpleData.PackageChangeBundle);
EditorGUILayout.TextField(Language.HistoryChangeBundleCount, strChange);
if (GUILayout.Button(Language.Copy, GUILayout.Width(50)))
{
EditUtil.CopyToClipBoard(strChange);
}
GUILayout.EndHorizontal();
EditorGUILayout.Space();
GUILayout.BeginHorizontal();
var strRemove = GetPackageChangeInfo(simpleData.PackageRemoveBundle);
EditorGUILayout.TextField(Language.HistoryRemoveBundleCount, strRemove);
if (GUILayout.Button(Language.Copy, GUILayout.Width(50)))
{
EditUtil.CopyToClipBoard(strRemove);
}
GUILayout.EndHorizontal();
EditorGUILayout.Space();
GUILayout.BeginHorizontal();
var strDownload = GetPackageDownloadInfo(simpleData.PackageDownloadSize);
EditorGUILayout.TextField(Language.HistoryDownloadSize, strDownload);
if (GUILayout.Button(Language.Copy, GUILayout.Width(50)))
{
EditUtil.CopyToClipBoard(strDownload);
}
GUILayout.EndHorizontal();
EditorGUILayout.Space();
if (GUILayout.Button(Language.HistoryCompareBuild, GUILayout.Height(40)))
{
var saveJson =
JsonConvert.SerializeObject(compareInfo,
Formatting.Indented); //JsonUtility.ToJson(compareInfo, true);
var saveFolder =
EditorUtility.OpenFolderPanel(Language.BuildProfilerTips, Environment.CurrentDirectory, "");
var savePath = $"{saveFolder}/history_compare_{DateTime.Now.ToString("yyyyMMddHHmmss")}.json";
File.WriteAllText(savePath, saveJson);
EditorUtility.DisplayDialog(Language.Tips, Language.Success + $", path={savePath}", Language.Confirm);
}
}
string GetPackageChangeInfo(Dictionary<string, List<string>> dictionary)
{
var all = 0;
var packageStr = "";
var index = 0;
foreach (var key in dictionary.Keys)
{
index++;
var value = dictionary[key];
all += value.Count;
packageStr += $"{key}={value.Count}";
if (index < dictionary.Count)
{
packageStr += "、 ";
}
}
var str = string.Format(Language.HistoryBundleChangeTitle, all, packageStr);
return str;
}
string GetPackageDownloadInfo(Dictionary<string, long> dictionary)
{
long all = 0;
var packageStr = "";
var index = 0;
foreach (var key in dictionary.Keys)
{
index++;
var value = dictionary[key];
all += value;
packageStr += $"{key}={Util.GetFriendlySize(value)}";
if (index < dictionary.Count)
{
packageStr += "、 ";
}
}
var str = string.Format(Language.HistoryBundleChangeTitle, Util.GetFriendlySize(all), packageStr);
return str;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c688eedf74e6448b950e6975f675b3b1
timeCreated: 1680142237

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3a69a28535dc4e99b1b9bdf70b380d4d
timeCreated: 1680143027

View File

@@ -0,0 +1,230 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace NBC.Asset.Editor
{
public sealed class HistoryBundleViewItem : TreeViewItem
{
private BundleData _bundle;
public BundleData Bundle => _bundle;
public HistoryBundleViewItem(int id, BundleData bundle) : base(id, id, bundle.Name)
{
_bundle = bundle;
}
}
public class HistoryBundleTreeEditor : TreeView
{
public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState()
{
return new MultiColumnHeaderState(GetColumns());
}
private static MultiColumnHeaderState.Column[] GetColumns()
{
List<MultiColumnHeaderState.Column> retVal = new List<MultiColumnHeaderState.Column>();
retVal.Add(EditUtil.GetMultiColumnHeaderColumn(Language.HistoryBundleName, 260));
retVal.Add(EditUtil.GetMultiColumnHeaderColumn(Language.HistorySize, 70, 50, 100));
retVal.Add(EditUtil.GetMultiColumnHeaderColumn(Language.HistoryHash, 240,200,300));
return retVal.ToArray();
}
enum MyColumns
{
BundleName,
Size,
Hash,
}
/// <summary>
/// 当前选中了
/// </summary>
private bool _contextOnItem = false;
HistoryWindow _window;
public MultiColumnHeaderState HeaderState;
public HistoryBundleTreeEditor(TreeViewState state, HistoryWindow window, MultiColumnHeaderState header) :
base(state,
new MultiColumnHeader(header))
{
_window = window;
HeaderState = header;
showBorder = true;
showAlternatingRowBackgrounds = true;
Reload();
}
private TreeViewItem _root = null;
protected override TreeViewItem BuildRoot()
{
_root = new TreeViewItem
{
id = -1,
depth = -1,
children = new List<TreeViewItem>()
};
int id = 0;
if (_window.SelectVersion != null)
{
List<BundleData> list = new List<BundleData>();
foreach (var package in _window.SelectVersion.Packages)
{
list.AddRange(package.Bundles);
}
foreach (var bundle in list)
{
id++;
var t = new HistoryBundleViewItem(id, bundle);
_root.AddChild(t);
}
}
return _root;
}
#region
public override void OnGUI(Rect rect)
{
base.OnGUI(rect);
HeaderState.AutoWidth(rect.width, 0);
if (UnityEngine.Event.current.type == EventType.MouseDown && UnityEngine.Event.current.button == 0 &&
rect.Contains(UnityEngine.Event.current.mousePosition))
{
SetSelection(Array.Empty<int>(), TreeViewSelectionOptions.FireSelectionChanged);
}
}
protected override void RowGUI(RowGUIArgs args)
{
for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
{
CellGUI(args.GetCellRect(i), args.item, args.GetColumn(i), ref args);
}
}
private void CellGUI(Rect cellRect, TreeViewItem item, int column, ref RowGUIArgs args)
{
HistoryBundleViewItem bundleTreeViewItem = item as HistoryBundleViewItem;
if (bundleTreeViewItem == null) return;
var bundleData = bundleTreeViewItem.Bundle;
Color oldColor = GUI.color;
CenterRectUsingSingleLineHeight(ref cellRect);
// if (!File.Exists(assetData.Path))
// {
// GUI.color = Color.red;
// }
switch ((MyColumns)column)
{
case MyColumns.BundleName:
EditorGUI.LabelField(cellRect, bundleData.Name);
break;
case MyColumns.Hash:
EditorGUI.LabelField(cellRect, bundleData.Hash);
break;
case MyColumns.Size:
EditorGUI.LabelField(cellRect, Util.GetFriendlySize(bundleData.Size), GUITools.DefLabelStyle);
break;
}
GUI.color = oldColor;
}
#endregion
#region
/// <summary>
/// 点击的时候
/// </summary>
protected override void ContextClicked()
{
if (HasSelection())
{
_contextOnItem = false;
}
}
protected override void DoubleClickedItem(int id)
{
if (FindItem(id, rootItem) is AssetTreeViewItem assetItem)
{
UnityEngine.Object o = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetItem.Asset.Path);
EditorGUIUtility.PingObject(o);
Selection.activeObject = o;
}
}
protected override void ContextClickedItem(int id)
{
if (_contextOnItem)
{
_contextOnItem = false;
return;
}
_contextOnItem = true;
List<int> selectedNodes = new List<int>();
foreach (var nodeID in GetSelection())
{
selectedNodes.Add(nodeID);
}
GenericMenu menu = new GenericMenu();
if (selectedNodes.Count == 1)
{
menu.AddItem(new GUIContent(Language.CopyPath), false, CopyPath, selectedNodes);
menu.AddItem(new GUIContent(Language.CopyAddressPath), false, CopyAddressPath, selectedNodes);
}
menu.ShowAsContext();
}
#endregion
#region
private void CopyAddressPath(object context)
{
if (context is List<int> selectedNodes && selectedNodes.Count > 0)
{
TreeViewItem item = FindItem(selectedNodes[0], rootItem);
if (item is AssetTreeViewItem assetTreeViewItem)
{
EditUtil.CopyToClipBoard(assetTreeViewItem.Asset.Address);
Debug.Log($"copy success{assetTreeViewItem.Asset.Address}");
}
}
}
private void CopyPath(object context)
{
if (context is List<int> selectedNodes && selectedNodes.Count > 0)
{
TreeViewItem item = FindItem(selectedNodes[0], rootItem);
if (item is AssetTreeViewItem assetTreeViewItem)
{
EditUtil.CopyToClipBoard(assetTreeViewItem.Asset.Path);
Debug.Log($"copy success{assetTreeViewItem.Asset.Path}");
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: de6b7df37676439d8f14de84f5028069
timeCreated: 1680146377

View File

@@ -0,0 +1,328 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace NBC.Asset.Editor
{
public class HistoryVersionTreeViewItem : TreeViewItem
{
private VersionHistoryData _version;
public VersionHistoryData Version => _version;
public HistoryVersionTreeViewItem(int id, VersionHistoryData version) : base(id, id, version.ShowName)
{
_version = version;
}
}
public class HistoryVersionTreeEditor : TreeView
{
public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState()
{
return new MultiColumnHeaderState(GetColumns());
}
private static MultiColumnHeaderState.Column[] GetColumns()
{
List<MultiColumnHeaderState.Column> retVal = new List<MultiColumnHeaderState.Column>();
var fist = EditUtil.GetMultiColumnHeaderColumn(Language.HistoryVersionName, 200, 200, 1000);
retVal.Add(fist);
return retVal.ToArray();
}
/// <summary>
/// 当前选中了
/// </summary>
private bool _contextOnItem = false;
HistoryWindow _window;
public MultiColumnHeaderState HeaderState;
public HistoryVersionTreeEditor(TreeViewState state, HistoryWindow window, MultiColumnHeaderState header) :
base(state,
new MultiColumnHeader(header))
{
_window = window;
HeaderState = header;
showBorder = true;
showAlternatingRowBackgrounds = true;
Reload();
}
private TreeViewItem _root;
protected override TreeViewItem BuildRoot()
{
_root = new TreeViewItem
{
id = -1,
depth = -1,
children = new List<TreeViewItem>()
};
int id = 0;
if (_window.ShowVersionHistory != null)
{
foreach (var version in _window.ShowVersionHistory)
{
id++;
var t = new HistoryVersionTreeViewItem(id, version);
_root.AddChild(t);
}
}
return _root;
}
internal void Refresh()
{
var selection = GetSelection();
SelectionChanged(selection);
}
#region
public override void OnGUI(Rect rect)
{
base.OnGUI(rect);
HeaderState.AutoWidth(rect.width);
if (Event.current.type == EventType.MouseDown && Event.current.button == 0 &&
rect.Contains(Event.current.mousePosition))
{
SetSelection(Array.Empty<int>(), TreeViewSelectionOptions.FireSelectionChanged);
}
}
/// <summary>
/// 绘制行
/// </summary>
/// <param name="args"></param>
protected override void RowGUI(RowGUIArgs args)
{
for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
{
CellGUI(args.GetCellRect(i), args.item, args.GetColumn(i), ref args);
}
}
private void CellGUI(Rect cellRect, TreeViewItem item, int column, ref RowGUIArgs args)
{
if (item is HistoryVersionTreeViewItem versionTreeViewItem)
{
CenterRectUsingSingleLineHeight(ref cellRect);
if (column == 0)
{
var iconRect = new Rect(cellRect.x + 4, cellRect.y + 1, cellRect.height - 2, cellRect.height - 2);
GUI.DrawTexture(iconRect, Styles.Package, ScaleMode.ScaleToFit);
var nameRect = new Rect(cellRect.x + iconRect.xMax + 1, cellRect.y, cellRect.width - iconRect.width,
cellRect.height);
if (_window.SelectCompareVersion != null &&
_window.SelectCompareVersion.ShowName == item.displayName)
{
DefaultGUI.Label(nameRect, "[√]" + item.displayName, args.selected, args.focused);
}
else
{
DefaultGUI.Label(nameRect, item.displayName, args.selected, args.focused);
}
}
}
}
#endregion
#region
/// <summary>
/// 点击的时候
/// </summary>
protected override void ContextClicked()
{
if (HasSelection())
{
_contextOnItem = false;
return;
}
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent(Language.Refresh), false, o => { _window.Refresh(); }, null);
menu.ShowAsContext();
}
/// <summary>
/// 是否能多选
/// </summary>
/// <param name="item">选中的文件</param>
/// <returns></returns>
protected override bool CanMultiSelect(TreeViewItem item)
{
return false;
}
protected override float GetCustomRowHeight(int row, TreeViewItem item)
{
return 30;
}
protected override void ContextClickedItem(int id)
{
if (_contextOnItem)
{
_contextOnItem = false;
return;
}
_contextOnItem = true;
List<int> selectedNodes = new List<int>();
foreach (var nodeID in GetSelection())
{
selectedNodes.Add(nodeID);
}
GenericMenu menu = new GenericMenu();
if (selectedNodes.Count == 1)
{
var index = selectedNodes[0] - 1;
var select = false;
if (_window.SelectCompareVersion != null && _window.ShowVersionHistory != null)
{
if (_window.ShowVersionHistory.Count > index)
{
var version = _window.ShowVersionHistory[index];
if (version != null)
{
if (version.ShowName == _window.SelectCompareVersion.ShowName)
{
select = true;
}
}
}
}
if (select)
{
menu.AddItem(new GUIContent(Language.HistoryUnSelectCompare), false, HistoryUnSelectCompare,
selectedNodes);
}
else
{
menu.AddItem(new GUIContent(Language.HistorySelectCompare), false, HistorySelectCompare,
selectedNodes);
}
menu.AddItem(new GUIContent(Language.HistoryUse), false, HistoryUse,
selectedNodes);
menu.AddItem(new GUIContent(Language.HistoryCopyToFolder), false, HistoryCopyToFolder,
selectedNodes);
menu.AddItem(new GUIContent(Language.HistoryDelete), false, HistoryDelete,
selectedNodes);
}
menu.ShowAsContext();
}
#endregion
#region
protected override void SelectionChanged(IList<int> selectedIds)
{
var selectedBundles = new List<string>();
foreach (var id in selectedIds)
{
var item = FindItem(id, rootItem);
if (item != null)
selectedBundles.Add(item.displayName);
}
_window.UpdateSelectedVersion(selectedBundles.Count > 0 ? selectedBundles[0] : string.Empty);
}
private void HistoryUse(object context)
{
if (context is List<int> selectedNodes && selectedNodes.Count > 0)
{
TreeViewItem item = FindItem(selectedNodes[0], rootItem);
if (item is HistoryVersionTreeViewItem versionTreeViewItem)
{
versionTreeViewItem.Version?.CopyToStreamingAssets();
EditorUtility.DisplayDialog(Language.Tips, Language.Success, Language.Confirm);
}
}
}
private void HistoryCopyToFolder(object context)
{
if (context is List<int> selectedNodes && selectedNodes.Count > 0)
{
TreeViewItem item = FindItem(selectedNodes[0], rootItem);
if (item is HistoryVersionTreeViewItem versionTreeViewItem)
{
var saveFolder =
EditorUtility.OpenFolderPanel(Language.BuildProfilerTips, Environment.CurrentDirectory, "");
versionTreeViewItem.Version?.CopyToFolder(saveFolder + "/");
EditorUtility.DisplayDialog(Language.Tips, Language.Success + $", path:{saveFolder}",
Language.Confirm);
}
}
}
private void HistoryDelete(object context)
{
if (context is List<int> selectedNodes && selectedNodes.Count > 0)
{
TreeViewItem item = FindItem(selectedNodes[0], rootItem);
if (item is HistoryVersionTreeViewItem versionTreeViewItem)
{
if (versionTreeViewItem.Version != null)
{
HistoryUtil.DeleteHistoryVersions(versionTreeViewItem.Version.FileName);
_window.Refresh();
}
}
}
}
private void HistorySelectCompare(object context)
{
if (context is List<int> selectedNodes && selectedNodes.Count > 0)
{
TreeViewItem item = FindItem(selectedNodes[0], rootItem);
if (item is HistoryVersionTreeViewItem versionTreeViewItem)
{
if (versionTreeViewItem.Version != null)
{
_window.UpdateCompareSelectedVersion(versionTreeViewItem.Version.ShowName);
}
}
}
}
private void HistoryUnSelectCompare(object context)
{
if (_window.SelectCompareVersion == null) return;
if (context is List<int> selectedNodes && selectedNodes.Count > 0)
{
TreeViewItem item = FindItem(selectedNodes[0], rootItem);
if (item is HistoryVersionTreeViewItem versionTreeViewItem)
{
var v = versionTreeViewItem.Version;
if (v != null && _window.SelectCompareVersion.ShowName == v.ShowName)
{
_window.UpdateCompareSelectedVersion(string.Empty);
}
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0ee881dcc31542749793be9f5a205289
timeCreated: 1680143063