解決各類漏傳 資源 / 代碼 的疑難雜症.app
由於Unity比較特殊的meta文件系統, 忘傳漏傳文件在後期可能致使重大引用丟失, 將SVN整合進項目勢在必行. TortoiseSVN自帶了命令行工具, 安裝的時候選擇了的話就能用了工具
直接代碼:ui
using UnityEngine; using UnityEditor; using System.Diagnostics; using System.Collections.Generic; namespace MyEditor { public class UnitySVN { private const string Add_CMD = "add"; private const string COMMIT_CMD = "commit"; private const string UPDATE_CMD = "update"; private const string REVERT_CMD = "revert"; private static System.Text.StringBuilder ms_sb = new System.Text.StringBuilder(); #region MenuItem Funcs [MenuItem("Assets/SVN/Update", false, 1001)] public static void SVN_Update() { var paths = GetAssetPathList(); if(paths.Count > 0) { Update(paths: paths.ToArray()); } } [MenuItem("Assets/SVN/Revert", false, 1002)] public static void SVN_Revert() { var paths = GetAssetPathList(); if(paths.Count > 0) { Revert(paths.ToArray()); } } [MenuItem("Assets/SVN/Commit", false, 1003)] public static void SVN_Commit() { var paths = GetAssetPathList(); if(paths.Count > 0) { Commit("UnitySVN Upload", true, paths.ToArray()); } } #endregion #region Wrapped Funcs // add public static void Add(params string[] paths) { WrappedCommadn(Add_CMD, paths, false); } // update public static void Update(params string[] paths) { WrappedCommadn(UPDATE_CMD, paths, false); SaveAndRefresh(); } // revert public static void Revert(params string[] paths) { WrappedCommadn(REVERT_CMD, paths, false); SaveAndRefresh(); } // add->update->commit public static void Commit(string log, bool add = true, params string[] paths) { if(add) { Add(paths); } Update(paths); string extMsg = log ?? string.Empty; WrappedCommadn(command: COMMIT_CMD, paths: paths, newThread: true, extCommand: "/logmsg:\"Auto Upload : " + (extMsg) + "\""); } /// <summary> /// Wrap SVN Command /// </summary> /// <param name="command"></param> /// <param name="path"></param> /// <param name="extCommand"></param> public static void WrappedCommadn(string command, string[] paths, bool newThread = false, string extCommand = null) { if(paths == null || paths.Length == 0) { return; } ms_sb.Append(paths[0]); for(int i = 1; i < paths.Length; i++) { ms_sb.Append("*"); ms_sb.Append(paths[i]); } string cmd = "/c tortoiseproc.exe /command:{0} /path:\"{1}\" {2} /closeonend 2"; string pathString = ms_sb.ToString(); var commandString = string.Format(cmd, command, pathString, extCommand ?? string.Empty); ProcessStartInfo info = new ProcessStartInfo("cmd.exe", commandString); info.WindowStyle = ProcessWindowStyle.Hidden; if(newThread) { System.Threading.ThreadPool.QueueUserWorkItem((_obj) => { RunProcess(info); }); } else { RunProcess(info); } } #endregion #region Help Funcs public static HashSet<string> GetAssets() { HashSet<string> allAssets = new HashSet<string>(); const string BaseFolder = "Assets"; foreach(var obj in Selection.objects) { var assetPath = AssetDatabase.GetAssetPath(obj); List<string> fullDirs = FullDirectories(assetPath, BaseFolder); allAssets.UnionWith(fullDirs); var dps = AssetDatabase.GetDependencies(assetPath, true); foreach(var dp in dps) { if(dp != assetPath) { List<string> dpsDirs = FullDirectories(dp, BaseFolder); allAssets.UnionWith(dpsDirs); } } } return allAssets; } public static List<string> GetAssetPathList() { var path = new List<string>(GetAssets()); path.Sort((_l, _r) => { if(_l.Length > _r.Length) { return 1; } if(_l.Length < _r.Length) { return -1; } return 0; }); return path; } public static void SaveAndRefresh() { AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } public static List<string> FullDirectories(string path, string baseFolder) { List<string> retVal = new List<string>(); retVal.Add(path); retVal.Add(path + ".meta"); baseFolder = baseFolder.Replace("\\", "/"); var dir = System.IO.Path.GetDirectoryName(path).Replace("\\", "/"); while(string.IsNullOrEmpty(dir) == false && dir != baseFolder) { retVal.Add(dir); retVal.Add(dir + ".meta"); dir = System.IO.Path.GetDirectoryName(dir).Replace("\\", "/"); } return retVal; } private static void RunProcess(ProcessStartInfo info) { Process p = null; try { using(p = Process.Start(info)) { p.WaitForExit(); } } catch(System.Exception ex) { UnityEngine.Debug.LogError(@ex.ToString()); if(p != null) { p.Kill(); } } } #endregion } /* / closeonend:0不自動關閉對話框 / closeonend:1會自動關閉,若是沒有錯誤 / closeonend:2會自動關閉,若是沒有發生錯誤和衝突 / closeonend:3會自動關閉,若是沒有錯誤,衝突和合並 / closeonend:4會自動關閉,若是沒有錯誤,衝突和合並 */ }
主要的功能仍是自動上傳功能, 被選中物體的全部關聯引用都會被加入上傳列表, 而且全部文件夾也會被加入, 這樣就保證了Add邏輯不會錯誤.spa