ResourceEditorController.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. //------------------------------------------------------------
  2. // Game Framework
  3. // Copyright © 2013-2021 loyalsoft. All rights reserved.
  4. // Homepage: http://www.game7000.com/
  5. // Feedback: http://www.game7000.com/
  6. //------------------------------------------------------------
  7. using GameFramework;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.IO;
  11. using System.Xml;
  12. using UnityEditor;
  13. using UnityEngine;
  14. namespace UnityGameFramework.Editor.ResourceTools
  15. {
  16. public sealed class ResourceEditorController
  17. {
  18. private const string DefaultSourceAssetRootPath = "Assets";
  19. private readonly string m_ConfigurationPath;
  20. private readonly ResourceCollection m_ResourceCollection;
  21. private readonly List<string> m_SourceAssetSearchPaths;
  22. private readonly List<string> m_SourceAssetSearchRelativePaths;
  23. private readonly Dictionary<string, SourceAsset> m_SourceAssets;
  24. private SourceFolder m_SourceAssetRoot;
  25. private string m_SourceAssetRootPath;
  26. private string m_SourceAssetUnionTypeFilter;
  27. private string m_SourceAssetUnionLabelFilter;
  28. private string m_SourceAssetExceptTypeFilter;
  29. private string m_SourceAssetExceptLabelFilter;
  30. private AssetSorterType m_AssetSorter;
  31. public ResourceEditorController()
  32. {
  33. m_ConfigurationPath = Type.GetConfigurationPath<ResourceEditorConfigPathAttribute>() ?? Utility.Path.GetRegularPath(Path.Combine(Application.dataPath, "GameFramework/Configs/ResourceEditor.xml"));
  34. m_ResourceCollection = new ResourceCollection();
  35. m_ResourceCollection.OnLoadingResource += delegate (int index, int count)
  36. {
  37. if (OnLoadingResource != null)
  38. {
  39. OnLoadingResource(index, count);
  40. }
  41. };
  42. m_ResourceCollection.OnLoadingAsset += delegate (int index, int count)
  43. {
  44. if (OnLoadingAsset != null)
  45. {
  46. OnLoadingAsset(index, count);
  47. }
  48. };
  49. m_ResourceCollection.OnLoadCompleted += delegate ()
  50. {
  51. if (OnLoadCompleted != null)
  52. {
  53. OnLoadCompleted();
  54. }
  55. };
  56. m_SourceAssetSearchPaths = new List<string>();
  57. m_SourceAssetSearchRelativePaths = new List<string>();
  58. m_SourceAssets = new Dictionary<string, SourceAsset>(StringComparer.Ordinal);
  59. m_SourceAssetRoot = null;
  60. m_SourceAssetRootPath = null;
  61. m_SourceAssetUnionTypeFilter = null;
  62. m_SourceAssetUnionLabelFilter = null;
  63. m_SourceAssetExceptTypeFilter = null;
  64. m_SourceAssetExceptLabelFilter = null;
  65. m_AssetSorter = AssetSorterType.Path;
  66. SourceAssetRootPath = DefaultSourceAssetRootPath;
  67. }
  68. public int ResourceCount
  69. {
  70. get
  71. {
  72. return m_ResourceCollection.ResourceCount;
  73. }
  74. }
  75. public int AssetCount
  76. {
  77. get
  78. {
  79. return m_ResourceCollection.AssetCount;
  80. }
  81. }
  82. public SourceFolder SourceAssetRoot
  83. {
  84. get
  85. {
  86. return m_SourceAssetRoot;
  87. }
  88. }
  89. public string SourceAssetRootPath
  90. {
  91. get
  92. {
  93. return m_SourceAssetRootPath;
  94. }
  95. set
  96. {
  97. if (m_SourceAssetRootPath == value)
  98. {
  99. return;
  100. }
  101. m_SourceAssetRootPath = value.Replace('\\', '/');
  102. m_SourceAssetRoot = new SourceFolder(m_SourceAssetRootPath, null);
  103. RefreshSourceAssetSearchPaths();
  104. }
  105. }
  106. public string SourceAssetUnionTypeFilter
  107. {
  108. get
  109. {
  110. return m_SourceAssetUnionTypeFilter;
  111. }
  112. set
  113. {
  114. if (m_SourceAssetUnionTypeFilter == value)
  115. {
  116. return;
  117. }
  118. m_SourceAssetUnionTypeFilter = value;
  119. }
  120. }
  121. public string SourceAssetUnionLabelFilter
  122. {
  123. get
  124. {
  125. return m_SourceAssetUnionLabelFilter;
  126. }
  127. set
  128. {
  129. if (m_SourceAssetUnionLabelFilter == value)
  130. {
  131. return;
  132. }
  133. m_SourceAssetUnionLabelFilter = value;
  134. }
  135. }
  136. public string SourceAssetExceptTypeFilter
  137. {
  138. get
  139. {
  140. return m_SourceAssetExceptTypeFilter;
  141. }
  142. set
  143. {
  144. if (m_SourceAssetExceptTypeFilter == value)
  145. {
  146. return;
  147. }
  148. m_SourceAssetExceptTypeFilter = value;
  149. }
  150. }
  151. public string SourceAssetExceptLabelFilter
  152. {
  153. get
  154. {
  155. return m_SourceAssetExceptLabelFilter;
  156. }
  157. set
  158. {
  159. if (m_SourceAssetExceptLabelFilter == value)
  160. {
  161. return;
  162. }
  163. m_SourceAssetExceptLabelFilter = value;
  164. }
  165. }
  166. public AssetSorterType AssetSorter
  167. {
  168. get
  169. {
  170. return m_AssetSorter;
  171. }
  172. set
  173. {
  174. if (m_AssetSorter == value)
  175. {
  176. return;
  177. }
  178. m_AssetSorter = value;
  179. }
  180. }
  181. public event GameFrameworkAction<int, int> OnLoadingResource = null;
  182. public event GameFrameworkAction<int, int> OnLoadingAsset = null;
  183. public event GameFrameworkAction OnLoadCompleted = null;
  184. public event GameFrameworkAction<SourceAsset[]> OnAssetAssigned = null;
  185. public event GameFrameworkAction<SourceAsset[]> OnAssetUnassigned = null;
  186. public bool Load()
  187. {
  188. if (!File.Exists(m_ConfigurationPath))
  189. {
  190. return false;
  191. }
  192. try
  193. {
  194. XmlDocument xmlDocument = new XmlDocument();
  195. xmlDocument.Load(m_ConfigurationPath);
  196. XmlNode xmlRoot = xmlDocument.SelectSingleNode("UnityGameFramework");
  197. XmlNode xmlEditor = xmlRoot.SelectSingleNode("ResourceEditor");
  198. XmlNode xmlSettings = xmlEditor.SelectSingleNode("Settings");
  199. XmlNodeList xmlNodeList = null;
  200. XmlNode xmlNode = null;
  201. xmlNodeList = xmlSettings.ChildNodes;
  202. for (int i = 0; i < xmlNodeList.Count; i++)
  203. {
  204. xmlNode = xmlNodeList.Item(i);
  205. switch (xmlNode.Name)
  206. {
  207. case "SourceAssetRootPath":
  208. SourceAssetRootPath = xmlNode.InnerText;
  209. break;
  210. case "SourceAssetSearchPaths":
  211. m_SourceAssetSearchRelativePaths.Clear();
  212. XmlNodeList xmlNodeListInner = xmlNode.ChildNodes;
  213. XmlNode xmlNodeInner = null;
  214. for (int j = 0; j < xmlNodeListInner.Count; j++)
  215. {
  216. xmlNodeInner = xmlNodeListInner.Item(j);
  217. if (xmlNodeInner.Name != "SourceAssetSearchPath")
  218. {
  219. continue;
  220. }
  221. m_SourceAssetSearchRelativePaths.Add(xmlNodeInner.Attributes.GetNamedItem("RelativePath").Value);
  222. }
  223. break;
  224. case "SourceAssetUnionTypeFilter":
  225. SourceAssetUnionTypeFilter = xmlNode.InnerText;
  226. break;
  227. case "SourceAssetUnionLabelFilter":
  228. SourceAssetUnionLabelFilter = xmlNode.InnerText;
  229. break;
  230. case "SourceAssetExceptTypeFilter":
  231. SourceAssetExceptTypeFilter = xmlNode.InnerText;
  232. break;
  233. case "SourceAssetExceptLabelFilter":
  234. SourceAssetExceptLabelFilter = xmlNode.InnerText;
  235. break;
  236. case "AssetSorter":
  237. AssetSorter = (AssetSorterType)Enum.Parse(typeof(AssetSorterType), xmlNode.InnerText);
  238. break;
  239. }
  240. }
  241. RefreshSourceAssetSearchPaths();
  242. }
  243. catch
  244. {
  245. File.Delete(m_ConfigurationPath);
  246. return false;
  247. }
  248. ScanSourceAssets();
  249. m_ResourceCollection.Load();
  250. return true;
  251. }
  252. public bool Save()
  253. {
  254. try
  255. {
  256. XmlDocument xmlDocument = new XmlDocument();
  257. xmlDocument.AppendChild(xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", null));
  258. XmlElement xmlRoot = xmlDocument.CreateElement("UnityGameFramework");
  259. xmlDocument.AppendChild(xmlRoot);
  260. XmlElement xmlEditor = xmlDocument.CreateElement("ResourceEditor");
  261. xmlRoot.AppendChild(xmlEditor);
  262. XmlElement xmlSettings = xmlDocument.CreateElement("Settings");
  263. xmlEditor.AppendChild(xmlSettings);
  264. XmlElement xmlElement = null;
  265. XmlAttribute xmlAttribute = null;
  266. xmlElement = xmlDocument.CreateElement("SourceAssetRootPath");
  267. xmlElement.InnerText = SourceAssetRootPath.ToString();
  268. xmlSettings.AppendChild(xmlElement);
  269. xmlElement = xmlDocument.CreateElement("SourceAssetSearchPaths");
  270. xmlSettings.AppendChild(xmlElement);
  271. foreach (string sourceAssetSearchRelativePath in m_SourceAssetSearchRelativePaths)
  272. {
  273. XmlElement xmlElementInner = xmlDocument.CreateElement("SourceAssetSearchPath");
  274. xmlAttribute = xmlDocument.CreateAttribute("RelativePath");
  275. xmlAttribute.Value = sourceAssetSearchRelativePath;
  276. xmlElementInner.Attributes.SetNamedItem(xmlAttribute);
  277. xmlElement.AppendChild(xmlElementInner);
  278. }
  279. xmlElement = xmlDocument.CreateElement("SourceAssetUnionTypeFilter");
  280. xmlElement.InnerText = SourceAssetUnionTypeFilter ?? string.Empty;
  281. xmlSettings.AppendChild(xmlElement);
  282. xmlElement = xmlDocument.CreateElement("SourceAssetUnionLabelFilter");
  283. xmlElement.InnerText = SourceAssetUnionLabelFilter ?? string.Empty;
  284. xmlSettings.AppendChild(xmlElement);
  285. xmlElement = xmlDocument.CreateElement("SourceAssetExceptTypeFilter");
  286. xmlElement.InnerText = SourceAssetExceptTypeFilter ?? string.Empty;
  287. xmlSettings.AppendChild(xmlElement);
  288. xmlElement = xmlDocument.CreateElement("SourceAssetExceptLabelFilter");
  289. xmlElement.InnerText = SourceAssetExceptLabelFilter ?? string.Empty;
  290. xmlSettings.AppendChild(xmlElement);
  291. xmlElement = xmlDocument.CreateElement("AssetSorter");
  292. xmlElement.InnerText = AssetSorter.ToString();
  293. xmlSettings.AppendChild(xmlElement);
  294. string configurationDirectoryName = Path.GetDirectoryName(m_ConfigurationPath);
  295. if (!Directory.Exists(configurationDirectoryName))
  296. {
  297. Directory.CreateDirectory(configurationDirectoryName);
  298. }
  299. xmlDocument.Save(m_ConfigurationPath);
  300. AssetDatabase.Refresh();
  301. }
  302. catch
  303. {
  304. if (File.Exists(m_ConfigurationPath))
  305. {
  306. File.Delete(m_ConfigurationPath);
  307. }
  308. return false;
  309. }
  310. return m_ResourceCollection.Save();
  311. }
  312. public Resource[] GetResources()
  313. {
  314. return m_ResourceCollection.GetResources();
  315. }
  316. public Resource GetResource(string name, string variant)
  317. {
  318. return m_ResourceCollection.GetResource(name, variant);
  319. }
  320. public bool HasResource(string name, string variant)
  321. {
  322. return m_ResourceCollection.HasResource(name, variant);
  323. }
  324. public bool AddResource(string name, string variant, string fileSystem, LoadType loadType, bool packed)
  325. {
  326. return m_ResourceCollection.AddResource(name, variant, fileSystem, loadType, packed);
  327. }
  328. public bool RenameResource(string oldName, string oldVariant, string newName, string newVariant)
  329. {
  330. return m_ResourceCollection.RenameResource(oldName, oldVariant, newName, newVariant);
  331. }
  332. public bool RemoveResource(string name, string variant)
  333. {
  334. Asset[] assetsToRemove = m_ResourceCollection.GetAssets(name, variant);
  335. if (m_ResourceCollection.RemoveResource(name, variant))
  336. {
  337. List<SourceAsset> unassignedSourceAssets = new List<SourceAsset>();
  338. foreach (Asset asset in assetsToRemove)
  339. {
  340. SourceAsset sourceAsset = GetSourceAsset(asset.Guid);
  341. if (sourceAsset != null)
  342. {
  343. unassignedSourceAssets.Add(sourceAsset);
  344. }
  345. }
  346. if (OnAssetUnassigned != null)
  347. {
  348. OnAssetUnassigned(unassignedSourceAssets.ToArray());
  349. }
  350. return true;
  351. }
  352. return false;
  353. }
  354. public bool SetResourceLoadType(string name, string variant, LoadType loadType)
  355. {
  356. return m_ResourceCollection.SetResourceLoadType(name, variant, loadType);
  357. }
  358. public bool SetResourcePacked(string name, string variant, bool packed)
  359. {
  360. return m_ResourceCollection.SetResourcePacked(name, variant, packed);
  361. }
  362. public int RemoveUnusedResources()
  363. {
  364. List<Resource> resources = new List<Resource>(m_ResourceCollection.GetResources());
  365. List<Resource> removeResources = resources.FindAll(resource => GetAssets(resource.Name, resource.Variant).Length <= 0);
  366. foreach (Resource removeResource in removeResources)
  367. {
  368. m_ResourceCollection.RemoveResource(removeResource.Name, removeResource.Variant);
  369. }
  370. return removeResources.Count;
  371. }
  372. public Asset[] GetAssets(string name, string variant)
  373. {
  374. List<Asset> assets = new List<Asset>(m_ResourceCollection.GetAssets(name, variant));
  375. switch (AssetSorter)
  376. {
  377. case AssetSorterType.Path:
  378. assets.Sort(AssetPathComparer);
  379. break;
  380. case AssetSorterType.Name:
  381. assets.Sort(AssetNameComparer);
  382. break;
  383. case AssetSorterType.Guid:
  384. assets.Sort(AssetGuidComparer);
  385. break;
  386. }
  387. return assets.ToArray();
  388. }
  389. public Asset GetAsset(string guid)
  390. {
  391. return m_ResourceCollection.GetAsset(guid);
  392. }
  393. public bool AssignAsset(string guid, string name, string variant)
  394. {
  395. if (m_ResourceCollection.AssignAsset(guid, name, variant))
  396. {
  397. if (OnAssetAssigned != null)
  398. {
  399. OnAssetAssigned(new SourceAsset[] { GetSourceAsset(guid) });
  400. }
  401. return true;
  402. }
  403. return false;
  404. }
  405. public bool UnassignAsset(string guid)
  406. {
  407. if (m_ResourceCollection.UnassignAsset(guid))
  408. {
  409. SourceAsset sourceAsset = GetSourceAsset(guid);
  410. if (sourceAsset != null)
  411. {
  412. if (OnAssetUnassigned != null)
  413. {
  414. OnAssetUnassigned(new SourceAsset[] { sourceAsset });
  415. }
  416. }
  417. return true;
  418. }
  419. return false;
  420. }
  421. public int RemoveUnknownAssets()
  422. {
  423. List<Asset> assets = new List<Asset>(m_ResourceCollection.GetAssets());
  424. List<Asset> removeAssets = assets.FindAll(asset => GetSourceAsset(asset.Guid) == null);
  425. foreach (Asset asset in removeAssets)
  426. {
  427. m_ResourceCollection.UnassignAsset(asset.Guid);
  428. }
  429. return removeAssets.Count;
  430. }
  431. public SourceAsset[] GetSourceAssets()
  432. {
  433. int count = 0;
  434. SourceAsset[] sourceAssets = new SourceAsset[m_SourceAssets.Count];
  435. foreach (KeyValuePair<string, SourceAsset> sourceAsset in m_SourceAssets)
  436. {
  437. sourceAssets[count++] = sourceAsset.Value;
  438. }
  439. return sourceAssets;
  440. }
  441. public SourceAsset GetSourceAsset(string guid)
  442. {
  443. if (string.IsNullOrEmpty(guid))
  444. {
  445. return null;
  446. }
  447. SourceAsset sourceAsset = null;
  448. if (m_SourceAssets.TryGetValue(guid, out sourceAsset))
  449. {
  450. return sourceAsset;
  451. }
  452. return null;
  453. }
  454. public void ScanSourceAssets()
  455. {
  456. m_SourceAssets.Clear();
  457. m_SourceAssetRoot.Clear();
  458. string[] sourceAssetSearchPaths = m_SourceAssetSearchPaths.ToArray();
  459. HashSet<string> tempGuids = new HashSet<string>();
  460. tempGuids.UnionWith(AssetDatabase.FindAssets(SourceAssetUnionTypeFilter, sourceAssetSearchPaths));
  461. tempGuids.UnionWith(AssetDatabase.FindAssets(SourceAssetUnionLabelFilter, sourceAssetSearchPaths));
  462. tempGuids.ExceptWith(AssetDatabase.FindAssets(SourceAssetExceptTypeFilter, sourceAssetSearchPaths));
  463. tempGuids.ExceptWith(AssetDatabase.FindAssets(SourceAssetExceptLabelFilter, sourceAssetSearchPaths));
  464. string[] guids = new List<string>(tempGuids).ToArray();
  465. foreach (string guid in guids)
  466. {
  467. string fullPath = AssetDatabase.GUIDToAssetPath(guid);
  468. if (AssetDatabase.IsValidFolder(fullPath))
  469. {
  470. // Skip folder.
  471. continue;
  472. }
  473. string assetPath = fullPath.Substring(SourceAssetRootPath.Length + 1);
  474. string[] splitedPath = assetPath.Split('/');
  475. SourceFolder folder = m_SourceAssetRoot;
  476. for (int i = 0; i < splitedPath.Length - 1; i++)
  477. {
  478. SourceFolder subFolder = folder.GetFolder(splitedPath[i]);
  479. folder = subFolder == null ? folder.AddFolder(splitedPath[i]) : subFolder;
  480. }
  481. SourceAsset asset = folder.AddAsset(guid, fullPath, splitedPath[splitedPath.Length - 1]);
  482. m_SourceAssets.Add(asset.Guid, asset);
  483. }
  484. }
  485. private void RefreshSourceAssetSearchPaths()
  486. {
  487. m_SourceAssetSearchPaths.Clear();
  488. if (string.IsNullOrEmpty(m_SourceAssetRootPath))
  489. {
  490. SourceAssetRootPath = DefaultSourceAssetRootPath;
  491. }
  492. if (m_SourceAssetSearchRelativePaths.Count > 0)
  493. {
  494. foreach (string sourceAssetSearchRelativePath in m_SourceAssetSearchRelativePaths)
  495. {
  496. m_SourceAssetSearchPaths.Add(Utility.Path.GetRegularPath(Path.Combine(m_SourceAssetRootPath, sourceAssetSearchRelativePath)));
  497. }
  498. }
  499. else
  500. {
  501. m_SourceAssetSearchPaths.Add(m_SourceAssetRootPath);
  502. }
  503. }
  504. private int AssetPathComparer(Asset a, Asset b)
  505. {
  506. SourceAsset sourceAssetA = GetSourceAsset(a.Guid);
  507. SourceAsset sourceAssetB = GetSourceAsset(b.Guid);
  508. if (sourceAssetA != null && sourceAssetB != null)
  509. {
  510. return sourceAssetA.Path.CompareTo(sourceAssetB.Path);
  511. }
  512. if (sourceAssetA == null && sourceAssetB == null)
  513. {
  514. return a.Guid.CompareTo(b.Guid);
  515. }
  516. if (sourceAssetA == null)
  517. {
  518. return -1;
  519. }
  520. if (sourceAssetB == null)
  521. {
  522. return 1;
  523. }
  524. return 0;
  525. }
  526. private int AssetNameComparer(Asset a, Asset b)
  527. {
  528. SourceAsset sourceAssetA = GetSourceAsset(a.Guid);
  529. SourceAsset sourceAssetB = GetSourceAsset(b.Guid);
  530. if (sourceAssetA != null && sourceAssetB != null)
  531. {
  532. return sourceAssetA.Name.CompareTo(sourceAssetB.Name);
  533. }
  534. if (sourceAssetA == null && sourceAssetB == null)
  535. {
  536. return a.Guid.CompareTo(b.Guid);
  537. }
  538. if (sourceAssetA == null)
  539. {
  540. return -1;
  541. }
  542. if (sourceAssetB == null)
  543. {
  544. return 1;
  545. }
  546. return 0;
  547. }
  548. private int AssetGuidComparer(Asset a, Asset b)
  549. {
  550. SourceAsset sourceAssetA = GetSourceAsset(a.Guid);
  551. SourceAsset sourceAssetB = GetSourceAsset(b.Guid);
  552. if (sourceAssetA != null && sourceAssetB != null || sourceAssetA == null && sourceAssetB == null)
  553. {
  554. return a.Guid.CompareTo(b.Guid);
  555. }
  556. if (sourceAssetA == null)
  557. {
  558. return -1;
  559. }
  560. if (sourceAssetB == null)
  561. {
  562. return 1;
  563. }
  564. return 0;
  565. }
  566. }
  567. }