FR2_Ref.cs 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using UnityEditor;
  7. using UnityEngine;
  8. using Object = UnityEngine.Object;
  9. namespace vietlabs.fr2
  10. {
  11. public class FR2_SceneRef : FR2_Ref
  12. {
  13. internal static Dictionary<string, Type> CacheType = new Dictionary<string, Type>();
  14. // ------------------------- Ref in scene
  15. private static Action<Dictionary<string, FR2_Ref>> onFindRefInSceneComplete;
  16. private static Dictionary<string, FR2_Ref> refs = new Dictionary<string, FR2_Ref>();
  17. private static string[] cacheAssetGuids;
  18. public string sceneFullPath = "";
  19. public string scenePath = "";
  20. public string targetType;
  21. public HashSet<string> usingType = new HashSet<string>();
  22. public FR2_SceneRef(int index, int depth, FR2_Asset asset, FR2_Asset by) : base(index, depth, asset, by)
  23. {
  24. isSceneRef = false;
  25. }
  26. // public override string ToString()
  27. // {
  28. // return "SceneRef: " + sceneFullPath;
  29. // }
  30. public FR2_SceneRef(int depth, Object target) : base(0, depth, null, null)
  31. {
  32. component = target;
  33. this.depth = depth;
  34. isSceneRef = true;
  35. var obj = target as GameObject;
  36. if (obj == null)
  37. {
  38. var com = target as Component;
  39. if (com != null)
  40. {
  41. obj = com.gameObject;
  42. }
  43. }
  44. scenePath = FR2_Unity.GetGameObjectPath(obj, false);
  45. if (component == null)
  46. {
  47. return;
  48. }
  49. sceneFullPath = scenePath + component.name;
  50. targetType = component.GetType().Name;
  51. }
  52. public static IWindow window { get; set; }
  53. public override bool isSelected()
  54. {
  55. return component == null ? false : FR2_Bookmark.Contains(component);
  56. }
  57. public void Draw(Rect r, IWindow window, bool showDetails)
  58. {
  59. bool selected = isSelected();
  60. DrawToogleSelect(r);
  61. var margin = 2;
  62. var left = new Rect(r);
  63. left.width = r.width / 3f;
  64. var right = new Rect(r);
  65. right.xMin += left.width + margin;
  66. //Debug.Log("draw scene "+ selected);
  67. if ( /* FR2_Setting.PingRow && */ Event.current.type == EventType.MouseDown && Event.current.button == 0)
  68. {
  69. Rect pingRect = FR2_Setting.PingRow
  70. ? new Rect(0, r.y, r.x + r.width, r.height)
  71. : left;
  72. if (pingRect.Contains(Event.current.mousePosition))
  73. {
  74. if (Event.current.control || Event.current.command)
  75. {
  76. if (selected)
  77. {
  78. FR2_Bookmark.Remove(this);
  79. }
  80. else
  81. {
  82. FR2_Bookmark.Add(this);
  83. }
  84. if (window != null) window.Repaint();
  85. } else {
  86. EditorGUIUtility.PingObject(component);
  87. }
  88. Event.current.Use();
  89. }
  90. }
  91. EditorGUI.ObjectField(showDetails ? left : r, GUIContent.none, component, typeof(GameObject), true);
  92. if (!showDetails) return;
  93. bool drawPath = FR2_Setting.GroupMode != FR2_RefDrawer.Mode.Folder;
  94. float pathW = drawPath ? EditorStyles.miniLabel.CalcSize(new GUIContent(scenePath)).x : 0;
  95. string assetName = component.name;
  96. // if(usingType!= null && usingType.Count > 0)
  97. // {
  98. // assetName += " -> ";
  99. // foreach(var item in usingType)
  100. // {
  101. // assetName += item + " - ";
  102. // }
  103. // assetName = assetName.Substring(0, assetName.Length - 3);
  104. // }
  105. Color cc = FR2_Cache.Api.setting.SelectedColor;
  106. var lableRect = new Rect(
  107. right.x,
  108. right.y,
  109. pathW + EditorStyles.boldLabel.CalcSize(new GUIContent(assetName)).x,
  110. right.height);
  111. if (selected)
  112. {
  113. Color c = GUI.color;
  114. GUI.color = cc;
  115. GUI.DrawTexture(lableRect, EditorGUIUtility.whiteTexture);
  116. GUI.color = c;
  117. }
  118. if (drawPath)
  119. {
  120. GUI.Label(LeftRect(pathW, ref right), scenePath, EditorStyles.miniLabel);
  121. right.xMin -= 4f;
  122. GUI.Label(right, assetName, EditorStyles.boldLabel);
  123. }
  124. else
  125. {
  126. GUI.Label(right, assetName);
  127. }
  128. if (!FR2_Setting.ShowUsedByClassed || usingType == null)
  129. {
  130. return;
  131. }
  132. float sub = 10;
  133. var re = new Rect(r.x + r.width - sub, r.y, 20, r.height);
  134. Type t = null;
  135. foreach (string item in usingType)
  136. {
  137. string name = item;
  138. if (!CacheType.TryGetValue(item, out t))
  139. {
  140. t = FR2_Unity.GetType(name);
  141. // if (t == null)
  142. // {
  143. // continue;
  144. // }
  145. CacheType.Add(item, t);
  146. }
  147. GUIContent content;
  148. var width = 0.0f;
  149. if (!FR2_Asset.cacheImage.TryGetValue(name, out content))
  150. {
  151. if (t == null)
  152. {
  153. content = new GUIContent(name);
  154. }
  155. else
  156. {
  157. Texture text = EditorGUIUtility.ObjectContent(null, t).image;
  158. if (text == null)
  159. {
  160. content = new GUIContent(name);
  161. }
  162. else
  163. {
  164. content = new GUIContent(text, name);
  165. }
  166. }
  167. FR2_Asset.cacheImage.Add(name, content);
  168. }
  169. if (content.image == null)
  170. {
  171. width = EditorStyles.label.CalcSize(content).x;
  172. }
  173. else
  174. {
  175. width = 20;
  176. }
  177. re.x -= width;
  178. re.width = width;
  179. GUI.Label(re, content);
  180. re.x -= margin; // margin;
  181. }
  182. // var nameW = EditorStyles.boldLabel.CalcSize(new GUIContent(assetName)).x;
  183. }
  184. private Rect LeftRect(float w, ref Rect rect)
  185. {
  186. rect.x += w;
  187. rect.width -= w;
  188. return new Rect(rect.x - w, rect.y, w, rect.height);
  189. }
  190. // ------------------------- Scene use scene objects
  191. public static Dictionary<string, FR2_Ref> FindSceneUseSceneObjects(GameObject[] targets)
  192. {
  193. var results = new Dictionary<string, FR2_Ref>();
  194. GameObject[] objs = Selection.gameObjects;
  195. for (var i = 0; i < objs.Length; i++)
  196. {
  197. if (FR2_Unity.IsInAsset(objs[i]))
  198. {
  199. continue;
  200. }
  201. string key = objs[i].GetInstanceID().ToString();
  202. if (!results.ContainsKey(key))
  203. {
  204. results.Add(key, new FR2_SceneRef(0, objs[i]));
  205. }
  206. Component[] coms = objs[i].GetComponents<Component>();
  207. Dictionary<Component, HashSet<FR2_SceneCache.HashValue>> SceneCache = FR2_SceneCache.Api.cache;
  208. for (var j = 0; j < coms.Length; j++)
  209. {
  210. HashSet<FR2_SceneCache.HashValue> hash = null;
  211. if (coms[j] == null) continue; // missing component
  212. if (SceneCache.TryGetValue(coms[j], out hash))
  213. {
  214. foreach (FR2_SceneCache.HashValue item in hash)
  215. {
  216. if (item.isSceneObject)
  217. {
  218. Object obj = item.target;
  219. string key1 = obj.GetInstanceID().ToString();
  220. if (!results.ContainsKey(key1))
  221. {
  222. results.Add(key1, new FR2_SceneRef(1, obj));
  223. }
  224. }
  225. }
  226. }
  227. }
  228. }
  229. return results;
  230. }
  231. // ------------------------- Scene in scene
  232. public static Dictionary<string, FR2_Ref> FindSceneInScene(GameObject[] targets)
  233. {
  234. var results = new Dictionary<string, FR2_Ref>();
  235. GameObject[] objs = Selection.gameObjects;
  236. for (var i = 0; i < objs.Length; i++)
  237. {
  238. if (FR2_Unity.IsInAsset(objs[i]))
  239. {
  240. continue;
  241. }
  242. string key = objs[i].GetInstanceID().ToString();
  243. if (!results.ContainsKey(key))
  244. {
  245. results.Add(key, new FR2_SceneRef(0, objs[i]));
  246. }
  247. foreach (KeyValuePair<Component, HashSet<FR2_SceneCache.HashValue>> item in FR2_SceneCache.Api.cache)
  248. foreach (FR2_SceneCache.HashValue item1 in item.Value)
  249. {
  250. // if(item.Key.gameObject.name == "ScenesManager")
  251. // Debug.Log(item1.objectReferenceValue);
  252. GameObject ob = null;
  253. if (item1.target is GameObject)
  254. {
  255. ob = item1.target as GameObject;
  256. }
  257. else
  258. {
  259. var com = item1.target as Component;
  260. if (com == null)
  261. {
  262. continue;
  263. }
  264. ob = com.gameObject;
  265. }
  266. if (ob == null)
  267. {
  268. continue;
  269. }
  270. if (ob != objs[i])
  271. {
  272. continue;
  273. }
  274. key = item.Key.GetInstanceID().ToString();
  275. if (!results.ContainsKey(key))
  276. {
  277. results.Add(key, new FR2_SceneRef(1, item.Key));
  278. }
  279. (results[key] as FR2_SceneRef).usingType.Add(item1.target.GetType().FullName);
  280. }
  281. }
  282. return results;
  283. }
  284. public static Dictionary<string, FR2_Ref> FindRefInScene(string[] assetGUIDs, bool depth,
  285. Action<Dictionary<string, FR2_Ref>> onComplete, IWindow win)
  286. {
  287. // var watch = new System.Diagnostics.Stopwatch();
  288. // watch.Start();
  289. window = win;
  290. cacheAssetGuids = assetGUIDs;
  291. onFindRefInSceneComplete = onComplete;
  292. if (FR2_SceneCache.ready)
  293. {
  294. FindRefInScene();
  295. }
  296. else
  297. {
  298. FR2_SceneCache.onReady -= FindRefInScene;
  299. FR2_SceneCache.onReady += FindRefInScene;
  300. }
  301. return refs;
  302. }
  303. private static void FindRefInScene()
  304. {
  305. refs = new Dictionary<string, FR2_Ref>();
  306. for (var i = 0; i < cacheAssetGuids.Length; i++)
  307. {
  308. FR2_Asset asset = FR2_Cache.Api.Get(cacheAssetGuids[i]);
  309. if (asset == null)
  310. {
  311. continue;
  312. }
  313. Add(refs, asset, 0);
  314. ApplyFilter(refs, asset);
  315. }
  316. if (onFindRefInSceneComplete != null)
  317. {
  318. onFindRefInSceneComplete(refs);
  319. }
  320. FR2_SceneCache.onReady -= FindRefInScene;
  321. // UnityEngine.Debug.Log("Time find ref in scene " + watch.ElapsedMilliseconds);
  322. }
  323. private static void FilterAll(Dictionary<string, FR2_Ref> refs, Object obj, string targetPath)
  324. {
  325. // ApplyFilter(refs, obj, targetPath);
  326. }
  327. private static void ApplyFilter(Dictionary<string, FR2_Ref> refs, FR2_Asset asset)
  328. {
  329. string targetPath = AssetDatabase.GUIDToAssetPath(asset.guid);
  330. if (string.IsNullOrEmpty(targetPath))
  331. {
  332. return; // asset not found - might be deleted!
  333. }
  334. //asset being moved!
  335. if (targetPath != asset.assetPath)
  336. {
  337. asset.MarkAsDirty(true, false);
  338. }
  339. Object target = AssetDatabase.LoadAssetAtPath(targetPath, typeof(Object));
  340. if (target == null)
  341. {
  342. //Debug.LogWarning("target is null");
  343. return;
  344. }
  345. bool targetIsGameobject = target is GameObject;
  346. if (targetIsGameobject)
  347. {
  348. foreach (GameObject item in FR2_Unity.getAllObjsInCurScene())
  349. {
  350. if (FR2_Unity.CheckIsPrefab(item))
  351. {
  352. string itemGUID = FR2_Unity.GetPrefabParent(item);
  353. // Debug.Log(item.name + " itemGUID: " + itemGUID);
  354. // Debug.Log(target.name + " asset.guid: " + asset.guid);
  355. if (itemGUID == asset.guid)
  356. {
  357. Add(refs, item, 1);
  358. }
  359. }
  360. }
  361. }
  362. string dir = Path.GetDirectoryName(targetPath);
  363. if (FR2_SceneCache.Api.folderCache.ContainsKey(dir))
  364. {
  365. foreach (Component item in FR2_SceneCache.Api.folderCache[dir])
  366. {
  367. if (FR2_SceneCache.Api.cache.ContainsKey(item))
  368. {
  369. foreach (FR2_SceneCache.HashValue item1 in FR2_SceneCache.Api.cache[item])
  370. {
  371. if (targetPath == AssetDatabase.GetAssetPath(item1.target))
  372. {
  373. Add(refs, item, 1);
  374. }
  375. }
  376. }
  377. }
  378. }
  379. }
  380. private static void Add(Dictionary<string, FR2_Ref> refs, FR2_Asset asset, int depth)
  381. {
  382. string targetId = asset.guid;
  383. if (!refs.ContainsKey(targetId))
  384. {
  385. refs.Add(targetId, new FR2_Ref(0, depth, asset, null));
  386. }
  387. }
  388. private static void Add(Dictionary<string, FR2_Ref> refs, Object target, int depth)
  389. {
  390. string targetId = target.GetInstanceID().ToString();
  391. if (!refs.ContainsKey(targetId))
  392. {
  393. refs.Add(targetId, new FR2_SceneRef(depth, target));
  394. }
  395. }
  396. }
  397. public class FR2_Ref
  398. {
  399. static int CSVSorter(FR2_Ref item1, FR2_Ref item2)
  400. {
  401. var r = item1.depth.CompareTo(item2.depth);
  402. if (r != 0) return r;
  403. var t = item1.type.CompareTo(item2.type);
  404. if (t != 0) return t;
  405. return item1.index.CompareTo(item2.index);
  406. }
  407. public static FR2_Ref[] FromDict(Dictionary<string, FR2_Ref> dict)
  408. {
  409. if (dict == null || dict.Count == 0) return null;
  410. var result = new List<FR2_Ref>();
  411. foreach (var kvp in dict)
  412. {
  413. if (kvp.Value == null) continue;
  414. if (kvp.Value.asset == null) continue;
  415. result.Add(kvp.Value);
  416. }
  417. result.Sort(CSVSorter);
  418. return result.ToArray();
  419. }
  420. public static FR2_Ref[] FromList(List<FR2_Ref> list)
  421. {
  422. if (list == null || list.Count == 0) return null;
  423. list.Sort(CSVSorter);
  424. var result = new List<FR2_Ref>();
  425. for (int i = 0; i < list.Count; i++)
  426. {
  427. if (list[i].asset == null) continue;
  428. result.Add(list[i]);
  429. }
  430. return result.ToArray();
  431. }
  432. public FR2_Asset addBy;
  433. public FR2_Asset asset;
  434. public Object component;
  435. public int depth;
  436. public string group;
  437. public int index;
  438. public bool isSceneRef;
  439. public int matchingScore;
  440. public int type;
  441. public override string ToString()
  442. {
  443. if (isSceneRef)
  444. {
  445. var sr = (FR2_SceneRef) this;
  446. return sr.scenePath;
  447. }
  448. return asset.assetPath;
  449. }
  450. public FR2_Ref(int index, int depth, FR2_Asset asset, FR2_Asset by)
  451. {
  452. this.index = index;
  453. this.depth = depth;
  454. this.asset = asset;
  455. if (asset != null)
  456. {
  457. type = AssetType.GetIndex(asset.extension);
  458. }
  459. addBy = by;
  460. // isSceneRef = false;
  461. }
  462. public FR2_Ref(int index, int depth, FR2_Asset asset, FR2_Asset by, string group) : this(index, depth, asset,
  463. by)
  464. {
  465. this.group = group;
  466. // isSceneRef = false;
  467. }
  468. public string GetSceneObjId()
  469. {
  470. if (component == null)
  471. {
  472. return string.Empty;
  473. }
  474. return component.GetInstanceID().ToString();
  475. }
  476. public virtual bool isSelected()
  477. {
  478. return FR2_Bookmark.Contains(asset.guid);
  479. }
  480. public virtual void DrawToogleSelect(Rect r)
  481. {
  482. var s = isSelected();
  483. r.width = 16f;
  484. if (!GUI2.Toggle(r, ref s)) return;
  485. if (s)
  486. {
  487. FR2_Bookmark.Add(this);
  488. }
  489. else
  490. {
  491. FR2_Bookmark.Remove(this);
  492. }
  493. }
  494. // public FR2_Ref(int depth, UnityEngine.Object target)
  495. // {
  496. // this.component = target;
  497. // this.depth = depth;
  498. // // isSceneRef = true;
  499. // }
  500. internal List<FR2_Ref> Append(Dictionary<string, FR2_Ref> dict, params string[] guidList)
  501. {
  502. var result = new List<FR2_Ref>();
  503. if (FR2_Cache.Api.disabled)
  504. {
  505. return result;
  506. }
  507. if (!FR2_Cache.isReady)
  508. {
  509. Debug.LogWarning("Cache not yet ready! Please wait!");
  510. return result;
  511. }
  512. //filter to remove items that already in dictionary
  513. for (var i = 0; i < guidList.Length; i++)
  514. {
  515. string guid = guidList[i];
  516. if (dict.ContainsKey(guid))
  517. {
  518. continue;
  519. }
  520. FR2_Asset child = FR2_Cache.Api.Get(guid);
  521. if (child == null)
  522. {
  523. continue;
  524. }
  525. var r = new FR2_Ref(dict.Count, depth + 1, child, asset);
  526. if (!asset.IsFolder)
  527. {
  528. dict.Add(guid, r);
  529. }
  530. result.Add(r);
  531. }
  532. return result;
  533. }
  534. internal void AppendUsedBy(Dictionary<string, FR2_Ref> result, bool deep)
  535. {
  536. // var list = Append(result, FR2_Asset.FindUsedByGUIDs(asset).ToArray());
  537. // if (!deep) return;
  538. // // Add next-level
  539. // for (var i = 0;i < list.Count;i ++)
  540. // {
  541. // list[i].AppendUsedBy(result, true);
  542. // }
  543. Dictionary<string, FR2_Asset> h = asset.UsedByMap;
  544. List<FR2_Ref> list = deep ? new List<FR2_Ref>() : null;
  545. if (asset.UsedByMap == null) return;
  546. foreach (KeyValuePair<string, FR2_Asset> kvp in h)
  547. {
  548. string guid = kvp.Key;
  549. if (result.ContainsKey(guid))
  550. {
  551. continue;
  552. }
  553. FR2_Asset child = FR2_Cache.Api.Get(guid);
  554. if (child == null)
  555. {
  556. continue;
  557. }
  558. if (child.IsMissing)
  559. {
  560. continue;
  561. }
  562. var r = new FR2_Ref(result.Count, depth + 1, child, asset);
  563. if (!asset.IsFolder)
  564. {
  565. result.Add(guid, r);
  566. }
  567. if (deep)
  568. {
  569. list.Add(r);
  570. }
  571. }
  572. if (!deep)
  573. {
  574. return;
  575. }
  576. foreach (FR2_Ref item in list)
  577. {
  578. item.AppendUsedBy(result, true);
  579. }
  580. }
  581. internal void AppendUsage(Dictionary<string, FR2_Ref> result, bool deep)
  582. {
  583. Dictionary<string, HashSet<int>> h = asset.UseGUIDs;
  584. List<FR2_Ref> list = deep ? new List<FR2_Ref>() : null;
  585. foreach (KeyValuePair<string, HashSet<int>> kvp in h)
  586. {
  587. string guid = kvp.Key;
  588. if (result.ContainsKey(guid))
  589. {
  590. continue;
  591. }
  592. FR2_Asset child = FR2_Cache.Api.Get(guid);
  593. if (child == null)
  594. {
  595. continue;
  596. }
  597. if (child.IsMissing)
  598. {
  599. continue;
  600. }
  601. var r = new FR2_Ref(result.Count, depth + 1, child, asset);
  602. if (!asset.IsFolder)
  603. {
  604. result.Add(guid, r);
  605. }
  606. if (deep)
  607. {
  608. list.Add(r);
  609. }
  610. }
  611. if (!deep)
  612. {
  613. return;
  614. }
  615. foreach (FR2_Ref item in list)
  616. {
  617. item.AppendUsage(result, true);
  618. }
  619. }
  620. // --------------------- STATIC UTILS -----------------------
  621. internal static Dictionary<string, FR2_Ref> FindRefs(string[] guids, bool usageOrUsedBy, bool addFolder)
  622. {
  623. var dict = new Dictionary<string, FR2_Ref>();
  624. var list = new List<FR2_Ref>();
  625. for (var i = 0; i < guids.Length; i++)
  626. {
  627. string guid = guids[i];
  628. if (dict.ContainsKey(guid))
  629. {
  630. continue;
  631. }
  632. FR2_Asset asset = FR2_Cache.Api.Get(guid);
  633. if (asset == null)
  634. {
  635. continue;
  636. }
  637. var r = new FR2_Ref(i, 0, asset, null);
  638. if (!asset.IsFolder || addFolder)
  639. {
  640. dict.Add(guid, r);
  641. }
  642. list.Add(r);
  643. }
  644. for (var i = 0; i < list.Count; i++)
  645. {
  646. if (usageOrUsedBy)
  647. {
  648. list[i].AppendUsage(dict, true);
  649. }
  650. else
  651. {
  652. list[i].AppendUsedBy(dict, true);
  653. }
  654. }
  655. //var result = dict.Values.ToList();
  656. //result.Sort((item1, item2)=>{
  657. // return item1.index.CompareTo(item2.index);
  658. //});
  659. return dict;
  660. }
  661. public static Dictionary<string, FR2_Ref> FindUsage(string[] guids)
  662. {
  663. return FindRefs(guids, true, true);
  664. }
  665. public static Dictionary<string, FR2_Ref> FindUsedBy(string[] guids)
  666. {
  667. return FindRefs(guids, false, true);
  668. }
  669. public static Dictionary<string, FR2_Ref> FindUsageScene(GameObject[] objs, bool depth)
  670. {
  671. var dict = new Dictionary<string, FR2_Ref>();
  672. // var list = new List<FR2_Ref>();
  673. for (var i = 0; i < objs.Length; i++)
  674. {
  675. if (FR2_Unity.IsInAsset(objs[i]))
  676. {
  677. continue; //only get in scene
  678. }
  679. //add selection
  680. if (!dict.ContainsKey(objs[i].GetInstanceID().ToString()))
  681. {
  682. dict.Add(objs[i].GetInstanceID().ToString(), new FR2_SceneRef(0, objs[i]));
  683. }
  684. foreach (Object item in FR2_Unity.GetAllRefObjects(objs[i]))
  685. {
  686. AppendUsageScene(dict, item);
  687. }
  688. if (depth)
  689. {
  690. foreach (GameObject child in FR2_Unity.getAllChild(objs[i]))
  691. foreach (Object item2 in FR2_Unity.GetAllRefObjects(child))
  692. {
  693. AppendUsageScene(dict, item2);
  694. }
  695. }
  696. }
  697. return dict;
  698. }
  699. private static void AppendUsageScene(Dictionary<string, FR2_Ref> dict, Object obj)
  700. {
  701. string path = AssetDatabase.GetAssetPath(obj);
  702. if (string.IsNullOrEmpty(path))
  703. {
  704. return;
  705. }
  706. string guid = AssetDatabase.AssetPathToGUID(path);
  707. if (string.IsNullOrEmpty(guid))
  708. {
  709. return;
  710. }
  711. if (dict.ContainsKey(guid))
  712. {
  713. return;
  714. }
  715. FR2_Asset asset = FR2_Cache.Api.Get(guid);
  716. if (asset == null)
  717. {
  718. return;
  719. }
  720. var r = new FR2_Ref(0, 1, asset, null);
  721. dict.Add(guid, r);
  722. }
  723. }
  724. public class FR2_RefDrawer : IRefDraw
  725. {
  726. public enum Mode
  727. {
  728. Dependency,
  729. Depth,
  730. Type,
  731. Extension,
  732. Folder,
  733. Atlas,
  734. AssetBundle,
  735. None
  736. }
  737. public enum Sort
  738. {
  739. Type,
  740. Path,
  741. Size
  742. }
  743. public static GUIStyle toolbarSearchField;
  744. public static GUIStyle toolbarSearchFieldCancelButton;
  745. public static GUIStyle toolbarSearchFieldCancelButtonEmpty;
  746. internal readonly FR2_TreeUI2.GroupDrawer groupDrawer;
  747. private readonly bool showSearch = true;
  748. public bool caseSensitive = false;
  749. // STATUS
  750. private bool dirty;
  751. private int excludeCount;
  752. public string level0Group;
  753. public bool forceHideDetails;
  754. public string Lable;
  755. internal List<FR2_Ref> list;
  756. internal Dictionary<string, FR2_Ref> refs;
  757. // FILTERING
  758. private string searchTerm = string.Empty;
  759. private bool selectFilter;
  760. private bool showIgnore;
  761. // ORIGINAL
  762. internal FR2_Ref[] source
  763. {
  764. get { return FR2_Ref.FromList(list); }
  765. }
  766. public FR2_RefDrawer(IWindow window)
  767. {
  768. this.window = window;
  769. groupDrawer = new FR2_TreeUI2.GroupDrawer(DrawGroup, DrawAsset);
  770. }
  771. public string messageNoRefs = "Do select something!";
  772. public string messageEmpty = "It's empty!";
  773. public IWindow window { get; set; }
  774. void DrawEmpty(Rect rect, string text)
  775. {
  776. rect = GUI2.Padding(rect, 2f, 2f);
  777. rect.height = 40f;
  778. EditorGUI.HelpBox(rect, text, MessageType.Info);
  779. }
  780. public bool Draw(Rect rect)
  781. {
  782. if (refs == null || refs.Count == 0)
  783. {
  784. DrawEmpty(rect, messageNoRefs);
  785. return false;
  786. }
  787. if (dirty || list == null)
  788. {
  789. ApplyFilter();
  790. }
  791. if (!groupDrawer.hasChildren)
  792. {
  793. DrawEmpty(rect, messageEmpty);
  794. }
  795. else
  796. {
  797. groupDrawer.Draw(rect);
  798. }
  799. return false;
  800. }
  801. public bool DrawLayout()
  802. {
  803. if (refs == null || refs.Count == 0)
  804. {
  805. return false;
  806. }
  807. if (dirty || list == null)
  808. {
  809. ApplyFilter();
  810. }
  811. groupDrawer.DrawLayout();
  812. return false;
  813. }
  814. public int ElementCount()
  815. {
  816. if (refs == null)
  817. {
  818. return 0;
  819. }
  820. return refs.Count;
  821. // return refs.Where(x => x.Value.depth != 0).Count();
  822. }
  823. public void SetRefs(Dictionary<string, FR2_Ref> dictRefs)
  824. {
  825. refs = dictRefs;
  826. dirty = true;
  827. }
  828. void SetBookmarkGroup(string groupLabel, bool willbookmark)
  829. {
  830. string[] ids = groupDrawer.GetChildren(groupLabel);
  831. var info = GetBMInfo(groupLabel);
  832. for (var i = 0; i < ids.Length; i++)
  833. {
  834. FR2_Ref rf;
  835. if (!refs.TryGetValue(ids[i], out rf))
  836. {
  837. continue;
  838. }
  839. if (willbookmark)
  840. {
  841. FR2_Bookmark.Add(rf);
  842. }
  843. else
  844. {
  845. FR2_Bookmark.Remove(rf);
  846. }
  847. }
  848. info.count = willbookmark ? info.total : 0;
  849. }
  850. internal class BookmarkInfo
  851. {
  852. public int count;
  853. public int total;
  854. }
  855. private Dictionary<string, BookmarkInfo> gBookmarkCache = new Dictionary<string, BookmarkInfo>();
  856. BookmarkInfo GetBMInfo(string groupLabel)
  857. {
  858. BookmarkInfo info = null;
  859. if (!gBookmarkCache.TryGetValue(groupLabel, out info))
  860. {
  861. string[] ids = groupDrawer.GetChildren(groupLabel);
  862. info = new BookmarkInfo();
  863. for (var i = 0; i < ids.Length; i++)
  864. {
  865. FR2_Ref rf;
  866. if (!refs.TryGetValue(ids[i], out rf))
  867. {
  868. continue;
  869. }
  870. info.total++;
  871. var isBM = FR2_Bookmark.Contains(rf);
  872. if (isBM) info.count++;
  873. }
  874. gBookmarkCache.Add(groupLabel, info);
  875. }
  876. return info;
  877. }
  878. void DrawToggleGroup(Rect r, string groupLabel)
  879. {
  880. var info = GetBMInfo(groupLabel);
  881. var selectAll = info.count == info.total;
  882. r.width = 16f;
  883. if (GUI2.Toggle(r, ref selectAll))
  884. {
  885. SetBookmarkGroup(groupLabel, selectAll);
  886. }
  887. if (!selectAll && info.count > 0)
  888. {
  889. //GUI.DrawTexture(r, EditorStyles.
  890. }
  891. }
  892. private void DrawGroup(Rect r, string label, int childCount)
  893. {
  894. if (FR2_Setting.GroupMode == Mode.Folder)
  895. {
  896. Texture tex = AssetDatabase.GetCachedIcon("Assets");
  897. GUI.DrawTexture(new Rect(r.x - 2f, r.y - 2f, 16f, 16f), tex);
  898. r.xMin += 16f;
  899. }
  900. DrawToggleGroup(r, label);
  901. r.xMin += 18f;
  902. GUI.Label(r, label + " (" + childCount + ")", EditorStyles.boldLabel);
  903. bool hasMouse = Event.current.type == EventType.MouseUp && r.Contains(Event.current.mousePosition);
  904. if (hasMouse && Event.current.button == 1)
  905. {
  906. var menu = new GenericMenu();
  907. menu.AddItem(new GUIContent("Add Bookmark"), false, () => { SetBookmarkGroup(label, true); });
  908. menu.AddItem(new GUIContent("Remove Bookmark"), false, () =>
  909. {
  910. SetBookmarkGroup(label, false);
  911. });
  912. menu.ShowAsContext();
  913. Event.current.Use();
  914. }
  915. }
  916. private void DrawAsset(Rect r, string guid)
  917. {
  918. FR2_Ref rf;
  919. if (!refs.TryGetValue(guid, out rf))
  920. {
  921. return;
  922. }
  923. if (rf.isSceneRef)
  924. {
  925. if (rf.component == null)
  926. {
  927. return;
  928. }
  929. var re = rf as FR2_SceneRef;
  930. if (re != null)
  931. {
  932. r.x -= 16f;
  933. rf.DrawToogleSelect(r);
  934. r.xMin += 32f;
  935. re.Draw(r, window, !forceHideDetails);
  936. }
  937. }
  938. else
  939. {
  940. r.xMin -= 16f;
  941. rf.DrawToogleSelect(r);
  942. r.xMin += 32f;
  943. rf.asset.Draw (r,
  944. rf.depth == 1,
  945. !forceHideDetails && (FR2_Setting.GroupMode != Mode.Folder),
  946. !forceHideDetails && FR2_Setting.s.displayFileSize,
  947. !forceHideDetails && FR2_Setting.s.displayAssetBundleName,
  948. !forceHideDetails && FR2_Setting.s.displayAtlasName,
  949. !forceHideDetails && FR2_Setting.s.showUsedByClassed,
  950. window
  951. );
  952. }
  953. }
  954. private string GetGroup(FR2_Ref rf)
  955. {
  956. if (rf.depth == 0)
  957. {
  958. return level0Group;
  959. }
  960. if (FR2_Setting.GroupMode == Mode.None)
  961. {
  962. return "(no group)";
  963. }
  964. FR2_SceneRef sr = null;
  965. if (rf.isSceneRef)
  966. {
  967. sr = rf as FR2_SceneRef;
  968. if (sr == null) return null;
  969. }
  970. if (!rf.isSceneRef)
  971. {
  972. if (rf.asset.IsExcluded) return null; // "(ignored)"
  973. }
  974. switch (FR2_Setting.GroupMode)
  975. {
  976. case Mode.Extension: return rf.isSceneRef ? sr.targetType : rf.asset.extension;
  977. case Mode.Type:
  978. {
  979. return rf.isSceneRef ? sr.targetType : AssetType.FILTERS[rf.type].name;
  980. }
  981. case Mode.Folder: return rf.isSceneRef ? sr.scenePath : rf.asset.assetFolder;
  982. case Mode.Dependency:
  983. {
  984. return rf.depth == 1 ? "Direct Usage" : "Indirect Usage";
  985. }
  986. case Mode.Depth:
  987. {
  988. return "Level " + rf.depth.ToString();
  989. }
  990. case Mode.Atlas : return rf.isSceneRef ? "(not in atlas)" : (string.IsNullOrEmpty(rf.asset.AtlasName) ? "(not in atlas)" : rf.asset.AtlasName);
  991. case Mode.AssetBundle : return rf.isSceneRef ? "(not in assetbundle)" : (string.IsNullOrEmpty(rf.asset.AssetBundleName) ? "(not in assetbundle)" : rf.asset.AssetBundleName);
  992. }
  993. return "(others)";
  994. }
  995. private void SortGroup(List<string> groups)
  996. {
  997. groups.Sort((item1, item2) =>
  998. {
  999. if (item1.Contains("(")) return 1;
  1000. if (item2.Contains("(")) return -1;
  1001. return item1.CompareTo(item2);
  1002. });
  1003. }
  1004. public FR2_RefDrawer Reset(string[] assetGUIDs, bool isUsage)
  1005. {
  1006. //Debug.Log("Reset :: " + assetGUIDs.Length + "\n" + string.Join("\n", assetGUIDs));
  1007. gBookmarkCache.Clear();
  1008. if (isUsage)
  1009. {
  1010. refs = FR2_Ref.FindUsage(assetGUIDs);
  1011. }
  1012. else
  1013. {
  1014. refs = FR2_Ref.FindUsedBy(assetGUIDs);
  1015. }
  1016. dirty = true;
  1017. if (list != null)
  1018. {
  1019. list.Clear();
  1020. }
  1021. return this;
  1022. }
  1023. public FR2_RefDrawer Reset(GameObject[] objs, bool findDept, bool findPrefabInAsset)
  1024. {
  1025. refs = FR2_Ref.FindUsageScene(objs, findDept);
  1026. var guidss = new List<string>();
  1027. var dependent = FR2_SceneCache.Api.prefabDependencies;
  1028. foreach (var gameObject in objs)
  1029. {
  1030. HashSet<string> hash;
  1031. if (!dependent.TryGetValue(gameObject, out hash))
  1032. {
  1033. continue;
  1034. }
  1035. foreach (string guid in hash)
  1036. {
  1037. guidss.Add(guid);
  1038. }
  1039. }
  1040. Dictionary<string, FR2_Ref> usageRefs1 = FR2_Ref.FindUsage(guidss.ToArray());
  1041. foreach (KeyValuePair<string, FR2_Ref> kvp in usageRefs1)
  1042. {
  1043. if (refs.ContainsKey(kvp.Key))
  1044. {
  1045. continue;
  1046. }
  1047. if (guidss.Contains(kvp.Key))
  1048. {
  1049. kvp.Value.depth = 1;
  1050. }
  1051. refs.Add(kvp.Key, kvp.Value);
  1052. }
  1053. if (findPrefabInAsset)
  1054. {
  1055. var guids = new List<string>();
  1056. for (var i = 0; i < objs.Length; i++)
  1057. {
  1058. string guid = FR2_Unity.GetPrefabParent(objs[i]);
  1059. if (string.IsNullOrEmpty(guid))
  1060. {
  1061. continue;
  1062. }
  1063. guids.Add(guid);
  1064. }
  1065. Dictionary<string, FR2_Ref> usageRefs = FR2_Ref.FindUsage(guids.ToArray());
  1066. foreach (KeyValuePair<string, FR2_Ref> kvp in usageRefs)
  1067. {
  1068. if (refs.ContainsKey(kvp.Key))
  1069. {
  1070. continue;
  1071. }
  1072. if (guids.Contains(kvp.Key))
  1073. {
  1074. kvp.Value.depth = 1;
  1075. }
  1076. refs.Add(kvp.Key, kvp.Value);
  1077. }
  1078. }
  1079. dirty = true;
  1080. if (list != null)
  1081. {
  1082. list.Clear();
  1083. }
  1084. return this;
  1085. }
  1086. //ref in scene
  1087. public FR2_RefDrawer Reset(string[] assetGUIDs, IWindow window)
  1088. {
  1089. refs = FR2_SceneRef.FindRefInScene(assetGUIDs, true, SetRefInScene, window);
  1090. dirty = true;
  1091. if (list != null)
  1092. {
  1093. list.Clear();
  1094. }
  1095. return this;
  1096. }
  1097. private void SetRefInScene(Dictionary<string, FR2_Ref> data)
  1098. {
  1099. refs = data;
  1100. dirty = true;
  1101. if (list != null)
  1102. {
  1103. list.Clear();
  1104. }
  1105. }
  1106. //scene in scene
  1107. public FR2_RefDrawer ResetSceneInScene(GameObject[] objs)
  1108. {
  1109. refs = FR2_SceneRef.FindSceneInScene(objs);
  1110. dirty = true;
  1111. if (list != null)
  1112. {
  1113. list.Clear();
  1114. }
  1115. return this;
  1116. }
  1117. public FR2_RefDrawer ResetSceneUseSceneObjects(GameObject[] objs)
  1118. {
  1119. refs = FR2_SceneRef.FindSceneUseSceneObjects(objs);
  1120. dirty = true;
  1121. if (list != null)
  1122. {
  1123. list.Clear();
  1124. }
  1125. return this;
  1126. }
  1127. public FR2_RefDrawer ResetUnusedAsset()
  1128. {
  1129. List<FR2_Asset> lst = FR2_Cache.Api.ScanUnused();
  1130. refs = lst.ToDictionary(x => x.guid, x => new FR2_Ref(0, 1, x, null));
  1131. dirty = true;
  1132. if (list != null)
  1133. {
  1134. list.Clear();
  1135. }
  1136. return this;
  1137. }
  1138. public void RefreshSort()
  1139. {
  1140. if (list == null)
  1141. {
  1142. return;
  1143. }
  1144. if (list.Count > 0 && list[0].isSceneRef == false && FR2_Setting.SortMode == Sort.Size)
  1145. {
  1146. list = list.OrderByDescending(x => x.asset != null ? x.asset.fileSize : 0).ToList();
  1147. } else
  1148. {
  1149. list.Sort((r1, r2) =>
  1150. {
  1151. var isMixed = r1.isSceneRef ^ r2.isSceneRef;
  1152. if (isMixed)
  1153. {
  1154. #if FR2_DEBUG
  1155. var sb = new StringBuilder();
  1156. sb.Append("r1: " + r1.ToString());
  1157. sb.AppendLine();
  1158. sb.Append("r2: " +r2.ToString());
  1159. Debug.LogWarning("Mixed compared!\n" + sb.ToString());
  1160. #endif
  1161. var v1 = r1.isSceneRef ? 1 : 0;
  1162. var v2 = r2.isSceneRef ? 1 : 0;
  1163. return v2.CompareTo(v1);
  1164. }
  1165. if (r1.isSceneRef)
  1166. {
  1167. var rs1 = (FR2_SceneRef)r1;
  1168. var rs2 = (FR2_SceneRef)r2;
  1169. return SortAsset(rs1.sceneFullPath, rs2.sceneFullPath,
  1170. rs1.targetType, rs2.targetType,
  1171. FR2_Setting.SortMode == Sort.Path);
  1172. }
  1173. return SortAsset(
  1174. r1.asset.assetPath, r2.asset.assetPath,
  1175. r1.asset.extension, r2.asset.extension,
  1176. false
  1177. );
  1178. });
  1179. }
  1180. // clean up list
  1181. int invalidCount = 0;
  1182. for (int i = list.Count-1; i >=0 ; i--)
  1183. {
  1184. var item = list[i];
  1185. if (item.isSceneRef)
  1186. {
  1187. if (string.IsNullOrEmpty(item.GetSceneObjId()))
  1188. {
  1189. invalidCount++;
  1190. list.RemoveAt(i);
  1191. }
  1192. continue;
  1193. }
  1194. if (item.asset == null)
  1195. {
  1196. invalidCount++;
  1197. list.RemoveAt(i);
  1198. continue;
  1199. }
  1200. }
  1201. #if FR2_DEBUG
  1202. if (invalidCount > 0) Debug.LogWarning("Removed [" + invalidCount + "] invalid assets / objects");
  1203. #endif
  1204. groupDrawer.Reset(list,
  1205. rf =>
  1206. {
  1207. if (rf == null) return null;
  1208. if (rf.isSceneRef) return rf.GetSceneObjId();
  1209. return rf.asset == null ? null : rf.asset.guid;
  1210. }, GetGroup, SortGroup);
  1211. }
  1212. public bool isExclueAnyItem()
  1213. {
  1214. return excludeCount > 0;
  1215. }
  1216. private void ApplyFilter()
  1217. {
  1218. dirty = false;
  1219. if (refs == null)
  1220. {
  1221. return;
  1222. }
  1223. if (list == null)
  1224. {
  1225. list = new List<FR2_Ref>();
  1226. }
  1227. else
  1228. {
  1229. list.Clear();
  1230. }
  1231. int minScore = searchTerm.Length;
  1232. string term1 = searchTerm;
  1233. if (!caseSensitive)
  1234. {
  1235. term1 = term1.ToLower();
  1236. }
  1237. string term2 = term1.Replace(" ", string.Empty);
  1238. excludeCount = 0;
  1239. foreach (KeyValuePair<string, FR2_Ref> item in refs)
  1240. {
  1241. FR2_Ref r = item.Value;
  1242. if (FR2_Setting.IsTypeExcluded(r.type))
  1243. {
  1244. excludeCount++;
  1245. continue; //skip this one
  1246. }
  1247. if (!showSearch || string.IsNullOrEmpty(searchTerm))
  1248. {
  1249. r.matchingScore = 0;
  1250. list.Add(r);
  1251. continue;
  1252. }
  1253. //calculate matching score
  1254. string name1 = r.isSceneRef ? (r as FR2_SceneRef).sceneFullPath : r.asset.assetName;
  1255. if (!caseSensitive)
  1256. {
  1257. name1 = name1.ToLower();
  1258. }
  1259. string name2 = name1.Replace(" ", string.Empty);
  1260. int score1 = FR2_Unity.StringMatch(term1, name1);
  1261. int score2 = FR2_Unity.StringMatch(term2, name2);
  1262. r.matchingScore = Mathf.Max(score1, score2);
  1263. if (r.matchingScore > minScore)
  1264. {
  1265. list.Add(r);
  1266. }
  1267. }
  1268. RefreshSort();
  1269. }
  1270. public void SetDirty()
  1271. {
  1272. dirty = true;
  1273. }
  1274. private int SortAsset(string term11, string term12, string term21, string term22, bool swap)
  1275. {
  1276. // if (term11 == null) term11 = string.Empty;
  1277. // if (term12 == null) term12 = string.Empty;
  1278. // if (term21 == null) term21 = string.Empty;
  1279. // if (term22 == null) term22 = string.Empty;
  1280. var v1 = String.Compare(term11, term12, StringComparison.Ordinal);
  1281. var v2 = String.Compare(term21, term22, StringComparison.Ordinal);
  1282. return swap ? (v1 == 0) ? v2 : v1 : (v2 == 0) ? v1 : v2;
  1283. }
  1284. public Dictionary<string, FR2_Ref> getRefs()
  1285. {
  1286. return refs;
  1287. }
  1288. }
  1289. }