Files
JJBB/Assets/Editor/Utilities/DllUtilities.cs

283 lines
11 KiB
C#
Raw Permalink Normal View History

2024-08-23 15:49:34 +08:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
public class DllUtilities : EditorWindow
{
private static string guidPath
{
get { return Application.dataPath.MoveUp().Open("GuidList" + AssetConst.textExtension); }
}
private static string fileIdPath
{
get { return Application.dataPath.MoveUp().Open("FileIdList" + AssetConst.textExtension); }
}
private static string editorProjectRoot
{
get
{
return Application.dataPath.MoveUp().Open("JjbbDll/EditorDll/EditorDll/Code/");
}
}
private static string androidProjectRoot
{
get
{
return Application.dataPath.MoveUp().Open("JjbbDll/AndroidDll/AndroidDll/Code/");
}
}
private void OnGUI()
{
// if (GUILayout.Button("编译组件Guid"))
// BuildGuidFile();
// GUILayout.Space(10f);
// if (GUILayout.Button("编译组件FileId"))
// BuildFileIdFile();
// GUILayout.Space(10f);
if (GUILayout.Button("移动动态库代码"))
{
BuildGuidFile();
BuildFileIdFile();
MoveDllFiles();
}
GUILayout.Space(10f);
if (GUILayout.Button("替换全部组件"))
ReplaceAllComponents();
}
[MenuItem("Bundle V2/Dll Utilities/Open Window")]
public static void Open()
{
GetWindow<DllUtilities>("动态库更新工具");
}
private static Dictionary<string, string> LoadFileAsDictionary(string path)
{
var list = File.ReadAllLines(path);
var result = new Dictionary<string, string>();
foreach (var line in list)
if (!string.IsNullOrEmpty(line))
{
var split = line.Trim().Split(';');
if (split.Length > 1) result[split[0]] = split[1];
}
return result;
}
private static void ReplaceAllComponents()
{
var files = (from assetPath in AssetDatabase.GetAllAssetPaths()
where assetPath.StartsWith(AssetConst.nonInternalHeader)
where !assetPath.StartsWith(AssetConst.csAssetHeader)
where AssetConst.prefabExtension.Equals(Path.GetExtension(assetPath), StringComparison.Ordinal) ||
AssetConst.sceneExtension.Equals(Path.GetExtension(assetPath), StringComparison.Ordinal)
orderby assetPath
select assetPath).ToArray();
var dllGuid = AssetDatabase.AssetPathToGUID("Assets/Project/Dll/JjbbDll.dll");
var guidRegex = new Regex("(?<=guid: ).+?(?=,)");
var fileIdRegex = new Regex("(?<=fileID: )11500000(?=\\D)");
const string header = " m_Script: {fileID: 11500000,";
var guidList = LoadFileAsDictionary(guidPath);
var fileList = LoadFileAsDictionary(fileIdPath);
var convertDict = new Dictionary<string, string>();
foreach (var keyValue in fileList)
{
string guid;
if (guidList.TryGetValue(keyValue.Key, out guid))
convertDict[guid] = keyValue.Value;
}
var count = 0;
for (var i = 0; i < files.Length; i++)
{
EditorUtility.DisplayProgressBar("Replace Components", string.Format("{0} / {1}", i + 1, files.Length),
(float) i / files.Length);
var file = files[i];
var lines = File.ReadAllLines(file);
var dirty = false;
for (var j = 0; j < lines.Length; j++)
{
var line = lines[j];
if (line.Contains(header))
{
var guid = guidRegex.Match(line);
if (guid.Success)
{
var guidValue = guid.Value;
string newFileId;
if (convertDict.TryGetValue(guidValue, out newFileId))
{
line = guidRegex.Replace(line, dllGuid);
line = fileIdRegex.Replace(line, newFileId);
lines[j] = line;
dirty = true;
}
else
{
var assetPath = AssetDatabase.GUIDToAssetPath(guidValue);
if (string.IsNullOrEmpty(assetPath))
Debug.LogWarning(string.Format("Empty component found at file: {0}!", file));
else if (IsProjectPath(assetPath) && IsProjectPath(file))
Debug.LogError(string.Format("Unable to found guid {0} at assetPath {1} at file {2}!", guidValue, assetPath, file));
}
}
else
{
Debug.LogError(string.Format("Unable to match line {0} with guid Regex!", line));
}
}
}
if (dirty)
{
count++;
var builder = new StringBuilder();
for (var j = 0; j < lines.Length; j++)
{
var line = lines[j];
if (j > 0)
builder.Append('\n');
builder.Append(line);
}
File.WriteAllText(file, builder.ToString());
}
}
EditorUtility.ClearProgressBar();
Debug.LogWarning(string.Format("Total Conversion: {0}!", count));
}
private static void CopyCodeToTarget(string assetPath, string targetProject)
{
assetPath = assetPath.Substring("Assets/".Length);
var source = Application.dataPath.Open(assetPath);
var target = targetProject.Open(assetPath);
var dir = Path.GetDirectoryName(target);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
File.Copy(source, target);
}
private static void MoveDllFiles()
{
var assetPaths = (from assetPath in AssetDatabase.GetAllAssetPaths()
where assetPath.StartsWith(AssetConst.nonInternalHeader)
// 注CsAsset里面会有特殊的初始化器将会处于Android的非动态库Assembly中用于驱动动态库
where IsProjectPath(assetPath) && !assetPath.StartsWith(AssetConst.csAssetHeader)
where ".cs".Equals(Path.GetExtension(assetPath), StringComparison.Ordinal)
orderby assetPath
select assetPath).ToArray();
for (var i = 0; i < assetPaths.Length; i++)
{
EditorUtility.DisplayProgressBar("Copy Files",
string.Format("{0} / {1}", i + 1, assetPaths.Length),
(float) i / assetPaths.Length);
CopyCodeToTarget(assetPaths[i], editorProjectRoot);
CopyCodeToTarget(assetPaths[i], androidProjectRoot);
}
for (var i = 0; i < assetPaths.Length; i++)
{
EditorUtility.DisplayProgressBar("Delete Files",
string.Format("{0} / {1}", i + 1, assetPaths.Length),
(float) i / assetPaths.Length);
var source = EditorCommonUtility.AssetToFilePath(assetPaths[i]);
File.Delete(source);
source += AssetConst.metaExtension;
if (File.Exists(source))
File.Delete(source);
}
EditorUtility.ClearProgressBar();
}
private static void BuildFileIdFile()
{
var assembly = Assembly.GetAssembly(typeof(LoginUILogic));
var types = assembly.GetTypes().Where(a => a.IsSubclassOf(typeof(MonoBehaviour))).ToArray();
var builder = new StringBuilder();
for (var i = 0; i < types.Length; i++)
{
EditorUtility.DisplayProgressBar("Compute FileId",
string.Format("{0} / {1}", i + 1, types.Length),
(float) i / types.Length);
var type = types[i];
var fileId = FileIdUtility.Compute(type);
var name = type.FullName;
var dot = name.LastIndexOf('.');
if (dot > 0)
name = name.Substring(dot);
builder.AppendLine(string.Format("{0};{1}", name, fileId));
}
EditorUtility.ClearProgressBar();
File.WriteAllText(Application.dataPath.MoveUp().Open("FileIdList.txt"), builder.ToString());
}
private static bool IsProjectPath(string assetPath)
{
return !assetPath.Contains("/Editor/") && !assetPath.Contains("/Plugins/");
}
private static void BuildGuidFile()
{
var allTargets = (from assetPath in AssetDatabase.GetAllAssetPaths()
where assetPath.StartsWith(AssetConst.nonInternalHeader)
where IsProjectPath(assetPath)
where !assetPath.StartsWith("Assets/Project3D/BundleData/")
let extension = Path.GetExtension(assetPath)
where AssetConst.prefabExtension.Equals(extension, StringComparison.Ordinal) ||
AssetConst.sceneExtension.Equals(extension, StringComparison.Ordinal)
select assetPath).ToArray();
var dict = new Dictionary<string, string>();
var guidRegex = new Regex("(?<=guid: ).+?(?=,)");
var failedHash = new HashSet<string>();
for (var i = 0; i < allTargets.Length; i++)
{
EditorUtility.DisplayProgressBar("Create Guid", string.Format("{0} / {1}", i + 1, allTargets.Length),
(float) i / allTargets.Length);
var assetPath = allTargets[i];
var lines = File.ReadAllLines(assetPath);
foreach (var line in lines)
if (line.Contains("m_Script: {fileID: 11500000,"))
{
var match = guidRegex.Match(line);
if (!match.Success)
{
Debug.LogError(string.Format("Unable to match guid on line {0}!", line));
}
else
{
var guid = match.Value;
if (!dict.ContainsKey(guid))
dict[guid] = AssetDatabase.GUIDToAssetPath(guid);
}
}
}
EditorUtility.ClearProgressBar();
var builder = new StringBuilder();
foreach (var keyValue in dict)
if (IsProjectPath(keyValue.Key))
builder.AppendLine(string.Format("{0};{1}", Path.GetFileNameWithoutExtension(keyValue.Value),
keyValue.Key));
File.WriteAllText(guidPath, builder.ToString());
}
}