Files
JJBB/Assets/Editor/Utilities/DllUtilities.cs
2024-08-23 15:49:34 +08:00

283 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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());
}
}