EditorConfigExporter.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. using UnityEditor;
  2. using UnityEngine;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using Excel;
  7. using System.Data;
  8. using System.Xml;
  9. public class EditorConfigExporter : EditorWindow
  10. {
  11. [MenuItem("DashGame/Design Tools/Export Config")]
  12. public static void AddWindow()
  13. {
  14. Rect wr = new Rect(0, 0, 350, 220);
  15. EditorConfigExporter window = (EditorConfigExporter)EditorWindow.GetWindowWithRect(typeof(EditorConfigExporter), wr, false, "Export Config");
  16. window.Show();
  17. }
  18. public List<string> nameArray = new List<string>();
  19. private string defaultPath;
  20. private bool shouldDelete = true, ignoreSameVersion = true;
  21. private bool isSuccess;
  22. private string text;
  23. private List<string> idArr;
  24. private Dictionary<string, string> md5Dict;
  25. void Awake()
  26. {
  27. defaultPath = Application.dataPath + @"/XlsxSource";
  28. if (!Directory.Exists(defaultPath))
  29. Directory.CreateDirectory(defaultPath);
  30. GetObjectNameToArray<string>(defaultPath, "xlsx");
  31. }
  32. void OnGUI()
  33. {
  34. EditorGUI.LabelField(new Rect(90, 50, 200, 16), new GUIContent("导出所有配置文件到xml目录"));
  35. shouldDelete = EditorGUI.Toggle(new Rect(90, 80, 200, 16), new GUIContent("覆盖已有文件"), shouldDelete);
  36. ignoreSameVersion = EditorGUI.Toggle(new Rect(90, 100, 200, 16), new GUIContent("忽略相同版本"), ignoreSameVersion);
  37. EditorGUI.LabelField(new Rect(2, 200, 350, 16), new GUIContent("Chongqing DashGame Tech. Co.,Ltd, gsgundam, v0.1.0"));
  38. if (GUI.Button(new Rect(50, 135, 250, 40), "立即导出"))
  39. CreateAllXml();
  40. }
  41. /// <summary>
  42. /// Return all files' name in target path in Assets//
  43. /// </summary>
  44. /// <returns>File name in array</returns>
  45. /// <param name="path">Assets sublevel path</param>
  46. /// <param name="pattern">File type filter</param>
  47. /// <typeparam name="T">Class name</typeparam>
  48. void GetObjectNameToArray<T>(string path, string pattern, string subDirectory = "")
  49. {
  50. try
  51. {
  52. //return file name by array in target folder & subfolder, it can be null
  53. string[] files = Directory.GetFiles(path);
  54. for (int i = 0; i < files.Length; i++)
  55. {
  56. string p = files[i];
  57. //file
  58. int index = p.LastIndexOf("\\");
  59. //string folder = p.Substring(0, index + 1); //todo 取消注释
  60. string fileName = p.Substring(index + 1);
  61. //if directoryEntries is not null, tempPaths cannot be null after splited
  62. if (fileName.EndsWith(".meta"))
  63. continue;
  64. string[] pathSplit = StringExtention.SplitWithString(fileName, ".");
  65. if (pathSplit.Length > 1)
  66. {
  67. nameArray.Add(subDirectory + "\\" + pathSplit[0]);
  68. }
  69. }
  70. //recursion
  71. string[] folders = Directory.GetDirectories(path);
  72. for (int i = 0; i < folders.Length; i++)
  73. {
  74. string p = folders[i];
  75. GetObjectNameToArray<T>(p, pattern, p.Substring(defaultPath.Length));
  76. }
  77. }
  78. catch (System.IO.DirectoryNotFoundException)
  79. {
  80. Debug.Log("The path encapsulated in the " + path + "Directory object does not exist.");
  81. }
  82. }
  83. /// <summary>
  84. /// custom split string function
  85. /// </summary>
  86. private class StringExtention
  87. {
  88. public static string[] SplitWithString(string sourceString, string splitString)
  89. {
  90. //string tempSourceString = sourceString; //todo 取消注释
  91. List<string> arrayList = new List<string>();
  92. string s = string.Empty;
  93. while (sourceString.IndexOf(splitString) > -1) //split
  94. {
  95. s = sourceString.Substring(0, sourceString.IndexOf(splitString));
  96. sourceString = sourceString.Substring(sourceString.IndexOf(splitString) + splitString.Length);
  97. arrayList.Add(s);
  98. }
  99. arrayList.Add(sourceString);
  100. return arrayList.ToArray();
  101. }
  102. }
  103. private void CreateAllXml()
  104. {
  105. foreach (string str in nameArray)
  106. {
  107. Debug.Log(str);
  108. if (str.Contains("xlsx_md5") || str.Contains("language"))
  109. continue;
  110. if (ignoreSameVersion)
  111. {
  112. GetMd5Xml(str);
  113. if (!CheckVersion(str))
  114. {
  115. CreateXml(str);
  116. }
  117. }
  118. else
  119. {
  120. CreateXml(str);
  121. }
  122. }
  123. if (isSuccess)
  124. {
  125. ShowNotification(new GUIContent( "已成功导出!"));
  126. DirectoryInfo di = new DirectoryInfo(defaultPath);
  127. DirectoryInfo[] diArr = di.GetDirectories();
  128. for (int i = 0; i < diArr.Length; i++)
  129. CreateMd5XML(diArr[i].ToString() + "/");
  130. AssetDatabase.Refresh();
  131. }
  132. else
  133. ShowNotification(new GUIContent("文件有错误!"));
  134. }
  135. private void CreateXml(string fileName)
  136. {
  137. idArr = new List<string>();
  138. // string filepath = Application.dataPath + @"/Resources/XML/Config" + fileName + ".xml";
  139. string filepath = Application.dataPath + @"/Resources/XML/Config" + fileName + ".xml";
  140. text = "";
  141. filepath = filepath.Replace("\\", "/");
  142. string[] pathArr = filepath.Split('/');
  143. string tempPath = "";
  144. for(int i = 0; i < pathArr.Length; i++)
  145. {
  146. tempPath += pathArr[i] + "/";
  147. if (i > 1 && i < pathArr.Length - 1)
  148. {
  149. if (!Directory.Exists(tempPath))
  150. {
  151. Directory.CreateDirectory(tempPath);
  152. }
  153. }
  154. }
  155. if ((!File.Exists(filepath) && !shouldDelete) || shouldDelete)
  156. {
  157. List<string> labels = new List<string>(); //comments = new List<string>(); //todo 取消注释
  158. XmlDocument xmlDoc = new XmlDocument();
  159. try
  160. {
  161. FileStream stream = File.Open(Application.dataPath + @"/XlsxSource" + fileName + ".xlsx", FileMode.Open, FileAccess.Read);
  162. IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
  163. text += "\nexcelReader.ResultsCount is" + excelReader.ResultsCount + "\n";
  164. text += "start excelReader. \n";
  165. DataSet result = excelReader.AsDataSet();
  166. text += "get result successful? result[" + result + "]";
  167. text += "result columns count is " + result.Tables[0].Columns.Count;
  168. int columns = result.Tables[0].Columns.Count;
  169. int rows = result.Tables[0].Rows.Count;
  170. //start create xml
  171. XmlElement root = xmlDoc.CreateElement("data");
  172. XmlElement comment = xmlDoc.CreateElement("comment");
  173. for (int i = 0; i < rows; i++)
  174. {
  175. XmlElement item = xmlDoc.CreateElement("item");
  176. if (i == 0)
  177. {
  178. continue;
  179. }
  180. for (int j = 0; j < columns; j++)
  181. {
  182. string nvalue = result.Tables[0].Rows[i][j].ToString();
  183. if (i == 1)
  184. {
  185. if (nvalue != null && nvalue != "")
  186. labels.Add(nvalue);
  187. }
  188. else if (i == 2)
  189. {
  190. if (j < labels.Count)
  191. {
  192. XmlElement commentItem = xmlDoc.CreateElement(labels[j]);
  193. commentItem.InnerText = "\n" + nvalue + "\n";
  194. comment.AppendChild(commentItem);
  195. }
  196. }
  197. else if (j < labels.Count)
  198. {
  199. if (fileName.Contains("shop_config"))
  200. nvalue = nvalue.Replace("\n", "");
  201. item.SetAttribute(labels[j], nvalue);
  202. if(j == 0 && !StringUtil.Empty(nvalue))
  203. {
  204. //check duplicate
  205. CheckDuplicate(fileName, nvalue);
  206. idArr.Add(nvalue);
  207. }
  208. //Debug.Log("labels[j] is " + labels[j] + ", nvalue is " + nvalue);
  209. }
  210. //Debug.Log(nvalue);
  211. }
  212. if (i > 2 && item.GetAttribute("id") != "")
  213. {
  214. root.AppendChild(item);
  215. }
  216. }
  217. root.AppendChild(comment);
  218. xmlDoc.AppendChild(root);
  219. xmlDoc.Save(filepath);
  220. AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
  221. // AssetDatabase.ImportAsset(@"Assets/Resources/XML/Config" + fileName + ".xml", ImportAssetOptions.ForceUpdate);
  222. //Debug.Log(fileName + ".xml is saved to " + filepath + ", count is " + idArr.Count);
  223. isSuccess = true;
  224. }
  225. catch (Exception e)
  226. {
  227. text += "Exception " + e.Message;
  228. Debug.Log("Exception " + e.Message);
  229. }
  230. }
  231. }
  232. private void CheckDuplicate(string fileName, string id)
  233. {
  234. if (idArr.Count < 1)
  235. return;
  236. for (int i = 0; i < idArr.Count; i++)
  237. {
  238. if (idArr[i] == id)
  239. Debug.LogError(id + " in " + fileName + " is a duplicate id.");
  240. }
  241. }
  242. private void HideNotification()
  243. {
  244. this.RemoveNotification();
  245. }
  246. private void CreateMd5XML(string sourcePath)
  247. {
  248. DirectoryInfo directoryInfo = new DirectoryInfo(sourcePath);
  249. List<string> pathList = DGFileUtil.GetAllFiles(directoryInfo, ".meta");
  250. XmlDocument xml = CreateMd5XmlDocument(pathList, sourcePath, null, null);
  251. string xmlSavePath = sourcePath + "xlsx_md5.xml";
  252. xml.Save(xmlSavePath);
  253. Debug.Log("Create xlsx xml : " + xmlSavePath);
  254. AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
  255. }
  256. private XmlDocument CreateMd5XmlDocument(List<string> pathList, string pathRoot, List<string> exceptList, string exceptRoot)
  257. {
  258. XmlDocument xml = new XmlDocument();
  259. XmlElement root = xml.CreateElement("xlsx");
  260. xml.AppendChild(root);
  261. for (int i = 0; i < pathList.Count; i++)
  262. {
  263. string assetPath = pathList[i];
  264. string md5 = MD5Util.GetFileHash(assetPath);
  265. string p = assetPath.Substring(pathRoot.Length);
  266. pathList[i] = p;
  267. XmlElement e = xml.CreateElement("a");
  268. XmlAttribute attr = xml.CreateAttribute("p");
  269. attr.Value = p;
  270. e.Attributes.Append(attr);
  271. attr = xml.CreateAttribute("m");
  272. attr.Value = md5;
  273. e.Attributes.Append(attr);
  274. root.AppendChild(e);
  275. }
  276. return xml;
  277. }
  278. private bool CheckVersion(string fileName)
  279. {
  280. if (md5Dict == null || md5Dict.Count < 1)
  281. return false;
  282. else
  283. {
  284. string[] pathArr = StringExtention.SplitWithString(fileName, "\\");
  285. if (pathArr.Length < 3)
  286. return false;
  287. string str = pathArr[2] + ".xlsx";
  288. string md5 = MD5Util.GetFileHash(defaultPath + fileName + ".xlsx");
  289. if (md5Dict.ContainsKey(str) && md5Dict[str] == md5)
  290. {
  291. Debug.Log(pathArr[2] + ".xlsx" + " has same version, ignored");
  292. return true;
  293. }
  294. else
  295. {
  296. if(md5Dict.ContainsKey(str))
  297. Debug.Log(fileName + ": [xml]" + md5Dict[str] + ", [xlsx]" + md5);
  298. else
  299. Debug.Log(fileName + "is new xlsx file, [xlsx]" + md5);
  300. }
  301. return false;
  302. }
  303. }
  304. private void GetMd5Xml(string fileName)
  305. {
  306. string[] pathArr = StringExtention.SplitWithString(fileName, "\\");
  307. string parent = pathArr[1];
  308. string xmlPath = defaultPath + "/" + parent + "/xlsx_md5.xml";
  309. if (!File.Exists(xmlPath))
  310. {
  311. return;
  312. }
  313. StreamReader sr = File.OpenText(xmlPath);
  314. string data = sr.ReadToEnd();
  315. sr.Close();
  316. sr.Dispose();
  317. XmlDocument xml = new XmlDocument();
  318. xml.LoadXml(data);
  319. md5Dict = new Dictionary<string, string>();
  320. XmlNode mapNode = xml.SelectSingleNode("xlsx");
  321. XmlNodeList nodeList = mapNode.SelectNodes("a");
  322. for (int i = 0; i < nodeList.Count; i++)
  323. {
  324. XmlNode node = nodeList[i];
  325. string path = node.Attributes["p"].Value;
  326. string md5 = node.Attributes["m"].Value;
  327. md5Dict.Add(path, md5);
  328. }
  329. }
  330. void OnInspectorUpdate()
  331. {
  332. this.Repaint();
  333. }
  334. void OnDestory()
  335. {
  336. EditorUtility.UnloadUnusedAssetsImmediate();
  337. }
  338. }