EditorConfigExporter.cs 13 KB

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