283 lines
11 KiB
C#
283 lines
11 KiB
C#
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());
|
||
}
|
||
} |