首次提交

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,157 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using UnityEngine.Networking;
namespace NBC.Asset.Editor
{
public static class EditUtil
{
public static async Task<string> GetHttpRequest(string url)
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
{
webRequest.SendWebRequest();
while (!webRequest.isDone)
{
await Task.Delay(100);
}
if (!string.IsNullOrEmpty(webRequest.error))
{
Debug.LogError(webRequest.error);
return string.Empty;
}
Debug.Log(webRequest.downloadHandler.text);
return webRequest.downloadHandler.text;
}
}
public static void CopyToClipBoard(string str)
{
TextEditor text2Editor = new TextEditor
{
text = str
};
text2Editor.OnFocus();
text2Editor.Copy();
}
public static string[] GetTagsArr(string tags)
{
if (!string.IsNullOrEmpty(tags))
{
return tags.Split(',');
}
return Array.Empty<string>();
}
public static void CopyToFolder(string filePath, string toPath)
{
if (!File.Exists(filePath)) return;
CreateDirectory(Path.GetDirectoryName(toPath));
if (File.Exists(toPath)) File.Delete(toPath);
File.Copy(filePath, toPath);
}
public static void CreateDirectory(string path)
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
public static T GetAssetOrCreate<T>(string path) where T : ScriptableObject
{
var asset = AssetDatabase.LoadAssetAtPath<T>(path);
if (asset != null) return asset;
var cfgPath = Path.GetDirectoryName(path);
if (!Directory.Exists(cfgPath))
{
Directory.CreateDirectory(cfgPath ?? string.Empty);
}
asset = ScriptableObject.CreateInstance<T>();
AssetDatabase.CreateAsset(asset, path);
AssetDatabase.SaveAssets();
return asset;
}
public static string GetActiveBuildTargetName()
{
switch (EditorUserBuildSettings.activeBuildTarget)
{
case BuildTarget.Android:
return "Android";
case BuildTarget.StandaloneOSX:
return "OSX";
case BuildTarget.StandaloneWindows:
case BuildTarget.StandaloneWindows64:
return "Windows";
case BuildTarget.iOS:
return "iOS";
case BuildTarget.WebGL:
return "WebGL";
case BuildTarget.StandaloneLinux64:
return "Linux";
default:
return "Default";
}
}
#region
public static MultiColumnHeaderState.Column GetMultiColumnHeaderColumn(string name, int width = 100,
int min = 80, int max = 200)
{
var val = new MultiColumnHeaderState.Column
{
headerContent = new GUIContent(name),
minWidth = min,
maxWidth = max,
width = width,
sortedAscending = true,
headerTextAlignment = TextAlignment.Center,
canSort = false,
autoResize = true,
allowToggleVisibility = false
};
return val;
}
#endregion
#region
public static List<Type> FindAllSubclass<T>()
{
var listOfBs = (from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
from assemblyType in domainAssembly.GetTypes()
where typeof(T).IsAssignableFrom(assemblyType)
select assemblyType).ToArray();
List<Type> list = new List<Type>();
foreach (var type in listOfBs)
{
if (type.IsSubclassOf(typeof(T)))
{
list.Add(type);
}
}
return list;
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 829fcd79798b42a3932b7253b48b9738
timeCreated: 1673938309

View File

@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace NBC.Asset.Editor
{
public static class GUITools
{
public static GUIStyle DefLabelStyle = new GUIStyle(GUI.skin.label)
{
richText = true,
alignment = TextAnchor.MiddleCenter
};
public static GUIStyle GetStyle(string styleName)
{
GUIStyle s = GUI.skin.FindStyle(styleName);
if (s == null) s = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle(styleName);
if (s == null)
{
Debug.LogError("Missing built-in gui style: " + styleName);
s = new GUIStyle();
}
return s;
}
public static bool EnumGUILayout(string title, object target, string fieldName)
{
var t = target.GetType();
var field = GetFieldInfo(t, fieldName);
var displayNameInfo = GetDisplayNameInfo(field);
var value = field.GetValue(target);
var newValue = value;
var names = displayNameInfo.Keys.ToList();
var values = displayNameInfo.Values.ToList();
var showName = value.ToString();
var mask = values.FindIndex(n => n.Name == showName);
if (mask < 0) mask = 0;
var newMask = EditorGUILayout.Popup(title, mask, names.ToArray());
if (newMask != mask)
{
var newInfo = values[newMask];
if (newInfo != null)
{
newValue = Enum.Parse(value.GetType(), newInfo.Name, true);
}
}
if (value != newValue)
{
field.SetValue(target, newValue);
return true;
}
return false;
}
private static Dictionary<Type, Dictionary<string, FieldInfo>> _fieldInfoDic =
new Dictionary<Type, Dictionary<string, FieldInfo>>();
private static FieldInfo GetFieldInfo(Type t, string fieldName)
{
//得到字段的值,只能得到public类型的字典的值
FieldInfo[] fieldInfos = t.GetFields();
FieldInfo showFieldInfo = null;
foreach (var fieldInfo in fieldInfos)
{
if (fieldInfo.Name == fieldName)
{
showFieldInfo = fieldInfo;
break;
}
}
if (showFieldInfo != null)
{
if (!_fieldInfoDic.TryGetValue(t, out var dictionary))
{
dictionary = new Dictionary<string, FieldInfo>();
_fieldInfoDic[t] = new Dictionary<string, FieldInfo>();
}
dictionary[fieldName] = showFieldInfo;
}
return showFieldInfo;
}
private static Dictionary<Type, Dictionary<string, FieldInfo>> _displayNameInfoDic =
new Dictionary<Type, Dictionary<string, FieldInfo>>();
private static Dictionary<string, FieldInfo> GetDisplayNameInfo(FieldInfo fieldInfo)
{
var fieldType = fieldInfo.FieldType;
if (_displayNameInfoDic.TryGetValue(fieldType, out var dictionary))
{
return dictionary;
}
var fields = fieldType.GetFields();
Dictionary<string, FieldInfo> showFieldInfos = new Dictionary<string, FieldInfo>();
foreach (var f in fields)
{
if (f.FieldType != fieldType) continue;
var menuNameAttr = f.GetCustomAttribute<DisplayNameAttribute>();
var showName = menuNameAttr != null ? menuNameAttr.showName : f.Name;
showFieldInfos[showName] = f;
}
_displayNameInfoDic[fieldType] = showFieldInfos;
return showFieldInfos;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 20ee641b395e4ba48ba26e0b88fd952a
timeCreated: 1679539111

View File

@@ -0,0 +1,345 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace NBC.Asset.Editor
{
public static class HistoryUtil
{
public static void CopyToStreamingAssets(this VersionHistoryData versionHistory)
{
if (versionHistory == null) return;
try
{
var streamingAssetsPath = $"{Application.streamingAssetsPath}/";
if (Directory.Exists(streamingAssetsPath))
Directory.Delete(streamingAssetsPath, true);
Directory.CreateDirectory(streamingAssetsPath);
versionHistory.CopyToFolder(streamingAssetsPath);
AssetDatabase.Refresh();
}
catch (Exception e)
{
Debug.LogError("copy version is null");
}
}
public static void CopyToFolder(this VersionHistoryData versionHistory, string folderPath)
{
if (!Directory.Exists(folderPath))
{
Debug.LogError("copy errorFolder not exists");
return;
}
var versionData = versionHistory.VersionData;
var versionPackageName = versionData.NameHash;
var filePath = BuildSettings.GetBuildPath(versionPackageName);
EditUtil.CopyToFolder(filePath, folderPath + versionPackageName);
// Const.GetStreamingPath(versionPackageName));
foreach (var package in versionHistory.Packages)
{
foreach (var bundle in package.Bundles)
{
//Const.GetStreamingPath(bundleNameAddHash)
var bundleNameAddHash = Util.NameAddHash(bundle.Name, bundle.Hash);
EditUtil.CopyToFolder(BuildSettings.GetBuildPath(bundleNameAddHash),
folderPath + bundleNameAddHash);
}
}
Util.WriteJson(versionData, folderPath + "version.json"); //Const.GetStreamingPath("version.json"));
}
public static void ShowLastBuildInfo()
{
var last = GetLastBuildCompareVersion();
var simpleData = last.SimpleChangeData;
var addCount = simpleData.PackageAddBundle.Values.Sum(v => v.Count);
var changeCount = simpleData.PackageChangeBundle.Values.Sum(v => v.Count);
var removeCount = simpleData.PackageRemoveBundle.Values.Sum(v => v.Count);
var tips = string.Format(Language.BuildSuccessTips, Util.GetFriendlySize(simpleData.DownloadSize), addCount,
changeCount,
removeCount);
Debug.Log(tips);
EditorUtility.DisplayDialog(Language.Tips, tips, Language.Confirm);
}
/// <summary>
/// 获取最后一次构建和上次构建变化内容
/// </summary>
/// <returns></returns>
public static VersionChangeData GetLastBuildCompareVersion()
{
var versions = GetHistoryVersions();
VersionHistoryData newHistoryData = null;
VersionHistoryData oldHistoryData = null;
if (versions != null)
{
if (versions.Count > 0)
{
newHistoryData = versions[0];
}
if (versions.Count > 1)
{
oldHistoryData = versions[1];
}
}
return CompareVersion(newHistoryData, oldHistoryData);
}
/// <summary>
/// 比较版本相差内容
/// </summary>
/// <param name="newHistoryData">更新的版本</param>
/// <param name="oldHistoryData">更老的版本</param>
public static VersionChangeData CompareVersion(VersionHistoryData newHistoryData,
VersionHistoryData oldHistoryData)
{
List<BundleData> oldBundles = new List<BundleData>();
if (oldHistoryData != null)
{
foreach (var package in oldHistoryData.Packages)
{
foreach (var bundle in package.Bundles)
{
oldBundles.Add(bundle);
}
}
}
List<BundleData> newBundles = new List<BundleData>();
if (newHistoryData != null)
{
foreach (var package in newHistoryData.Packages)
{
foreach (var bundle in package.Bundles)
{
newBundles.Add(bundle);
}
}
}
VersionChangeData ret = new VersionChangeData();
//查找新增和修改的bundle
foreach (var bundle in newBundles)
{
var old = oldBundles.Find(b => b.Name == bundle.Name);
if (old != null)
{
if (old.Hash != bundle.Hash || old.Size != bundle.Size)
{
ret.Change(bundle, VersionChangeData.TypeEnum.Change);
}
}
else
{
ret.Change(bundle, VersionChangeData.TypeEnum.Add);
}
}
//查找删除的bundle
foreach (var bundle in oldBundles)
{
var old = newBundles.Find(b => b.Name == bundle.Name);
if (old == null)
{
ret.Change(bundle, VersionChangeData.TypeEnum.Remove);
}
}
ret.Processing();
ret.NewVersionName = newHistoryData?.ShowName;
ret.OldVersionName = oldHistoryData?.ShowName;
return ret;
}
/// <summary>
/// 获取最后一个历史记录
/// </summary>
/// <returns></returns>
public static VersionHistoryData GetLastVersionHistory()
{
var history = GetHistoryVersions();
if (history != null && history.Count > 0)
{
return history[0];
}
return null;
}
/// <summary>
/// 获取所有历史记录
/// </summary>
public static List<VersionHistoryData> GetHistoryVersions()
{
var platformPath = BuildSettings.PlatformPath;
List<VersionHistoryData> ret = new List<VersionHistoryData>();
DirectoryInfo root = new DirectoryInfo(platformPath);
if (root.Exists)
{
FileInfo[] files = root.GetFiles();
List<string> filePaths = new List<string>();
foreach (var file in files)
{
if (file.Exists)
{
var ext = Path.GetExtension(file.FullName);
var fileName = Path.GetFileName(file.FullName);
if (ext.ToLower() == ".json" && fileName.StartsWith("version"))
{
filePaths.Add(file.FullName);
}
}
}
filePaths.Sort((a, b) =>
{
var fName1 = Path.GetFileNameWithoutExtension(a);
var fName2 = Path.GetFileNameWithoutExtension(b);
var index1 = fName1.Replace("version_", "");
var index2 = fName2.Replace("version_", "");
int.TryParse(index1, out var i1);
int.TryParse(index2, out var i2);
return i1 - i2;
});
filePaths.Reverse();
foreach (var file in filePaths)
{
var json = File.ReadAllText(file);
var versionName = Path.GetFileName(file);
versionName = versionName.Replace(Path.GetExtension(file), "");
var version = JsonUtility.FromJson<VersionData>(json);
if (version == null) continue;
var historyData = new VersionHistoryData();
historyData.VersionData = version;
var showTime = Util.TimestampToTime(version.BuildTime);
historyData.FileName = Path.GetFileName(file);
historyData.ShowName = versionName + "_" + showTime.ToString("yyyy-MM-dd HH:mm:ss");
var fileName = version.NameHash;
var packages = Util.ReadJson<VersionPackageData>(BuildSettings.GetBuildPath(fileName));
if (packages != null)
{
foreach (var packageData in packages.Packages)
{
foreach (var bundle in packageData.Bundles)
{
bundle.PackageName = packageData.Name;
}
historyData.Packages.Add(packageData);
}
}
ret.Add(historyData);
}
}
return ret;
}
/// <summary>
/// 删除某个历史版本记录
/// </summary>
public static void DeleteHistoryVersions(string versionFileName)
{
VersionHistoryData needDeleteVersion = null;
//所有bundle使用次数
Dictionary<string, int> useDic = new Dictionary<string, int>();
var versions = GetHistoryVersions();
foreach (var version in versions)
{
if (version.FileName == versionFileName)
{
needDeleteVersion = version;
}
var fileName = version.VersionData.NameHash;
UseDic(useDic, fileName);
foreach (var p in version.Packages)
{
foreach (var bundle in p.Bundles)
{
var name = bundle.NameHash;
if (useDic.ContainsKey(name))
{
useDic[name]++;
}
else
{
useDic[name] = 1;
}
}
}
}
if (needDeleteVersion != null)
{
List<string> canDeleteBundle = new List<string>();
foreach (var p in needDeleteVersion.Packages)
{
foreach (var bundle in p.Bundles)
{
var name = bundle.NameHash;
if (useDic.TryGetValue(name, out var count))
{
if (count <= 1) canDeleteBundle.Add(name);
}
else
{
canDeleteBundle.Add(name);
}
}
}
var platformPath = BuildSettings.PlatformPath;
DeleteFile($"{platformPath}/{versionFileName}");
var fileName = needDeleteVersion.VersionData.NameHash;
if (useDic.TryGetValue(fileName, out var c))
{
if (c <= 1)
{
DeleteFile($"{platformPath}/{fileName}");
}
}
foreach (var bundleName in canDeleteBundle)
{
DeleteFile($"{platformPath}/{bundleName}");
}
}
}
private static void UseDic(Dictionary<string, int> dic, string name)
{
if (dic.ContainsKey(name))
{
dic[name]++;
}
else
{
dic[name] = 1;
}
}
private static void DeleteFile(string filePath)
{
if (File.Exists(filePath))
{
File.Delete(filePath);
Debug.Log($"Delete File Path:{filePath}");
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fa2414c37f70494ea9cca95f4e2c5f97
timeCreated: 1680143474

View File

@@ -0,0 +1,14 @@
using UnityEditor;
namespace NBC.Asset.Editor
{
public class ImportAsset : AssetPostprocessor
{
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets,
string[] movedAssets,
string[] movedFromAssetPaths)
{
Builder.Gather();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 40584ff21de3482b9f0f65fa046d90b8
timeCreated: 1679478429

View File

@@ -0,0 +1,31 @@
using UnityEditor.IMGUI.Controls;
namespace NBC.Asset.Editor
{
public static class MultiColumnHeaderUtil
{
/// <summary>
/// 自动大小
/// </summary>
/// <param name="headerState"></param>
/// <param name="maxWidth">最大宽</param>
/// <param name="index">自由大小的序号</param>
public static void AutoWidth(this MultiColumnHeaderState headerState, float maxWidth, int index = 0)
{
var columns = headerState.columns;
if (columns == null) return;
var residue = maxWidth - 16;
for (int i = 0; i < columns.Length; i++)
{
var column = columns[i];
if (i != index)
{
residue -= column.width;
}
}
if (residue < 100) residue = 100;
columns[index].width = residue;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e4ce8dc1e9e949e2bbf2f82a9a99c4d7
timeCreated: 1679993977

View File

@@ -0,0 +1,81 @@
using System;
using System.Linq;
using UnityEngine;
namespace NBC.Asset.Editor
{
public class ScriptableSingleton<T> : ScriptableObject where T : ScriptableObject
{
private static T _inst;
public static T Instance
{
get
{
if (!_inst)
{
LoadOrCreate();
}
return _inst;
}
}
public static T Get()
{
return Instance;
}
public static T LoadOrCreate()
{
if (_inst == null)
{
string filePath = GetFilePath();
if (!string.IsNullOrEmpty(filePath))
{
_inst = EditUtil.GetAssetOrCreate<T>(GetFilePath());
}
else
{
Debug.LogError($"{nameof(ScriptableSingleton<T>)}: 请指定单例存档路径! ");
}
}
return _inst;
}
protected static string GetFilePath()
{
return typeof(T).GetCustomAttributes(inherit: true)
.Cast<FilePathAttribute>()
.FirstOrDefault(v => v != null)
?.filePath;
}
}
[AttributeUsage(AttributeTargets.Class)]
public class FilePathAttribute : Attribute
{
internal readonly string filePath;
/// <summary>
/// 单例存放路径
/// </summary>
/// <param name="path">相对 Project 路径</param>
public FilePathAttribute(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentException("Invalid relative path (it is empty)");
}
if (path[0] == '/')
{
path = path.Substring(1);
}
filePath = path;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4e9d02af499955041a242b7bb76b1338
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: