EditorConfigExporter.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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 + @"/Resource/Xlsx";
  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">Tab 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. Debug.Log(subDirectory + "\\" + pathSplit[0]);
  69. }
  70. }
  71. //recursion
  72. string[] folders = Directory.GetDirectories(path);
  73. for (int i = 0; i < folders.Length; i++)
  74. {
  75. string p = folders[i];
  76. GetObjectNameToArray<T>(p, pattern, p.Substring(defaultPath.Length));
  77. }
  78. }
  79. catch (System.IO.DirectoryNotFoundException)
  80. {
  81. Debug.Log("The path encapsulated in the " + path + "Directory object does not exist.");
  82. }
  83. }
  84. /// <summary>
  85. /// custom split string function
  86. /// </summary>
  87. private class StringExtention
  88. {
  89. public static string[] SplitWithString(string sourceString, string splitString)
  90. {
  91. //string tempSourceString = sourceString; //todo 取消注释
  92. List<string> arrayList = new List<string>();
  93. string s = string.Empty;
  94. while (sourceString.IndexOf(splitString) > -1) //split
  95. {
  96. s = sourceString.Substring(0, sourceString.IndexOf(splitString));
  97. sourceString = sourceString.Substring(sourceString.IndexOf(splitString) + splitString.Length);
  98. arrayList.Add(s);
  99. }
  100. arrayList.Add(sourceString);
  101. return arrayList.ToArray();
  102. }
  103. }
  104. private void CreateAllXml()
  105. {
  106. foreach (string str in nameArray)
  107. {
  108. Debug.Log(str);
  109. if (str.Contains("xlsx_md5") || str.Contains("language"))
  110. continue;
  111. if (ignoreSameVersion)
  112. {
  113. GetMd5Xml(str);
  114. if (!CheckVersion(str))
  115. {
  116. CreateXml(str);
  117. }
  118. }
  119. else
  120. {
  121. CreateXml(str);
  122. }
  123. }
  124. if (isSuccess)
  125. {
  126. ShowNotification(new GUIContent( "已成功导出!"));
  127. DirectoryInfo di = new DirectoryInfo(defaultPath);
  128. DirectoryInfo[] diArr = di.GetDirectories();
  129. for (int i = 0; i < diArr.Length; i++)
  130. CreateMd5XML(diArr[i].ToString() + "/");
  131. AssetDatabase.Refresh();
  132. }
  133. else
  134. ShowNotification(new GUIContent("文件有错误!"));
  135. }
  136. private void CreateXml(string fileName)
  137. {
  138. idArr = new List<string>();
  139. // string filepath = Application.dataPath + @"/Resources/XML/Config" + fileName + ".xml";
  140. string filepath = Application.dataPath + @"/Resource/XML/Config" + fileName + ".xml";
  141. text = "";
  142. filepath = filepath.Replace("\\", "/");
  143. string[] pathArr = filepath.Split('/');
  144. string tempPath = "";
  145. for(int i = 0; i < pathArr.Length; i++)
  146. {
  147. tempPath += pathArr[i] + "/";
  148. if (i > 1 && i < pathArr.Length - 1)
  149. {
  150. if (!Directory.Exists(tempPath))
  151. {
  152. Directory.CreateDirectory(tempPath);
  153. }
  154. }
  155. }
  156. if ((!File.Exists(filepath) && !shouldDelete) || shouldDelete)
  157. {
  158. List<string> labels = new List<string>(); //comments = new List<string>(); //todo 取消注释
  159. XmlDocument xmlDoc = new XmlDocument();
  160. try
  161. {
  162. FileStream stream = File.Open(Application.dataPath + @"/Resource/Xlsx" + fileName + ".xlsx", FileMode.Open, FileAccess.Read);
  163. IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
  164. text += "\nexcelReader.ResultsCount is" + excelReader.ResultsCount + "\n";
  165. text += "start excelReader. \n";
  166. DataSet result = excelReader.AsDataSet();
  167. text += "get result successful? result[" + result + "]";
  168. text += "result columns count is " + result.Tables[0].Columns.Count;
  169. int columns = result.Tables[0].Columns.Count;
  170. int rows = result.Tables[0].Rows.Count;
  171. //start create xml
  172. XmlElement root = xmlDoc.CreateElement("data");
  173. XmlElement comment = xmlDoc.CreateElement("comment");
  174. for (int i = 0; i < rows; i++)
  175. {
  176. XmlElement item = xmlDoc.CreateElement("item");
  177. if (i == 0)
  178. {
  179. continue;
  180. }
  181. for (int j = 0; j < columns; j++)
  182. {
  183. string nvalue = result.Tables[0].Rows[i][j].ToString();
  184. if (i == 1)
  185. {
  186. if (nvalue != null && nvalue != "")
  187. labels.Add(nvalue);
  188. }
  189. else if (i == 2)
  190. {
  191. if (j < labels.Count)
  192. {
  193. XmlElement commentItem = xmlDoc.CreateElement(labels[j]);
  194. commentItem.InnerText = "\n" + nvalue + "\n";
  195. comment.AppendChild(commentItem);
  196. }
  197. }
  198. else if (j < labels.Count)
  199. {
  200. if (fileName.Contains("shop_config"))
  201. nvalue = nvalue.Replace("\n", "");
  202. item.SetAttribute(labels[j], nvalue);
  203. if(j == 0 && !StringUtil.Empty(nvalue))
  204. {
  205. //check duplicate
  206. CheckDuplicate(fileName, nvalue);
  207. idArr.Add(nvalue);
  208. }
  209. //Debug.Log("labels[j] is " + labels[j] + ", nvalue is " + nvalue);
  210. }
  211. //Debug.Log(nvalue);
  212. }
  213. if (i > 2 && item.GetAttribute("id") != "")
  214. {
  215. root.AppendChild(item);
  216. }
  217. }
  218. root.AppendChild(comment);
  219. xmlDoc.AppendChild(root);
  220. xmlDoc.Save(filepath);
  221. AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
  222. // AssetDatabase.ImportAsset(@"Assets/Resources/XML/Config" + fileName + ".xml", ImportAssetOptions.ForceUpdate);
  223. //Debug.Log(fileName + ".xml is saved to " + filepath + ", count is " + idArr.Count);
  224. isSuccess = true;
  225. }
  226. catch (Exception e)
  227. {
  228. text += "Exception " + e.Message;
  229. Debug.Log("Exception " + e.Message);
  230. }
  231. }
  232. }
  233. private void CheckDuplicate(string fileName, string id)
  234. {
  235. if (idArr.Count < 1)
  236. return;
  237. for (int i = 0; i < idArr.Count; i++)
  238. {
  239. if (idArr[i] == id)
  240. Debug.LogError(id + " in " + fileName + " is a duplicate id.");
  241. }
  242. }
  243. private void HideNotification()
  244. {
  245. this.RemoveNotification();
  246. }
  247. private void CreateMd5XML(string sourcePath)
  248. {
  249. DirectoryInfo directoryInfo = new DirectoryInfo(sourcePath);
  250. List<string> pathList = DGFileUtil.GetAllFiles(directoryInfo, ".meta");
  251. XmlDocument xml = CreateMd5XmlDocument(pathList, sourcePath, null, null);
  252. string xmlSavePath = sourcePath + "xlsx_md5.xml";
  253. xml.Save(xmlSavePath);
  254. Debug.Log("Create xlsx xml : " + xmlSavePath);
  255. AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
  256. }
  257. private XmlDocument CreateMd5XmlDocument(List<string> pathList, string pathRoot, List<string> exceptList, string exceptRoot)
  258. {
  259. XmlDocument xml = new XmlDocument();
  260. XmlElement root = xml.CreateElement("xlsx");
  261. xml.AppendChild(root);
  262. for (int i = 0; i < pathList.Count; i++)
  263. {
  264. string assetPath = pathList[i];
  265. string md5 = MD5Util.GetFileHash(assetPath);
  266. string p = assetPath.Substring(pathRoot.Length);
  267. pathList[i] = p;
  268. XmlElement e = xml.CreateElement("a");
  269. XmlAttribute attr = xml.CreateAttribute("p");
  270. attr.Value = p;
  271. e.Attributes.Append(attr);
  272. attr = xml.CreateAttribute("m");
  273. attr.Value = md5;
  274. e.Attributes.Append(attr);
  275. root.AppendChild(e);
  276. }
  277. return xml;
  278. }
  279. private bool CheckVersion(string fileName)
  280. {
  281. if (md5Dict == null || md5Dict.Count < 1)
  282. return false;
  283. else
  284. {
  285. string[] pathArr = StringExtention.SplitWithString(fileName, "\\");
  286. if (pathArr.Length < 3)
  287. return false;
  288. string str = pathArr[2] + ".xlsx";
  289. string md5 = MD5Util.GetFileHash(defaultPath + fileName + ".xlsx");
  290. if (md5Dict.ContainsKey(str) && md5Dict[str] == md5)
  291. {
  292. Debug.Log(pathArr[2] + ".xlsx" + " has same version, ignored");
  293. return true;
  294. }
  295. else
  296. {
  297. if(md5Dict.ContainsKey(str))
  298. Debug.Log(fileName + ": [xml]" + md5Dict[str] + ", [xlsx]" + md5);
  299. else
  300. Debug.Log(fileName + "is new xlsx file, [xlsx]" + md5);
  301. }
  302. return false;
  303. }
  304. }
  305. private void GetMd5Xml(string fileName)
  306. {
  307. string[] pathArr = StringExtention.SplitWithString(fileName, "\\");
  308. string parent = pathArr[1];
  309. string xmlPath = defaultPath + "/" + parent + "/xlsx_md5.xml";
  310. if (!File.Exists(xmlPath))
  311. {
  312. return;
  313. }
  314. StreamReader sr = File.OpenText(xmlPath);
  315. string data = sr.ReadToEnd();
  316. sr.Close();
  317. sr.Dispose();
  318. XmlDocument xml = new XmlDocument();
  319. xml.LoadXml(data);
  320. md5Dict = new Dictionary<string, string>();
  321. XmlNode mapNode = xml.SelectSingleNode("xlsx");
  322. XmlNodeList nodeList = mapNode.SelectNodes("a");
  323. for (int i = 0; i < nodeList.Count; i++)
  324. {
  325. XmlNode node = nodeList[i];
  326. string path = node.Attributes["p"].Value;
  327. string md5 = node.Attributes["m"].Value;
  328. md5Dict.Add(path, md5);
  329. }
  330. }
  331. void OnInspectorUpdate()
  332. {
  333. this.Repaint();
  334. }
  335. void OnDestory()
  336. {
  337. EditorUtility.UnloadUnusedAssetsImmediate();
  338. }
  339. }