using UnityEditor; using UnityEngine; using System.IO; using System.Text; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using GameLogic; public class Packager { public static string platform = string.Empty; static List paths = new List(); static List files = new List(); static List maps = new List(); ///----------------------------------------------------------- static string[] exts = { ".txt", ".xml", ".lua", ".assetbundle", ".json" }; static bool CanCopy(string ext) { //能不能复制 foreach (string e in exts) { if (ext.Equals(e)) return true; } return false; } /// /// 载入素材 /// static UnityEngine.Object LoadAsset(string file) { if (file.EndsWith(".lua")) file += ".txt"; return AssetDatabase.LoadMainAssetAtPath("Assets/LuaFramework/Examples/Builds/" + file); } [MenuItem("LuaFramework/Build iPhone Resource", false, 100)] public static void BuildiPhoneResource() { BuildTarget target; #if UNITY_5_0 target = BuildTarget.iOS; #else target = BuildTarget.iOS; #endif BuildAssetResource(target); } [MenuItem("LuaFramework/Build Android Resource", false, 101)] public static void BuildAndroidResource() { BuildAssetResource(BuildTarget.Android); } [MenuItem("LuaFramework/Build Windows Resource", false, 102)] public static void BuildWindowsResource() { BuildAssetResource(BuildTarget.StandaloneWindows); } /// /// 生成绑定素材 /// public static void BuildAssetResource(BuildTarget target) { if (Directory.Exists(Util.DataPath)) { Directory.Delete(Util.DataPath, true); } string streamPath = Application.streamingAssetsPath; if (Directory.Exists(streamPath)) { Directory.Delete(streamPath, true); } Directory.CreateDirectory(streamPath); AssetDatabase.Refresh(); maps.Clear(); if (AppConst.luaBundleMode) { HandleLuaBundle(); } else { HandleLuaFile(); } if (AppConst.ExampleMode) { HandleExampleBundle(); } string resPath = "Assets/" + AppConst.AssetDir; BuildPipeline.BuildAssetBundles(resPath, maps.ToArray(), BuildAssetBundleOptions.None, target); BuildFileIndex(); string streamDir = Application.dataPath + "/" + AppConst.LuaTempDir; if (Directory.Exists(streamDir)) Directory.Delete(streamDir, true); AssetDatabase.Refresh(); } static void AddBuildMap(string bundleName, string pattern, string path) { string[] files = Directory.GetFiles(path, pattern); if (files.Length == 0) return; for (int i = 0; i < files.Length; i++) { files[i] = files[i].Replace('\\', '/'); } AssetBundleBuild build = new AssetBundleBuild(); build.assetBundleName = bundleName; build.assetNames = files; maps.Add(build); } /// /// 处理Lua代码包 /// static void HandleLuaBundle() { string streamDir = Application.dataPath + "/" + AppConst.LuaTempDir; if (!Directory.Exists(streamDir)) Directory.CreateDirectory(streamDir); string[] srcDirs = { CustomSettings.baseLuaDir, CustomSettings.baseLuaDir + "/ToLua/Lua" }; for (int i = 0; i < srcDirs.Length; i++) { if (AppConst.LuaByteMode) { string sourceDir = srcDirs[i]; string[] files = Directory.GetFiles(sourceDir, "*.lua", SearchOption.AllDirectories); int len = sourceDir.Length; if (sourceDir[len - 1] == '/' || sourceDir[len - 1] == '\\') { --len; } for (int j = 0; j < files.Length; j++) { string str = files[j].Remove(0, len); string dest = streamDir + str + ".bytes"; string dir = Path.GetDirectoryName(dest); Directory.CreateDirectory(dir); EncodeLuaFile(files[j], dest); } } else { ToLuaMenu.CopyLuaBytesFiles(srcDirs[i], streamDir); } } string[] dirs = Directory.GetDirectories(streamDir, "*", SearchOption.AllDirectories); for (int i = 0; i < dirs.Length; i++) { string name = dirs[i].Replace(streamDir, string.Empty); name = name.Replace('\\', '_').Replace('/', '_'); name = "lua/lua_" + name.ToLower() + AppConst.ExtName; string path = "Assets" + dirs[i].Replace(Application.dataPath, ""); AddBuildMap(name, "*.bytes", path); } AddBuildMap("lua/lua" + AppConst.ExtName, "*.bytes", "Assets/" + AppConst.LuaTempDir); //-------------------------------处理非Lua文件---------------------------------- string luaPath = AppDataPath + "/StreamingAssets/lua/"; for (int i = 0; i < srcDirs.Length; i++) { paths.Clear(); files.Clear(); string luaDataPath = srcDirs[i].ToLower(); Recursive(luaDataPath); foreach (string f in files) { if (f.EndsWith(".meta") || f.EndsWith(".lua")) continue; string newfile = f.Replace(luaDataPath, ""); string path = Path.GetDirectoryName(luaPath + newfile); if (!Directory.Exists(path)) Directory.CreateDirectory(path); string destfile = path + "/" + Path.GetFileName(f); File.Copy(f, destfile, true); } } AssetDatabase.Refresh(); } /// /// 处理框架实例包 /// static void HandleExampleBundle() { string resPath = AppDataPath + "/" + AppConst.AssetDir + "/"; if (!Directory.Exists(resPath)) Directory.CreateDirectory(resPath); AddBuildMap("prompt" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Prompt"); AddBuildMap("message" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Message"); AddBuildMap("prompt_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Prompt"); AddBuildMap("shared_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Shared"); } /// /// 处理Lua文件 /// static void HandleLuaFile() { string resPath = AppDataPath + "/StreamingAssets/"; string luaPath = resPath + "/lua/"; //----------复制Lua文件---------------- if (!Directory.Exists(luaPath)) { Directory.CreateDirectory(luaPath); } string[] luaPaths = { AppDataPath + "/LuaFramework/lua/", AppDataPath + "/LuaFramework/Tolua/Lua/" }; for (int i = 0; i < luaPaths.Length; i++) { paths.Clear(); files.Clear(); string luaDataPath = luaPaths[i].ToLower(); Recursive(luaDataPath); int n = 0; foreach (string f in files) { if (f.EndsWith(".meta")) continue; string newfile = f.Replace(luaDataPath, ""); string newpath = luaPath + newfile; string path = Path.GetDirectoryName(newpath); if (!Directory.Exists(path)) Directory.CreateDirectory(path); if (File.Exists(newpath)) { File.Delete(newpath); } if (AppConst.LuaByteMode) { EncodeLuaFile(f, newpath); } else { File.Copy(f, newpath, true); } UpdateProgress(n++, files.Count, newpath); } } EditorUtility.ClearProgressBar(); AssetDatabase.Refresh(); } static void BuildFileIndex() { string resPath = AppDataPath + "/StreamingAssets/"; ///----------------------创建文件列表----------------------- string newFilePath = resPath + "/files.txt"; if (File.Exists(newFilePath)) File.Delete(newFilePath); paths.Clear(); files.Clear(); Recursive(resPath); FileStream fs = new FileStream(newFilePath, FileMode.CreateNew); StreamWriter sw = new StreamWriter(fs); for (int i = 0; i < files.Count; i++) { string file = files[i]; string ext = Path.GetExtension(file); if (file.EndsWith(".meta") || file.Contains(".DS_Store")) continue; string md5 = Util.md5file(file); string value = file.Replace(resPath, string.Empty); sw.WriteLine(value + "|" + md5); } sw.Close(); fs.Close(); } /// /// 数据目录 /// static string AppDataPath { get { return Application.dataPath.ToLower(); } } /// /// 遍历目录及其子目录 /// static void Recursive(string path) { string[] names = Directory.GetFiles(path); string[] dirs = Directory.GetDirectories(path); foreach (string filename in names) { string ext = Path.GetExtension(filename); if (ext.Equals(".meta")) continue; files.Add(filename.Replace('\\', '/')); } foreach (string dir in dirs) { paths.Add(dir.Replace('\\', '/')); Recursive(dir); } } static void UpdateProgress(int progress, int progressMax, string desc) { string title = "Processing...[" + progress + " - " + progressMax + "]"; float value = (float)progress / (float)progressMax; EditorUtility.DisplayProgressBar(title, desc, value); } public static void EncodeLuaFile(string srcFile, string outFile) { if (!srcFile.ToLower().EndsWith(".lua")) { File.Copy(srcFile, outFile, true); return; } bool isWin = true; string luaexe = string.Empty; string args = string.Empty; string exedir = string.Empty; if (Application.platform == RuntimePlatform.WindowsEditor) { isWin = true; // 32位luagit args = "-b -g " + srcFile + " " + outFile; exedir = AppDataPath.Replace("assets", "") + "LuaEncoder/luajit/"; luaexe = "luajit.exe"; ProcessStartInfo info = new ProcessStartInfo(); info.FileName = luaexe; info.Arguments = args; info.WindowStyle = ProcessWindowStyle.Hidden; info.UseShellExecute = isWin; info.WorkingDirectory = exedir; Process pro = Process.Start(info); pro.Close(); // 64位luagit string outFile_64 = outFile.Replace(".bytes", "%64.bytes");// 文件名后缀添加64 args = "-b -g " + srcFile + " " + outFile_64; exedir = AppDataPath.Replace("assets", "") + "LuaEncoder/luajit_x64/"; luaexe = "luajit.exe"; ProcessStartInfo info_x64 = new ProcessStartInfo(); info_x64.FileName = luaexe; info_x64.Arguments = args; info_x64.WindowStyle = ProcessWindowStyle.Hidden; info_x64.UseShellExecute = isWin; info_x64.WorkingDirectory = exedir; Process pro_x64 = Process.Start(info_x64); pro_x64.Close(); } else if (Application.platform == RuntimePlatform.OSXEditor) { isWin = false; args = "-b -g " + srcFile + " " + outFile; exedir = AppDataPath.Replace("assets", "") + "LuaEncoder/luajit_mac/"; luaexe = exedir + "luajit"; ProcessStartInfo info = new ProcessStartInfo(); info.FileName = luaexe; info.Arguments = args; info.WindowStyle = ProcessWindowStyle.Hidden; info.UseShellExecute = isWin; info.WorkingDirectory = exedir; Process pro = Process.Start(info); pro.Close(); } } [MenuItem("LuaFramework/Build Protobuf-lua-gen File")] public static void BuildProtobufFile() { if (!AppConst.ExampleMode) { UnityEngine.Debug.LogError("若使用编码Protobuf-lua-gen功能,需要自己配置外部环境!!"); return; } string dir = AppDataPath + "/Lua/3rd/pblua"; paths.Clear(); files.Clear(); Recursive(dir); string protoc = "d:/protobuf-2.4.1/src/protoc.exe"; string protoc_gen_dir = "\"d:/protoc-gen-lua/plugin/protoc-gen-lua.bat\""; foreach (string f in files) { string name = Path.GetFileName(f); string ext = Path.GetExtension(f); if (!ext.Equals(".proto")) continue; ProcessStartInfo info = new ProcessStartInfo(); info.FileName = protoc; info.Arguments = " --lua_out=./ --plugin=protoc-gen-lua=" + protoc_gen_dir + " " + name; info.WindowStyle = ProcessWindowStyle.Hidden; info.UseShellExecute = true; info.WorkingDirectory = dir; info.ErrorDialog = true; Util.Log(info.FileName + " " + info.Arguments); Process pro = Process.Start(info); pro.WaitForExit(); } AssetDatabase.Refresh(); } }