ResourceEditor.cs 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. //------------------------------------------------------------
  2. // Game Framework
  3. // Copyright © 2013-2021 Jiang Yin. All rights reserved.
  4. // Homepage: https://gameframework.cn/
  5. // Feedback: mailto:ellan@gameframework.cn
  6. //------------------------------------------------------------
  7. using GameFramework;
  8. using System.Collections.Generic;
  9. using UnityEditor;
  10. using UnityEngine;
  11. namespace UnityGameFramework.Editor.ResourceTools
  12. {
  13. /// <summary>
  14. /// 资源编辑器。
  15. /// </summary>
  16. internal sealed partial class ResourceEditor : EditorWindow
  17. {
  18. private ResourceEditorController m_Controller = null;
  19. private MenuState m_MenuState = MenuState.Normal;
  20. private Resource m_SelectedResource = null;
  21. private ResourceFolder m_ResourceRoot = null;
  22. private HashSet<string> m_ExpandedResourceFolderNames = null;
  23. private HashSet<Asset> m_SelectedAssetsInSelectedResource = null;
  24. private HashSet<SourceFolder> m_ExpandedSourceFolders = null;
  25. private HashSet<SourceAsset> m_SelectedSourceAssets = null;
  26. private Texture m_MissingSourceAssetIcon = null;
  27. private HashSet<SourceFolder> m_CachedSelectedSourceFolders = null;
  28. private HashSet<SourceFolder> m_CachedUnselectedSourceFolders = null;
  29. private HashSet<SourceFolder> m_CachedAssignedSourceFolders = null;
  30. private HashSet<SourceFolder> m_CachedUnassignedSourceFolders = null;
  31. private HashSet<SourceAsset> m_CachedAssignedSourceAssets = null;
  32. private HashSet<SourceAsset> m_CachedUnassignedSourceAssets = null;
  33. private Vector2 m_ResourcesViewScroll = Vector2.zero;
  34. private Vector2 m_ResourceViewScroll = Vector2.zero;
  35. private Vector2 m_SourceAssetsViewScroll = Vector2.zero;
  36. private string m_InputResourceName = null;
  37. private string m_InputResourceVariant = null;
  38. private bool m_HideAssignedSourceAssets = false;
  39. private int m_CurrentResourceContentCount = 0;
  40. private int m_CurrentResourceRowOnDraw = 0;
  41. private int m_CurrentSourceRowOnDraw = 0;
  42. [MenuItem("Game Framework/Resource Tools/Resource Editor", false, 41)]
  43. private static void Open()
  44. {
  45. ResourceEditor window = GetWindow<ResourceEditor>("Resource Editor", true);
  46. window.minSize = new Vector2(1400f, 600f);
  47. }
  48. private void OnEnable()
  49. {
  50. m_Controller = new ResourceEditorController();
  51. m_Controller.OnLoadingResource += OnLoadingResource;
  52. m_Controller.OnLoadingAsset += OnLoadingAsset;
  53. m_Controller.OnLoadCompleted += OnLoadCompleted;
  54. m_Controller.OnAssetAssigned += OnAssetAssigned;
  55. m_Controller.OnAssetUnassigned += OnAssetUnassigned;
  56. m_MenuState = MenuState.Normal;
  57. m_SelectedResource = null;
  58. m_ResourceRoot = new ResourceFolder("Resources", null);
  59. m_ExpandedResourceFolderNames = new HashSet<string>();
  60. m_SelectedAssetsInSelectedResource = new HashSet<Asset>();
  61. m_ExpandedSourceFolders = new HashSet<SourceFolder>();
  62. m_SelectedSourceAssets = new HashSet<SourceAsset>();
  63. m_MissingSourceAssetIcon = EditorGUIUtility.IconContent("console.warnicon.sml").image;
  64. m_CachedSelectedSourceFolders = new HashSet<SourceFolder>();
  65. m_CachedUnselectedSourceFolders = new HashSet<SourceFolder>();
  66. m_CachedAssignedSourceFolders = new HashSet<SourceFolder>();
  67. m_CachedUnassignedSourceFolders = new HashSet<SourceFolder>();
  68. m_CachedAssignedSourceAssets = new HashSet<SourceAsset>();
  69. m_CachedUnassignedSourceAssets = new HashSet<SourceAsset>();
  70. m_ResourcesViewScroll = Vector2.zero;
  71. m_ResourceViewScroll = Vector2.zero;
  72. m_SourceAssetsViewScroll = Vector2.zero;
  73. m_InputResourceName = null;
  74. m_InputResourceVariant = null;
  75. m_HideAssignedSourceAssets = false;
  76. m_CurrentResourceContentCount = 0;
  77. m_CurrentResourceRowOnDraw = 0;
  78. m_CurrentSourceRowOnDraw = 0;
  79. if (m_Controller.Load())
  80. {
  81. Debug.Log("Load configuration success.");
  82. }
  83. else
  84. {
  85. Debug.LogWarning("Load configuration failure.");
  86. }
  87. EditorUtility.DisplayProgressBar("Prepare Resource Editor", "Processing...", 0f);
  88. RefreshResourceTree();
  89. EditorUtility.ClearProgressBar();
  90. }
  91. private void OnGUI()
  92. {
  93. EditorGUILayout.BeginHorizontal(GUILayout.Width(position.width), GUILayout.Height(position.height));
  94. {
  95. GUILayout.Space(2f);
  96. EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.25f));
  97. {
  98. GUILayout.Space(5f);
  99. EditorGUILayout.LabelField(Utility.Text.Format("Resource List ({0})", m_Controller.ResourceCount.ToString()), EditorStyles.boldLabel);
  100. EditorGUILayout.BeginHorizontal("box", GUILayout.Height(position.height - 52f));
  101. {
  102. DrawResourcesView();
  103. }
  104. EditorGUILayout.EndHorizontal();
  105. EditorGUILayout.BeginHorizontal();
  106. {
  107. GUILayout.Space(5f);
  108. DrawResourcesMenu();
  109. }
  110. EditorGUILayout.EndHorizontal();
  111. }
  112. EditorGUILayout.EndVertical();
  113. EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.25f));
  114. {
  115. GUILayout.Space(5f);
  116. EditorGUILayout.LabelField(Utility.Text.Format("Resource Content ({0})", m_CurrentResourceContentCount.ToString()), EditorStyles.boldLabel);
  117. EditorGUILayout.BeginHorizontal("box", GUILayout.Height(position.height - 52f));
  118. {
  119. DrawResourceView();
  120. }
  121. EditorGUILayout.EndHorizontal();
  122. EditorGUILayout.BeginHorizontal();
  123. {
  124. GUILayout.Space(5f);
  125. DrawResourceMenu();
  126. }
  127. EditorGUILayout.EndHorizontal();
  128. }
  129. EditorGUILayout.EndVertical();
  130. EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.5f - 16f));
  131. {
  132. GUILayout.Space(5f);
  133. EditorGUILayout.LabelField("Asset List", EditorStyles.boldLabel);
  134. EditorGUILayout.BeginHorizontal("box", GUILayout.Height(position.height - 52f));
  135. {
  136. DrawSourceAssetsView();
  137. }
  138. EditorGUILayout.EndHorizontal();
  139. EditorGUILayout.BeginHorizontal();
  140. {
  141. GUILayout.Space(5f);
  142. DrawSourceAssetsMenu();
  143. }
  144. EditorGUILayout.EndHorizontal();
  145. }
  146. EditorGUILayout.EndVertical();
  147. GUILayout.Space(5f);
  148. }
  149. EditorGUILayout.EndHorizontal();
  150. }
  151. private void DrawResourcesView()
  152. {
  153. m_CurrentResourceRowOnDraw = 0;
  154. m_ResourcesViewScroll = EditorGUILayout.BeginScrollView(m_ResourcesViewScroll);
  155. {
  156. DrawResourceFolder(m_ResourceRoot);
  157. }
  158. EditorGUILayout.EndScrollView();
  159. }
  160. private void DrawResourceFolder(ResourceFolder folder)
  161. {
  162. bool expand = IsExpandedResourceFolder(folder);
  163. EditorGUILayout.BeginHorizontal();
  164. {
  165. #if UNITY_2019_3_OR_NEWER
  166. bool foldout = EditorGUI.Foldout(new Rect(18f + 14f * folder.Depth, 20f * m_CurrentResourceRowOnDraw + 4f, int.MaxValue, 14f), expand, string.Empty, true);
  167. #else
  168. bool foldout = EditorGUI.Foldout(new Rect(18f + 14f * folder.Depth, 20f * m_CurrentResourceRowOnDraw + 2f, int.MaxValue, 14f), expand, string.Empty, true);
  169. #endif
  170. if (expand != foldout)
  171. {
  172. expand = !expand;
  173. SetExpandedResourceFolder(folder, expand);
  174. }
  175. #if UNITY_2019_3_OR_NEWER
  176. GUI.DrawTexture(new Rect(32f + 14f * folder.Depth, 20f * m_CurrentResourceRowOnDraw + 3f, 16f, 16f), ResourceFolder.Icon);
  177. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(44f + 14f * folder.Depth), GUILayout.Height(18f));
  178. #else
  179. GUI.DrawTexture(new Rect(32f + 14f * folder.Depth, 20f * m_CurrentResourceRowOnDraw + 1f, 16f, 16f), ResourceFolder.Icon);
  180. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(40f + 14f * folder.Depth), GUILayout.Height(18f));
  181. #endif
  182. EditorGUILayout.LabelField(folder.Name);
  183. }
  184. EditorGUILayout.EndHorizontal();
  185. m_CurrentResourceRowOnDraw++;
  186. if (expand)
  187. {
  188. foreach (ResourceFolder subFolder in folder.GetFolders())
  189. {
  190. DrawResourceFolder(subFolder);
  191. }
  192. foreach (ResourceItem resourceItem in folder.GetItems())
  193. {
  194. DrawResourceItem(resourceItem);
  195. }
  196. }
  197. }
  198. private void DrawResourceItem(ResourceItem resourceItem)
  199. {
  200. EditorGUILayout.BeginHorizontal();
  201. {
  202. string title = resourceItem.Name;
  203. if (resourceItem.Resource.Packed)
  204. {
  205. title = "[Packed] " + title;
  206. }
  207. float emptySpace = position.width;
  208. if (EditorGUILayout.Toggle(m_SelectedResource == resourceItem.Resource, GUILayout.Width(emptySpace - 12f)))
  209. {
  210. ChangeSelectedResource(resourceItem.Resource);
  211. }
  212. else if (m_SelectedResource == resourceItem.Resource)
  213. {
  214. ChangeSelectedResource(null);
  215. }
  216. GUILayout.Space(-emptySpace + 24f);
  217. #if UNITY_2019_3_OR_NEWER
  218. GUI.DrawTexture(new Rect(32f + 14f * resourceItem.Depth, 20f * m_CurrentResourceRowOnDraw + 3f, 16f, 16f), resourceItem.Icon);
  219. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(30f + 14f * resourceItem.Depth), GUILayout.Height(18f));
  220. #else
  221. GUI.DrawTexture(new Rect(32f + 14f * resourceItem.Depth, 20f * m_CurrentResourceRowOnDraw + 1f, 16f, 16f), resourceItem.Icon);
  222. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(26f + 14f * resourceItem.Depth), GUILayout.Height(18f));
  223. #endif
  224. EditorGUILayout.LabelField(title);
  225. }
  226. EditorGUILayout.EndHorizontal();
  227. m_CurrentResourceRowOnDraw++;
  228. }
  229. private void DrawResourcesMenu()
  230. {
  231. switch (m_MenuState)
  232. {
  233. case MenuState.Normal:
  234. DrawResourcesMenu_Normal();
  235. break;
  236. case MenuState.Add:
  237. DrawResourcesMenu_Add();
  238. break;
  239. case MenuState.Rename:
  240. DrawResourcesMenu_Rename();
  241. break;
  242. case MenuState.Remove:
  243. DrawResourcesMenu_Remove();
  244. break;
  245. }
  246. }
  247. private void DrawResourcesMenu_Normal()
  248. {
  249. if (GUILayout.Button("Add", GUILayout.Width(65f)))
  250. {
  251. m_MenuState = MenuState.Add;
  252. m_InputResourceName = null;
  253. m_InputResourceVariant = null;
  254. GUI.FocusControl(null);
  255. }
  256. EditorGUI.BeginDisabledGroup(m_SelectedResource == null);
  257. {
  258. if (GUILayout.Button("Rename", GUILayout.Width(65f)))
  259. {
  260. m_MenuState = MenuState.Rename;
  261. m_InputResourceName = m_SelectedResource != null ? m_SelectedResource.Name : null;
  262. m_InputResourceVariant = m_SelectedResource != null ? m_SelectedResource.Variant : null;
  263. GUI.FocusControl(null);
  264. }
  265. if (GUILayout.Button("Remove", GUILayout.Width(65f)))
  266. {
  267. m_MenuState = MenuState.Remove;
  268. }
  269. if (m_SelectedResource == null)
  270. {
  271. EditorGUILayout.EnumPopup(LoadType.LoadFromFile);
  272. }
  273. else
  274. {
  275. LoadType loadType = (LoadType)EditorGUILayout.EnumPopup(m_SelectedResource.LoadType);
  276. if (loadType != m_SelectedResource.LoadType)
  277. {
  278. SetResourceLoadType(loadType);
  279. }
  280. }
  281. bool packed = EditorGUILayout.ToggleLeft("Packed", m_SelectedResource != null && m_SelectedResource.Packed, GUILayout.Width(65f));
  282. if (m_SelectedResource != null && packed != m_SelectedResource.Packed)
  283. {
  284. SetResourcePacked(packed);
  285. }
  286. }
  287. EditorGUI.EndDisabledGroup();
  288. }
  289. private void DrawResourcesMenu_Add()
  290. {
  291. GUI.SetNextControlName("NewResourceNameTextField");
  292. m_InputResourceName = EditorGUILayout.TextField(m_InputResourceName);
  293. GUI.SetNextControlName("NewResourceVariantTextField");
  294. m_InputResourceVariant = EditorGUILayout.TextField(m_InputResourceVariant, GUILayout.Width(60f));
  295. if (GUI.GetNameOfFocusedControl() == "NewResourceNameTextField" || GUI.GetNameOfFocusedControl() == "NewResourceVariantTextField")
  296. {
  297. if (Event.current.isKey && Event.current.keyCode == KeyCode.Return)
  298. {
  299. EditorUtility.DisplayProgressBar("Add Resource", "Processing...", 0f);
  300. AddResource(m_InputResourceName, m_InputResourceVariant, true);
  301. EditorUtility.ClearProgressBar();
  302. Repaint();
  303. }
  304. }
  305. if (GUILayout.Button("Add", GUILayout.Width(50f)))
  306. {
  307. EditorUtility.DisplayProgressBar("Add Resource", "Processing...", 0f);
  308. AddResource(m_InputResourceName, m_InputResourceVariant, true);
  309. EditorUtility.ClearProgressBar();
  310. }
  311. if (GUILayout.Button("Back", GUILayout.Width(50f)))
  312. {
  313. m_MenuState = MenuState.Normal;
  314. }
  315. }
  316. private void DrawResourcesMenu_Rename()
  317. {
  318. if (m_SelectedResource == null)
  319. {
  320. m_MenuState = MenuState.Normal;
  321. return;
  322. }
  323. GUI.SetNextControlName("RenameResourceNameTextField");
  324. m_InputResourceName = EditorGUILayout.TextField(m_InputResourceName);
  325. GUI.SetNextControlName("RenameResourceVariantTextField");
  326. m_InputResourceVariant = EditorGUILayout.TextField(m_InputResourceVariant, GUILayout.Width(60f));
  327. if (GUI.GetNameOfFocusedControl() == "RenameResourceNameTextField" || GUI.GetNameOfFocusedControl() == "RenameResourceVariantTextField")
  328. {
  329. if (Event.current.isKey && Event.current.keyCode == KeyCode.Return)
  330. {
  331. EditorUtility.DisplayProgressBar("Rename Resource", "Processing...", 0f);
  332. RenameResource(m_SelectedResource, m_InputResourceName, m_InputResourceVariant);
  333. EditorUtility.ClearProgressBar();
  334. Repaint();
  335. }
  336. }
  337. if (GUILayout.Button("OK", GUILayout.Width(50f)))
  338. {
  339. EditorUtility.DisplayProgressBar("Rename Resource", "Processing...", 0f);
  340. RenameResource(m_SelectedResource, m_InputResourceName, m_InputResourceVariant);
  341. EditorUtility.ClearProgressBar();
  342. }
  343. if (GUILayout.Button("Back", GUILayout.Width(50f)))
  344. {
  345. m_MenuState = MenuState.Normal;
  346. }
  347. }
  348. private void DrawResourcesMenu_Remove()
  349. {
  350. if (m_SelectedResource == null)
  351. {
  352. m_MenuState = MenuState.Normal;
  353. return;
  354. }
  355. GUILayout.Label(Utility.Text.Format("Remove '{0}' ?", m_SelectedResource.FullName));
  356. if (GUILayout.Button("Yes", GUILayout.Width(50f)))
  357. {
  358. EditorUtility.DisplayProgressBar("Remove Resource", "Processing...", 0f);
  359. RemoveResource();
  360. EditorUtility.ClearProgressBar();
  361. m_MenuState = MenuState.Normal;
  362. }
  363. if (GUILayout.Button("No", GUILayout.Width(50f)))
  364. {
  365. m_MenuState = MenuState.Normal;
  366. }
  367. }
  368. private void DrawResourceView()
  369. {
  370. m_ResourceViewScroll = EditorGUILayout.BeginScrollView(m_ResourceViewScroll);
  371. {
  372. if (m_SelectedResource != null)
  373. {
  374. int index = 0;
  375. Asset[] assets = m_Controller.GetAssets(m_SelectedResource.Name, m_SelectedResource.Variant);
  376. m_CurrentResourceContentCount = assets.Length;
  377. foreach (Asset asset in assets)
  378. {
  379. SourceAsset sourceAsset = m_Controller.GetSourceAsset(asset.Guid);
  380. string assetName = sourceAsset != null ? (m_Controller.AssetSorter == AssetSorterType.Path ? sourceAsset.Path : (m_Controller.AssetSorter == AssetSorterType.Name ? sourceAsset.Name : sourceAsset.Guid)) : asset.Guid;
  381. EditorGUILayout.BeginHorizontal();
  382. {
  383. float emptySpace = position.width;
  384. bool select = IsSelectedAssetInSelectedResource(asset);
  385. if (select != EditorGUILayout.Toggle(select, GUILayout.Width(emptySpace - 12f)))
  386. {
  387. select = !select;
  388. SetSelectedAssetInSelectedResource(asset, select);
  389. }
  390. GUILayout.Space(-emptySpace + 24f);
  391. #if UNITY_2019_3_OR_NEWER
  392. GUI.DrawTexture(new Rect(20f, 20f * index++ + 3f, 16f, 16f), sourceAsset != null ? sourceAsset.Icon : m_MissingSourceAssetIcon);
  393. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(16f), GUILayout.Height(18f));
  394. #else
  395. GUI.DrawTexture(new Rect(20f, 20f * index++ + 1f, 16f, 16f), sourceAsset != null ? sourceAsset.Icon : m_MissingSourceAssetIcon);
  396. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(14f), GUILayout.Height(18f));
  397. #endif
  398. EditorGUILayout.LabelField(assetName);
  399. }
  400. EditorGUILayout.EndHorizontal();
  401. }
  402. }
  403. else
  404. {
  405. m_CurrentResourceContentCount = 0;
  406. }
  407. }
  408. EditorGUILayout.EndScrollView();
  409. }
  410. private void DrawResourceMenu()
  411. {
  412. if (GUILayout.Button("All", GUILayout.Width(50f)) && m_SelectedResource != null)
  413. {
  414. Asset[] assets = m_Controller.GetAssets(m_SelectedResource.Name, m_SelectedResource.Variant);
  415. foreach (Asset asset in assets)
  416. {
  417. SetSelectedAssetInSelectedResource(asset, true);
  418. }
  419. }
  420. if (GUILayout.Button("None", GUILayout.Width(50f)))
  421. {
  422. m_SelectedAssetsInSelectedResource.Clear();
  423. }
  424. m_Controller.AssetSorter = (AssetSorterType)EditorGUILayout.EnumPopup(m_Controller.AssetSorter, GUILayout.Width(60f));
  425. GUILayout.Label(string.Empty);
  426. EditorGUI.BeginDisabledGroup(m_SelectedResource == null || m_SelectedAssetsInSelectedResource.Count <= 0);
  427. {
  428. if (GUILayout.Button(Utility.Text.Format("{0} >>", m_SelectedAssetsInSelectedResource.Count.ToString()), GUILayout.Width(80f)))
  429. {
  430. foreach (Asset asset in m_SelectedAssetsInSelectedResource)
  431. {
  432. UnassignAsset(asset);
  433. }
  434. m_SelectedAssetsInSelectedResource.Clear();
  435. }
  436. }
  437. EditorGUI.EndDisabledGroup();
  438. }
  439. private void DrawSourceAssetsView()
  440. {
  441. m_CurrentSourceRowOnDraw = 0;
  442. m_SourceAssetsViewScroll = EditorGUILayout.BeginScrollView(m_SourceAssetsViewScroll);
  443. {
  444. DrawSourceFolder(m_Controller.SourceAssetRoot);
  445. }
  446. EditorGUILayout.EndScrollView();
  447. }
  448. private void DrawSourceAssetsMenu()
  449. {
  450. HashSet<SourceAsset> selectedSourceAssets = GetSelectedSourceAssets();
  451. EditorGUI.BeginDisabledGroup(m_SelectedResource == null || selectedSourceAssets.Count <= 0);
  452. {
  453. if (GUILayout.Button(Utility.Text.Format("<< {0}", selectedSourceAssets.Count.ToString()), GUILayout.Width(80f)))
  454. {
  455. foreach (SourceAsset sourceAsset in selectedSourceAssets)
  456. {
  457. AssignAsset(sourceAsset, m_SelectedResource);
  458. }
  459. m_SelectedSourceAssets.Clear();
  460. m_CachedSelectedSourceFolders.Clear();
  461. }
  462. }
  463. EditorGUI.EndDisabledGroup();
  464. EditorGUI.BeginDisabledGroup(selectedSourceAssets.Count <= 0);
  465. {
  466. if (GUILayout.Button(Utility.Text.Format("<<< {0}", selectedSourceAssets.Count.ToString()), GUILayout.Width(80f)))
  467. {
  468. int index = 0;
  469. int count = selectedSourceAssets.Count;
  470. foreach (SourceAsset sourceAsset in selectedSourceAssets)
  471. {
  472. EditorUtility.DisplayProgressBar("Add Resources", Utility.Text.Format("{0}/{1} processing...", (++index).ToString(), count.ToString()), (float)index / count);
  473. int dotIndex = sourceAsset.FromRootPath.IndexOf('.');
  474. string name = dotIndex > 0 ? sourceAsset.FromRootPath.Substring(0, dotIndex) : sourceAsset.FromRootPath;
  475. AddResource(name, null, false);
  476. Resource resource = m_Controller.GetResource(name, null);
  477. if (resource == null)
  478. {
  479. continue;
  480. }
  481. AssignAsset(sourceAsset, resource);
  482. }
  483. EditorUtility.DisplayProgressBar("Add Resources", "Complete processing...", 1f);
  484. RefreshResourceTree();
  485. EditorUtility.ClearProgressBar();
  486. m_SelectedSourceAssets.Clear();
  487. m_CachedSelectedSourceFolders.Clear();
  488. }
  489. }
  490. EditorGUI.EndDisabledGroup();
  491. bool hideAssignedSourceAssets = EditorGUILayout.ToggleLeft("Hide Assigned", m_HideAssignedSourceAssets, GUILayout.Width(100f));
  492. if (hideAssignedSourceAssets != m_HideAssignedSourceAssets)
  493. {
  494. m_HideAssignedSourceAssets = hideAssignedSourceAssets;
  495. m_CachedSelectedSourceFolders.Clear();
  496. m_CachedUnselectedSourceFolders.Clear();
  497. m_CachedAssignedSourceFolders.Clear();
  498. m_CachedUnassignedSourceFolders.Clear();
  499. }
  500. GUILayout.Label(string.Empty);
  501. if (GUILayout.Button("Clean", GUILayout.Width(80f)))
  502. {
  503. EditorUtility.DisplayProgressBar("Clean", "Processing...", 0f);
  504. CleanResource();
  505. EditorUtility.ClearProgressBar();
  506. }
  507. if (GUILayout.Button("Save", GUILayout.Width(80f)))
  508. {
  509. EditorUtility.DisplayProgressBar("Save", "Processing...", 0f);
  510. SaveConfiguration();
  511. EditorUtility.ClearProgressBar();
  512. }
  513. }
  514. private void DrawSourceFolder(SourceFolder sourceFolder)
  515. {
  516. if (m_HideAssignedSourceAssets && IsAssignedSourceFolder(sourceFolder))
  517. {
  518. return;
  519. }
  520. bool expand = IsExpandedSourceFolder(sourceFolder);
  521. EditorGUILayout.BeginHorizontal();
  522. {
  523. bool select = IsSelectedSourceFolder(sourceFolder);
  524. if (select != EditorGUILayout.Toggle(select, GUILayout.Width(12f + 14f * sourceFolder.Depth)))
  525. {
  526. select = !select;
  527. SetSelectedSourceFolder(sourceFolder, select);
  528. }
  529. GUILayout.Space(-14f * sourceFolder.Depth);
  530. #if UNITY_2019_3_OR_NEWER
  531. bool foldout = EditorGUI.Foldout(new Rect(18f + 14f * sourceFolder.Depth, 20f * m_CurrentSourceRowOnDraw + 4f, int.MaxValue, 14f), expand, string.Empty, true);
  532. #else
  533. bool foldout = EditorGUI.Foldout(new Rect(18f + 14f * sourceFolder.Depth, 20f * m_CurrentSourceRowOnDraw + 2f, int.MaxValue, 14f), expand, string.Empty, true);
  534. #endif
  535. if (expand != foldout)
  536. {
  537. expand = !expand;
  538. SetExpandedSourceFolder(sourceFolder, expand);
  539. }
  540. #if UNITY_2019_3_OR_NEWER
  541. GUI.DrawTexture(new Rect(32f + 14f * sourceFolder.Depth, 20f * m_CurrentSourceRowOnDraw + 3f, 16f, 16f), SourceFolder.Icon);
  542. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(30f + 14f * sourceFolder.Depth), GUILayout.Height(18f));
  543. #else
  544. GUI.DrawTexture(new Rect(32f + 14f * sourceFolder.Depth, 20f * m_CurrentSourceRowOnDraw + 1f, 16f, 16f), SourceFolder.Icon);
  545. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(26f + 14f * sourceFolder.Depth), GUILayout.Height(18f));
  546. #endif
  547. EditorGUILayout.LabelField(sourceFolder.Name);
  548. }
  549. EditorGUILayout.EndHorizontal();
  550. m_CurrentSourceRowOnDraw++;
  551. if (expand)
  552. {
  553. foreach (SourceFolder subSourceFolder in sourceFolder.GetFolders())
  554. {
  555. DrawSourceFolder(subSourceFolder);
  556. }
  557. foreach (SourceAsset sourceAsset in sourceFolder.GetAssets())
  558. {
  559. DrawSourceAsset(sourceAsset);
  560. }
  561. }
  562. }
  563. private void DrawSourceAsset(SourceAsset sourceAsset)
  564. {
  565. if (m_HideAssignedSourceAssets && IsAssignedSourceAsset(sourceAsset))
  566. {
  567. return;
  568. }
  569. EditorGUILayout.BeginHorizontal();
  570. {
  571. float emptySpace = position.width;
  572. bool select = IsSelectedSourceAsset(sourceAsset);
  573. if (select != EditorGUILayout.Toggle(select, GUILayout.Width(emptySpace - 12f)))
  574. {
  575. select = !select;
  576. SetSelectedSourceAsset(sourceAsset, select);
  577. }
  578. GUILayout.Space(-emptySpace + 24f);
  579. #if UNITY_2019_3_OR_NEWER
  580. GUI.DrawTexture(new Rect(32f + 14f * sourceAsset.Depth, 20f * m_CurrentSourceRowOnDraw + 3f, 16f, 16f), sourceAsset.Icon);
  581. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(30f + 14f * sourceAsset.Depth), GUILayout.Height(18f));
  582. #else
  583. GUI.DrawTexture(new Rect(32f + 14f * sourceAsset.Depth, 20f * m_CurrentSourceRowOnDraw + 1f, 16f, 16f), sourceAsset.Icon);
  584. EditorGUILayout.LabelField(string.Empty, GUILayout.Width(26f + 14f * sourceAsset.Depth), GUILayout.Height(18f));
  585. #endif
  586. EditorGUILayout.LabelField(sourceAsset.Name);
  587. Asset asset = m_Controller.GetAsset(sourceAsset.Guid);
  588. EditorGUILayout.LabelField(asset != null ? GetResourceFullName(asset.Resource.Name, asset.Resource.Variant) : string.Empty, GUILayout.Width(position.width * 0.15f));
  589. }
  590. EditorGUILayout.EndHorizontal();
  591. m_CurrentSourceRowOnDraw++;
  592. }
  593. private void ChangeSelectedResource(Resource resource)
  594. {
  595. if (m_SelectedResource == resource)
  596. {
  597. return;
  598. }
  599. m_SelectedResource = resource;
  600. m_SelectedAssetsInSelectedResource.Clear();
  601. }
  602. private void SaveConfiguration()
  603. {
  604. if (m_Controller.Save())
  605. {
  606. Debug.Log("Save configuration success.");
  607. }
  608. else
  609. {
  610. Debug.LogWarning("Save configuration failure.");
  611. }
  612. }
  613. private void AddResource(string name, string variant, bool refresh)
  614. {
  615. if (variant == string.Empty)
  616. {
  617. variant = null;
  618. }
  619. string fullName = GetResourceFullName(name, variant);
  620. if (m_Controller.AddResource(name, variant, null, LoadType.LoadFromFile, false))
  621. {
  622. if (refresh)
  623. {
  624. RefreshResourceTree();
  625. }
  626. Debug.Log(Utility.Text.Format("Add resource '{0}' success.", fullName));
  627. m_MenuState = MenuState.Normal;
  628. }
  629. else
  630. {
  631. Debug.LogWarning(Utility.Text.Format("Add resource '{0}' failure.", fullName));
  632. }
  633. }
  634. private void RenameResource(Resource resource, string newName, string newVariant)
  635. {
  636. if (resource == null)
  637. {
  638. Debug.LogWarning("Resource is invalid.");
  639. return;
  640. }
  641. if (newVariant == string.Empty)
  642. {
  643. newVariant = null;
  644. }
  645. string oldFullName = resource.FullName;
  646. string newFullName = GetResourceFullName(newName, newVariant);
  647. if (m_Controller.RenameResource(resource.Name, resource.Variant, newName, newVariant))
  648. {
  649. RefreshResourceTree();
  650. Debug.Log(Utility.Text.Format("Rename resource '{0}' to '{1}' success.", oldFullName, newFullName));
  651. m_MenuState = MenuState.Normal;
  652. }
  653. else
  654. {
  655. Debug.LogWarning(Utility.Text.Format("Rename resource '{0}' to '{1}' failure.", oldFullName, newFullName));
  656. }
  657. }
  658. private void RemoveResource()
  659. {
  660. string fullName = m_SelectedResource.FullName;
  661. if (m_Controller.RemoveResource(m_SelectedResource.Name, m_SelectedResource.Variant))
  662. {
  663. ChangeSelectedResource(null);
  664. RefreshResourceTree();
  665. Debug.Log(Utility.Text.Format("Remove resource '{0}' success.", fullName));
  666. }
  667. else
  668. {
  669. Debug.LogWarning(Utility.Text.Format("Remove resource '{0}' failure.", fullName));
  670. }
  671. }
  672. private void SetResourceLoadType(LoadType loadType)
  673. {
  674. string fullName = m_SelectedResource.FullName;
  675. if (m_Controller.SetResourceLoadType(m_SelectedResource.Name, m_SelectedResource.Variant, loadType))
  676. {
  677. Debug.Log(Utility.Text.Format("Set resource '{0}' load type to '{1}' success.", fullName, loadType.ToString()));
  678. }
  679. else
  680. {
  681. Debug.LogWarning(Utility.Text.Format("Set resource '{0}' load type to '{1}' failure.", fullName, loadType.ToString()));
  682. }
  683. }
  684. private void SetResourcePacked(bool packed)
  685. {
  686. string fullName = m_SelectedResource.FullName;
  687. if (m_Controller.SetResourcePacked(m_SelectedResource.Name, m_SelectedResource.Variant, packed))
  688. {
  689. Debug.Log(Utility.Text.Format("{1} resource '{0}' success.", fullName, packed ? "Pack" : "Unpack"));
  690. }
  691. else
  692. {
  693. Debug.LogWarning(Utility.Text.Format("{1} resource '{0}' failure.", fullName, packed ? "Pack" : "Unpack"));
  694. }
  695. }
  696. private void AssignAsset(SourceAsset sourceAsset, Resource resource)
  697. {
  698. if (!m_Controller.AssignAsset(sourceAsset.Guid, resource.Name, resource.Variant))
  699. {
  700. Debug.LogWarning(Utility.Text.Format("Assign asset '{0}' to resource '{1}' failure.", sourceAsset.Name, resource.FullName));
  701. }
  702. }
  703. private void UnassignAsset(Asset asset)
  704. {
  705. if (!m_Controller.UnassignAsset(asset.Guid))
  706. {
  707. Debug.LogWarning(Utility.Text.Format("Unassign asset '{0}' from resource '{1}' failure.", asset.Guid, m_SelectedResource.FullName));
  708. }
  709. }
  710. private void CleanResource()
  711. {
  712. int unknownAssetCount = m_Controller.RemoveUnknownAssets();
  713. int unusedResourceCount = m_Controller.RemoveUnusedResources();
  714. RefreshResourceTree();
  715. Debug.Log(Utility.Text.Format("Clean complete, {0} unknown assets and {1} unused resources has been removed.", unknownAssetCount.ToString(), unusedResourceCount.ToString()));
  716. }
  717. private void RefreshResourceTree()
  718. {
  719. m_ResourceRoot.Clear();
  720. Resource[] resources = m_Controller.GetResources();
  721. foreach (Resource resource in resources)
  722. {
  723. string[] splitedPath = resource.Name.Split('/');
  724. ResourceFolder folder = m_ResourceRoot;
  725. for (int i = 0; i < splitedPath.Length - 1; i++)
  726. {
  727. ResourceFolder subFolder = folder.GetFolder(splitedPath[i]);
  728. folder = subFolder == null ? folder.AddFolder(splitedPath[i]) : subFolder;
  729. }
  730. string fullName = resource.Variant != null ? Utility.Text.Format("{0}.{1}", splitedPath[splitedPath.Length - 1], resource.Variant) : splitedPath[splitedPath.Length - 1];
  731. folder.AddItem(fullName, resource);
  732. }
  733. }
  734. private bool IsExpandedResourceFolder(ResourceFolder folder)
  735. {
  736. return m_ExpandedResourceFolderNames.Contains(folder.FromRootPath);
  737. }
  738. private void SetExpandedResourceFolder(ResourceFolder folder, bool expand)
  739. {
  740. if (expand)
  741. {
  742. m_ExpandedResourceFolderNames.Add(folder.FromRootPath);
  743. }
  744. else
  745. {
  746. m_ExpandedResourceFolderNames.Remove(folder.FromRootPath);
  747. }
  748. }
  749. private bool IsSelectedAssetInSelectedResource(Asset asset)
  750. {
  751. return m_SelectedAssetsInSelectedResource.Contains(asset);
  752. }
  753. private void SetSelectedAssetInSelectedResource(Asset asset, bool select)
  754. {
  755. if (select)
  756. {
  757. m_SelectedAssetsInSelectedResource.Add(asset);
  758. }
  759. else
  760. {
  761. m_SelectedAssetsInSelectedResource.Remove(asset);
  762. }
  763. }
  764. private bool IsExpandedSourceFolder(SourceFolder sourceFolder)
  765. {
  766. return m_ExpandedSourceFolders.Contains(sourceFolder);
  767. }
  768. private void SetExpandedSourceFolder(SourceFolder sourceFolder, bool expand)
  769. {
  770. if (expand)
  771. {
  772. m_ExpandedSourceFolders.Add(sourceFolder);
  773. }
  774. else
  775. {
  776. m_ExpandedSourceFolders.Remove(sourceFolder);
  777. }
  778. }
  779. private bool IsSelectedSourceFolder(SourceFolder sourceFolder)
  780. {
  781. if (m_CachedSelectedSourceFolders.Contains(sourceFolder))
  782. {
  783. return true;
  784. }
  785. if (m_CachedUnselectedSourceFolders.Contains(sourceFolder))
  786. {
  787. return false;
  788. }
  789. foreach (SourceAsset sourceAsset in sourceFolder.GetAssets())
  790. {
  791. if (m_HideAssignedSourceAssets && IsAssignedSourceAsset(sourceAsset))
  792. {
  793. continue;
  794. }
  795. if (!IsSelectedSourceAsset(sourceAsset))
  796. {
  797. m_CachedUnselectedSourceFolders.Add(sourceFolder);
  798. return false;
  799. }
  800. }
  801. foreach (SourceFolder subSourceFolder in sourceFolder.GetFolders())
  802. {
  803. if (m_HideAssignedSourceAssets && IsAssignedSourceFolder(sourceFolder))
  804. {
  805. continue;
  806. }
  807. if (!IsSelectedSourceFolder(subSourceFolder))
  808. {
  809. m_CachedUnselectedSourceFolders.Add(sourceFolder);
  810. return false;
  811. }
  812. }
  813. m_CachedSelectedSourceFolders.Add(sourceFolder);
  814. return true;
  815. }
  816. private void SetSelectedSourceFolder(SourceFolder sourceFolder, bool select)
  817. {
  818. if (select)
  819. {
  820. m_CachedSelectedSourceFolders.Add(sourceFolder);
  821. m_CachedUnselectedSourceFolders.Remove(sourceFolder);
  822. SourceFolder folder = sourceFolder;
  823. while (folder != null)
  824. {
  825. m_CachedUnselectedSourceFolders.Remove(folder);
  826. folder = folder.Folder;
  827. }
  828. }
  829. else
  830. {
  831. m_CachedSelectedSourceFolders.Remove(sourceFolder);
  832. m_CachedUnselectedSourceFolders.Add(sourceFolder);
  833. SourceFolder folder = sourceFolder;
  834. while (folder != null)
  835. {
  836. m_CachedSelectedSourceFolders.Remove(folder);
  837. folder = folder.Folder;
  838. }
  839. }
  840. foreach (SourceAsset sourceAsset in sourceFolder.GetAssets())
  841. {
  842. if (m_HideAssignedSourceAssets && IsAssignedSourceAsset(sourceAsset))
  843. {
  844. continue;
  845. }
  846. SetSelectedSourceAsset(sourceAsset, select);
  847. }
  848. foreach (SourceFolder subSourceFolder in sourceFolder.GetFolders())
  849. {
  850. if (m_HideAssignedSourceAssets && IsAssignedSourceFolder(subSourceFolder))
  851. {
  852. continue;
  853. }
  854. SetSelectedSourceFolder(subSourceFolder, select);
  855. }
  856. }
  857. private bool IsSelectedSourceAsset(SourceAsset sourceAsset)
  858. {
  859. return m_SelectedSourceAssets.Contains(sourceAsset);
  860. }
  861. private void SetSelectedSourceAsset(SourceAsset sourceAsset, bool select)
  862. {
  863. if (select)
  864. {
  865. m_SelectedSourceAssets.Add(sourceAsset);
  866. SourceFolder folder = sourceAsset.Folder;
  867. while (folder != null)
  868. {
  869. m_CachedUnselectedSourceFolders.Remove(folder);
  870. folder = folder.Folder;
  871. }
  872. }
  873. else
  874. {
  875. m_SelectedSourceAssets.Remove(sourceAsset);
  876. SourceFolder folder = sourceAsset.Folder;
  877. while (folder != null)
  878. {
  879. m_CachedSelectedSourceFolders.Remove(folder);
  880. folder = folder.Folder;
  881. }
  882. }
  883. }
  884. private bool IsAssignedSourceAsset(SourceAsset sourceAsset)
  885. {
  886. if (m_CachedAssignedSourceAssets.Contains(sourceAsset))
  887. {
  888. return true;
  889. }
  890. if (m_CachedUnassignedSourceAssets.Contains(sourceAsset))
  891. {
  892. return false;
  893. }
  894. return m_Controller.GetAsset(sourceAsset.Guid) != null;
  895. }
  896. private bool IsAssignedSourceFolder(SourceFolder sourceFolder)
  897. {
  898. if (m_CachedAssignedSourceFolders.Contains(sourceFolder))
  899. {
  900. return true;
  901. }
  902. if (m_CachedUnassignedSourceFolders.Contains(sourceFolder))
  903. {
  904. return false;
  905. }
  906. foreach (SourceAsset sourceAsset in sourceFolder.GetAssets())
  907. {
  908. if (!IsAssignedSourceAsset(sourceAsset))
  909. {
  910. m_CachedUnassignedSourceFolders.Add(sourceFolder);
  911. return false;
  912. }
  913. }
  914. foreach (SourceFolder subSourceFolder in sourceFolder.GetFolders())
  915. {
  916. if (!IsAssignedSourceFolder(subSourceFolder))
  917. {
  918. m_CachedUnassignedSourceFolders.Add(sourceFolder);
  919. return false;
  920. }
  921. }
  922. m_CachedAssignedSourceFolders.Add(sourceFolder);
  923. return true;
  924. }
  925. private HashSet<SourceAsset> GetSelectedSourceAssets()
  926. {
  927. if (!m_HideAssignedSourceAssets)
  928. {
  929. return m_SelectedSourceAssets;
  930. }
  931. HashSet<SourceAsset> selectedUnassignedSourceAssets = new HashSet<SourceAsset>();
  932. foreach (SourceAsset sourceAsset in m_SelectedSourceAssets)
  933. {
  934. if (!IsAssignedSourceAsset(sourceAsset))
  935. {
  936. selectedUnassignedSourceAssets.Add(sourceAsset);
  937. }
  938. }
  939. return selectedUnassignedSourceAssets;
  940. }
  941. private string GetResourceFullName(string name, string variant)
  942. {
  943. return variant != null ? Utility.Text.Format("{0}.{1}", name, variant) : name;
  944. }
  945. private void OnLoadingResource(int index, int count)
  946. {
  947. EditorUtility.DisplayProgressBar("Loading Resources", Utility.Text.Format("Loading resources, {0}/{1} loaded.", index.ToString(), count.ToString()), (float)index / count);
  948. }
  949. private void OnLoadingAsset(int index, int count)
  950. {
  951. EditorUtility.DisplayProgressBar("Loading Assets", Utility.Text.Format("Loading assets, {0}/{1} loaded.", index.ToString(), count.ToString()), (float)index / count);
  952. }
  953. private void OnLoadCompleted()
  954. {
  955. EditorUtility.ClearProgressBar();
  956. }
  957. private void OnAssetAssigned(SourceAsset[] sourceAssets)
  958. {
  959. HashSet<SourceFolder> affectedFolders = new HashSet<SourceFolder>();
  960. foreach (SourceAsset sourceAsset in sourceAssets)
  961. {
  962. m_CachedAssignedSourceAssets.Add(sourceAsset);
  963. m_CachedUnassignedSourceAssets.Remove(sourceAsset);
  964. affectedFolders.Add(sourceAsset.Folder);
  965. }
  966. foreach (SourceFolder sourceFolder in affectedFolders)
  967. {
  968. SourceFolder folder = sourceFolder;
  969. while (folder != null)
  970. {
  971. m_CachedUnassignedSourceFolders.Remove(folder);
  972. folder = folder.Folder;
  973. }
  974. }
  975. }
  976. private void OnAssetUnassigned(SourceAsset[] sourceAssets)
  977. {
  978. HashSet<SourceFolder> affectedFolders = new HashSet<SourceFolder>();
  979. foreach (SourceAsset sourceAsset in sourceAssets)
  980. {
  981. m_CachedAssignedSourceAssets.Remove(sourceAsset);
  982. m_CachedUnassignedSourceAssets.Add(sourceAsset);
  983. affectedFolders.Add(sourceAsset.Folder);
  984. }
  985. foreach (SourceFolder sourceFolder in affectedFolders)
  986. {
  987. SourceFolder folder = sourceFolder;
  988. while (folder != null)
  989. {
  990. m_CachedSelectedSourceFolders.Remove(folder);
  991. m_CachedAssignedSourceFolders.Remove(folder);
  992. m_CachedUnassignedSourceFolders.Add(folder);
  993. folder = folder.Folder;
  994. }
  995. }
  996. }
  997. }
  998. }