ABModelBundleInfo.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. using System;
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using UnityEditor.IMGUI.Controls;
  7. namespace AssetBundleBrowser.AssetBundleModel
  8. {
  9. internal sealed class BundleTreeItem : TreeViewItem
  10. {
  11. private BundleInfo m_Bundle;
  12. internal BundleInfo bundle
  13. {
  14. get { return m_Bundle; }
  15. }
  16. internal BundleTreeItem(BundleInfo b, int depth, Texture2D iconTexture) : base(b.nameHashCode, depth, b.displayName)
  17. {
  18. m_Bundle = b;
  19. icon = iconTexture;
  20. children = new List<TreeViewItem>();
  21. }
  22. internal MessageSystem.Message BundleMessage()
  23. {
  24. return m_Bundle.HighestMessage();
  25. }
  26. public override string displayName
  27. {
  28. get
  29. {
  30. return AssetBundleBrowserMain.instance.m_ManageTab.hasSearch ? m_Bundle.m_Name.fullNativeName : m_Bundle.displayName;
  31. }
  32. }
  33. }
  34. internal class BundleNameData
  35. {
  36. private List<string> m_PathTokens;
  37. private string m_FullBundleName;
  38. private string m_ShortName;
  39. private string m_VariantName;
  40. private string m_FullNativeName;
  41. //input (received from native) is a string of format:
  42. // /folder0/.../folderN/name.variant
  43. //it's broken into:
  44. // /m_pathTokens[0]/.../m_pathTokens[n]/m_shortName.m_variantName
  45. // and...
  46. // m_fullBundleName = /m_pathTokens[0]/.../m_pathTokens[n]/m_shortName
  47. // and...
  48. // m_fullNativeName = m_fullBundleName.m_variantName which is the same as the initial input.
  49. internal BundleNameData(string name) { SetName(name); }
  50. internal BundleNameData(string path, string name)
  51. {
  52. string finalName = System.String.IsNullOrEmpty(path) ? "" : path + '/';
  53. finalName += name;
  54. SetName(finalName);
  55. }
  56. public override int GetHashCode()
  57. {
  58. return fullNativeName.GetHashCode();
  59. }
  60. internal string fullNativeName
  61. { get { return m_FullNativeName; } }
  62. internal void SetBundleName(string bundleName, string variantName)
  63. {
  64. string name = bundleName;
  65. name += System.String.IsNullOrEmpty(variantName) ? "" : "." + variantName;
  66. SetName(name);
  67. }
  68. internal string bundleName
  69. {
  70. get { return m_FullBundleName; }
  71. //set { SetName(value); }
  72. }
  73. internal string shortName
  74. {
  75. get { return m_ShortName; }
  76. }
  77. internal string variant
  78. {
  79. get { return m_VariantName; }
  80. set
  81. {
  82. m_VariantName = value;
  83. m_FullNativeName = m_FullBundleName;
  84. m_FullNativeName += System.String.IsNullOrEmpty(m_VariantName) ? "" : "." + m_VariantName;
  85. }
  86. }
  87. internal List<string> pathTokens
  88. {
  89. get { return m_PathTokens; }
  90. set
  91. {
  92. m_PathTokens = value.GetRange(0, value.Count-1);
  93. SetShortName(value.Last());
  94. GenerateFullName();
  95. }
  96. }
  97. private void SetName(string name)
  98. {
  99. if(m_PathTokens == null)
  100. m_PathTokens = new List<string>();
  101. else
  102. m_PathTokens.Clear();
  103. int indexOfSlash = name.IndexOf('/');
  104. int previousIndex = 0;
  105. while(indexOfSlash != -1)
  106. {
  107. m_PathTokens.Add(name.Substring(previousIndex, (indexOfSlash - previousIndex)));
  108. previousIndex = indexOfSlash + 1;
  109. indexOfSlash = name.IndexOf('/', previousIndex);
  110. }
  111. SetShortName(name.Substring(previousIndex));
  112. GenerateFullName();
  113. }
  114. private void SetShortName(string inputName)
  115. {
  116. m_ShortName = inputName;
  117. int indexOfDot = m_ShortName.LastIndexOf('.');
  118. if (indexOfDot > -1)
  119. {
  120. m_VariantName = m_ShortName.Substring(indexOfDot + 1);
  121. m_ShortName = m_ShortName.Substring(0, indexOfDot);
  122. }
  123. else
  124. m_VariantName = string.Empty;
  125. }
  126. internal void PartialNameChange(string newToken, int indexFromBack)
  127. {
  128. if(indexFromBack == 0)
  129. {
  130. SetShortName(newToken);
  131. }
  132. else if(indexFromBack-1 < m_PathTokens.Count)
  133. {
  134. m_PathTokens[m_PathTokens.Count - indexFromBack] = newToken;
  135. }
  136. GenerateFullName();
  137. }
  138. private void GenerateFullName()
  139. {
  140. m_FullBundleName = string.Empty;
  141. for(int i = 0; i < m_PathTokens.Count; i++)
  142. {
  143. m_FullBundleName += m_PathTokens[i];
  144. m_FullBundleName += '/';
  145. }
  146. m_FullBundleName += m_ShortName;
  147. m_FullNativeName = m_FullBundleName;
  148. m_FullNativeName += System.String.IsNullOrEmpty(m_VariantName) ? "" : "." + m_VariantName;
  149. }
  150. }
  151. internal abstract class BundleInfo
  152. {
  153. protected BundleFolderInfo m_Parent;
  154. protected bool m_DoneUpdating;
  155. protected bool m_Dirty;
  156. internal BundleNameData m_Name;
  157. protected MessageSystem.MessageState m_BundleMessages = new MessageSystem.MessageState();
  158. protected MessageSystem.Message m_CachedHighMessage = null;
  159. internal BundleInfo(string name, BundleFolderInfo parent)
  160. {
  161. m_Name = new BundleNameData(name);
  162. m_Parent = parent;
  163. }
  164. internal BundleFolderInfo parent
  165. { get { return m_Parent; } }
  166. internal virtual string displayName
  167. {
  168. get { return m_Name.shortName; }
  169. }
  170. internal virtual int nameHashCode
  171. {
  172. get { return m_Name.GetHashCode(); }
  173. }
  174. internal abstract BundleTreeItem CreateTreeView(int depth);
  175. protected virtual void RefreshMessages()
  176. {
  177. RefreshEmptyStatus();
  178. RefreshDupeAssetWarning();
  179. var flag = m_BundleMessages.HighestMessageFlag();
  180. m_CachedHighMessage = MessageSystem.GetMessage(flag);
  181. }
  182. internal abstract bool RefreshEmptyStatus();
  183. internal abstract bool RefreshDupeAssetWarning();
  184. internal virtual MessageSystem.Message HighestMessage()
  185. {
  186. if (m_CachedHighMessage == null)
  187. RefreshMessages();
  188. return m_CachedHighMessage;
  189. }
  190. internal bool IsMessageSet(MessageSystem.MessageFlag flag)
  191. {
  192. return m_BundleMessages.IsSet(flag);
  193. }
  194. internal void SetMessageFlag(MessageSystem.MessageFlag flag, bool on)
  195. {
  196. m_BundleMessages.SetFlag(flag, on);
  197. }
  198. internal List<MessageSystem.Message> GetMessages()
  199. {
  200. return m_BundleMessages.GetMessages();
  201. }
  202. internal bool HasMessages()
  203. {
  204. return m_BundleMessages.HasMessages();
  205. }
  206. internal virtual bool HandleRename(string newName, int reverseDepth)
  207. {
  208. if (reverseDepth == 0)
  209. {
  210. if (!m_Parent.HandleChildRename(m_Name.shortName, newName))
  211. return false;
  212. }
  213. m_Name.PartialNameChange(newName, reverseDepth);
  214. return true;
  215. }
  216. internal virtual void HandleDelete(bool isRootOfDelete, string forcedNewName="", string forcedNewVariant = "")
  217. {
  218. if(isRootOfDelete)
  219. {
  220. m_Parent.HandleChildRename(m_Name.shortName, string.Empty);
  221. }
  222. }
  223. abstract internal void RefreshAssetList();
  224. abstract internal void AddAssetsToNode(AssetTreeItem node);
  225. abstract internal void Update();
  226. internal virtual bool doneUpdating
  227. { get { return m_DoneUpdating; } }
  228. internal virtual bool dirty
  229. { get { return m_Dirty; } }
  230. internal void ForceNeedUpdate()
  231. {
  232. m_DoneUpdating = false;
  233. m_Dirty = true;
  234. }
  235. abstract internal void HandleReparent(string parentName, BundleFolderInfo newParent = null);
  236. abstract internal List<AssetInfo> GetDependencies();
  237. abstract internal bool DoesItemMatchSearch(string search);
  238. }
  239. internal class BundleDataInfo : BundleInfo
  240. {
  241. protected List<AssetInfo> m_ConcreteAssets;
  242. protected List<AssetInfo> m_DependentAssets;
  243. protected HashSet<string> m_BundleDependencies;
  244. protected int m_ConcreteCounter;
  245. protected int m_DependentCounter;
  246. protected bool m_IsSceneBundle;
  247. protected long m_TotalSize;
  248. internal BundleDataInfo(string name, BundleFolderInfo parent) : base(name, parent)
  249. {
  250. m_ConcreteAssets = new List<AssetInfo>();
  251. m_DependentAssets = new List<AssetInfo>();
  252. m_BundleDependencies = new HashSet<string>();
  253. m_ConcreteCounter = 0;
  254. m_DependentCounter = 0;
  255. }
  256. ~BundleDataInfo()
  257. {
  258. foreach (var asset in m_DependentAssets)
  259. {
  260. AssetBundleModel.Model.UnRegisterAsset(asset, m_Name.fullNativeName);
  261. }
  262. }
  263. internal override bool HandleRename(string newName, int reverseDepth)
  264. {
  265. RefreshAssetList();
  266. if (!base.HandleRename(newName, reverseDepth))
  267. return false;
  268. Model.MoveAssetToBundle(m_ConcreteAssets, m_Name.bundleName, m_Name.variant);
  269. return true;
  270. }
  271. internal override void HandleDelete(bool isRootOfDelete, string forcedNewName="", string forcedNewVariant="")
  272. {
  273. RefreshAssetList();
  274. base.HandleDelete(isRootOfDelete);
  275. Model.MoveAssetToBundle(m_ConcreteAssets, forcedNewName, forcedNewVariant);
  276. }
  277. internal string TotalSize()
  278. {
  279. if (m_TotalSize == 0)
  280. return "--";
  281. return EditorUtility.FormatBytes(m_TotalSize);
  282. }
  283. internal override void RefreshAssetList()
  284. {
  285. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.AssetsDuplicatedInMultBundles, false);
  286. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.SceneBundleConflict, false);
  287. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.DependencySceneConflict, false);
  288. m_ConcreteAssets.Clear();
  289. m_TotalSize = 0;
  290. m_IsSceneBundle = false;
  291. foreach (var asset in m_DependentAssets)
  292. {
  293. AssetBundleModel.Model.UnRegisterAsset(asset, m_Name.fullNativeName);
  294. }
  295. m_DependentAssets.Clear();
  296. m_BundleDependencies.Clear();
  297. bool assetInBundle = false;
  298. bool sceneError = false;
  299. var assets = AssetBundleModel.Model.DataSource.GetAssetPathsFromAssetBundle(m_Name.fullNativeName);
  300. foreach(var assetName in assets)
  301. {
  302. if (AssetDatabase.GetMainAssetTypeAtPath(assetName) == typeof(SceneAsset))
  303. {
  304. m_IsSceneBundle = true;
  305. if(assetInBundle)
  306. sceneError = true;
  307. }
  308. else
  309. {
  310. assetInBundle = true;
  311. if (m_IsSceneBundle)
  312. sceneError = true;
  313. }
  314. var bundleName = Model.GetBundleName(assetName);
  315. if (System.String.IsNullOrEmpty(bundleName))
  316. {
  317. ///we get here if the current asset is only added due to being in an explicitly added folder
  318. var partialPath = assetName;
  319. while(
  320. !System.String.IsNullOrEmpty(partialPath) &&
  321. partialPath != "Assets" &&
  322. System.String.IsNullOrEmpty(bundleName))
  323. {
  324. partialPath = partialPath.Substring(0, partialPath.LastIndexOf('/'));
  325. bundleName = Model.GetBundleName(partialPath);
  326. }
  327. if(!System.String.IsNullOrEmpty(bundleName))
  328. {
  329. var folderAsset = Model.CreateAsset(partialPath, bundleName);
  330. folderAsset.isFolder = true;
  331. if (m_ConcreteAssets.FindIndex(a => a.displayName == folderAsset.displayName) == -1)
  332. {
  333. m_ConcreteAssets.Add(folderAsset);
  334. }
  335. m_DependentAssets.Add(Model.CreateAsset(assetName, folderAsset));
  336. if (m_DependentAssets != null && m_DependentAssets.Count > 0)
  337. {
  338. var last = m_DependentAssets.Last();
  339. if (last != null)
  340. m_TotalSize += last.fileSize;
  341. }
  342. }
  343. }
  344. else
  345. {
  346. var newAsset = Model.CreateAsset (assetName, m_Name.fullNativeName);
  347. if (newAsset != null)
  348. {
  349. m_ConcreteAssets.Add(newAsset);
  350. m_TotalSize += m_ConcreteAssets.Last().fileSize;
  351. if (AssetDatabase.GetMainAssetTypeAtPath(assetName) == typeof(SceneAsset))
  352. {
  353. m_IsSceneBundle = true;
  354. m_ConcreteAssets.Last().isScene = true;
  355. }
  356. }
  357. }
  358. }
  359. if(sceneError)
  360. {
  361. foreach (var asset in m_ConcreteAssets)
  362. {
  363. if (asset.isFolder)
  364. {
  365. asset.SetMessageFlag(MessageSystem.MessageFlag.DependencySceneConflict, true);
  366. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.DependencySceneConflict, true);
  367. }
  368. else
  369. {
  370. asset.SetMessageFlag(MessageSystem.MessageFlag.SceneBundleConflict, true);
  371. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.SceneBundleConflict, true);
  372. }
  373. }
  374. }
  375. m_ConcreteCounter = 0;
  376. m_DependentCounter = 0;
  377. m_Dirty = true;
  378. }
  379. internal override void AddAssetsToNode(AssetTreeItem node)
  380. {
  381. foreach (var asset in m_ConcreteAssets)
  382. node.AddChild(new AssetTreeItem(asset));
  383. foreach (var asset in m_DependentAssets)
  384. {
  385. if(!node.ContainsChild(asset))
  386. node.AddChild(new AssetTreeItem(asset));
  387. }
  388. m_Dirty = false;
  389. }
  390. internal HashSet<string> GetBundleDependencies()
  391. {
  392. return m_BundleDependencies;
  393. }
  394. internal override void Update()
  395. {
  396. int dependents = m_DependentAssets.Count;
  397. int bundleDep = m_BundleDependencies.Count;
  398. if(m_ConcreteCounter < m_ConcreteAssets.Count)
  399. {
  400. GatherDependencies(m_ConcreteAssets[m_ConcreteCounter]);
  401. m_ConcreteCounter++;
  402. m_DoneUpdating = false;
  403. }
  404. else if (m_DependentCounter < m_DependentAssets.Count)
  405. {
  406. GatherDependencies(m_DependentAssets[m_DependentCounter], m_Name.fullNativeName);
  407. m_DependentCounter++;
  408. m_DoneUpdating = false;
  409. }
  410. else
  411. {
  412. m_DoneUpdating = true;
  413. }
  414. m_Dirty = (dependents != m_DependentAssets.Count) || (bundleDep != m_BundleDependencies.Count);
  415. if (m_Dirty || m_DoneUpdating)
  416. RefreshMessages();
  417. }
  418. private void GatherDependencies(AssetInfo asset, string parentBundle = "")
  419. {
  420. if (System.String.IsNullOrEmpty(parentBundle))
  421. parentBundle = asset.bundleName;
  422. if (asset == null)
  423. return;
  424. var deps = asset.GetDependencies();
  425. if (deps == null)
  426. return;
  427. foreach (var ai in deps)
  428. {
  429. if (ai == asset || m_ConcreteAssets.Contains(ai) || m_DependentAssets.Contains(ai))
  430. continue;
  431. var bundleName = AssetBundleModel.Model.DataSource.GetImplicitAssetBundleName(ai.fullAssetName);
  432. if (string.IsNullOrEmpty(bundleName))
  433. {
  434. m_DependentAssets.Add(ai);
  435. m_TotalSize += ai.fileSize;
  436. if (Model.RegisterAsset(ai, parentBundle) > 1)
  437. {
  438. SetDuplicateWarning();
  439. }
  440. }
  441. else if(bundleName != m_Name.fullNativeName)
  442. {
  443. m_BundleDependencies.Add(bundleName);
  444. }
  445. }
  446. }
  447. internal override bool RefreshDupeAssetWarning()
  448. {
  449. foreach(var asset in m_DependentAssets)
  450. {
  451. if (asset != null && asset.IsMessageSet(MessageSystem.MessageFlag.AssetsDuplicatedInMultBundles))
  452. {
  453. SetDuplicateWarning();
  454. return true;
  455. }
  456. }
  457. return false;
  458. }
  459. internal bool IsEmpty()
  460. {
  461. return (m_ConcreteAssets.Count == 0);
  462. }
  463. internal override bool RefreshEmptyStatus()
  464. {
  465. bool empty = IsEmpty();
  466. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.EmptyBundle, empty);
  467. return empty;
  468. }
  469. protected void SetDuplicateWarning()
  470. {
  471. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.AssetsDuplicatedInMultBundles, true);
  472. m_Dirty = true;
  473. }
  474. internal bool isSceneBundle
  475. { get { return m_IsSceneBundle; } }
  476. internal override BundleTreeItem CreateTreeView(int depth)
  477. {
  478. RefreshAssetList();
  479. RefreshMessages();
  480. if (isSceneBundle)
  481. return new BundleTreeItem(this, depth, Model.GetSceneIcon());
  482. else
  483. return new BundleTreeItem(this, depth, Model.GetBundleIcon());
  484. }
  485. internal override void HandleReparent(string parentName, BundleFolderInfo newParent = null)
  486. {
  487. RefreshAssetList();
  488. string newName = System.String.IsNullOrEmpty(parentName) ? "" : parentName + '/';
  489. newName += m_Name.shortName;
  490. if (newName == m_Name.bundleName)
  491. return;
  492. if (newParent != null && newParent.GetChild(newName) != null)
  493. {
  494. Model.LogWarning("An item named '" + newName + "' already exists at this level in hierarchy. If your desire is to merge bundles, drag one on top of the other.");
  495. return;
  496. }
  497. foreach (var asset in m_ConcreteAssets)
  498. {
  499. Model.MoveAssetToBundle(asset, newName, m_Name.variant);
  500. }
  501. if (newParent != null)
  502. {
  503. m_Parent.HandleChildRename(m_Name.shortName, string.Empty);
  504. m_Parent = newParent;
  505. m_Parent.AddChild(this);
  506. }
  507. m_Name.SetBundleName(newName, m_Name.variant);
  508. }
  509. internal override List<AssetInfo> GetDependencies()
  510. {
  511. return m_DependentAssets;
  512. }
  513. internal override bool DoesItemMatchSearch(string search)
  514. {
  515. foreach(var asset in m_ConcreteAssets)
  516. {
  517. if (asset.displayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0)
  518. return true;
  519. }
  520. foreach (var asset in m_DependentAssets)
  521. {
  522. if (asset.displayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0)
  523. return true;
  524. }
  525. return false;
  526. }
  527. }
  528. internal class BundleVariantDataInfo : BundleDataInfo
  529. {
  530. protected List<AssetInfo> m_FolderIncludeAssets = new List<AssetInfo>();
  531. internal BundleVariantDataInfo(string name, BundleFolderInfo parent) : base(name, parent)
  532. {
  533. }
  534. internal override string displayName
  535. {
  536. get { return m_Name.variant; }
  537. }
  538. internal override void Update()
  539. {
  540. base.Update();
  541. (m_Parent as BundleVariantFolderInfo).ValidateVariants();
  542. }
  543. internal override void RefreshAssetList()
  544. {
  545. m_FolderIncludeAssets.Clear();
  546. base.RefreshAssetList();
  547. if(m_DependentAssets.Count > 0)
  548. m_FolderIncludeAssets = new List<AssetInfo>(m_DependentAssets);
  549. }
  550. internal bool IsSceneVariant()
  551. {
  552. RefreshAssetList();
  553. return isSceneBundle;
  554. }
  555. internal override bool HandleRename(string newName, int reverseDepth)
  556. {
  557. if (reverseDepth == 0)
  558. {
  559. RefreshAssetList();
  560. if (!m_Parent.HandleChildRename(m_Name.variant, newName))
  561. return false;
  562. m_Name.variant = newName;
  563. Model.MoveAssetToBundle(m_ConcreteAssets, m_Name.bundleName, m_Name.variant);
  564. }
  565. else if (reverseDepth == 1)
  566. {
  567. RefreshAssetList();
  568. m_Name.PartialNameChange(newName + "." + m_Name.variant, 0);
  569. Model.MoveAssetToBundle(m_ConcreteAssets, m_Name.bundleName, m_Name.variant);
  570. }
  571. else
  572. {
  573. return base.HandleRename(newName, reverseDepth-1);
  574. }
  575. return true;
  576. }
  577. internal override void HandleDelete(bool isRootOfDelete, string forcedNewName = "", string forcedNewVariant = "")
  578. {
  579. RefreshAssetList();
  580. if (isRootOfDelete)
  581. {
  582. m_Parent.HandleChildRename(m_Name.variant, string.Empty);
  583. }
  584. Model.MoveAssetToBundle(m_ConcreteAssets, forcedNewName, forcedNewVariant);
  585. }
  586. internal bool FindContentMismatch(BundleVariantDataInfo other)
  587. {
  588. bool result = false;
  589. if (m_FolderIncludeAssets.Count != 0 || other.m_FolderIncludeAssets.Count != 0)
  590. {
  591. var myUniqueAssets = new HashSet<string>();
  592. var otherUniqueAssets = new HashSet<string>(other.m_FolderIncludeAssets.Select(x => x.displayName));
  593. foreach (var asset in m_FolderIncludeAssets)
  594. {
  595. if (!otherUniqueAssets.Remove(asset.displayName))
  596. {
  597. myUniqueAssets.Add(asset.displayName);
  598. }
  599. }
  600. if (myUniqueAssets.Count > 0)
  601. {
  602. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.VariantBundleMismatch, true);
  603. result = true;
  604. }
  605. if (otherUniqueAssets.Count > 0)
  606. {
  607. other.m_BundleMessages.SetFlag(MessageSystem.MessageFlag.VariantBundleMismatch, true);
  608. result = true;
  609. }
  610. }
  611. else //this doesn't cover the super weird case of including a folder and some explicit assets. TODO - fix that.
  612. {
  613. var myUniqueAssets = new HashSet<string>();
  614. var otherUniqueAssets = new HashSet<string>(other.m_ConcreteAssets.Select(x => x.displayName));
  615. foreach (var asset in m_ConcreteAssets)
  616. {
  617. if (!otherUniqueAssets.Remove(asset.displayName))
  618. {
  619. myUniqueAssets.Add(asset.displayName);
  620. }
  621. }
  622. if (myUniqueAssets.Count > 0)
  623. {
  624. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.VariantBundleMismatch, true);
  625. result = true;
  626. }
  627. if (otherUniqueAssets.Count > 0)
  628. {
  629. other.m_BundleMessages.SetFlag(MessageSystem.MessageFlag.VariantBundleMismatch, true);
  630. result = true;
  631. }
  632. }
  633. return result;
  634. }
  635. }
  636. internal abstract class BundleFolderInfo : BundleInfo
  637. {
  638. protected Dictionary<string, BundleInfo> m_Children;
  639. internal BundleFolderInfo(string name, BundleFolderInfo parent) : base(name, parent)
  640. {
  641. m_Children = new Dictionary<string, BundleInfo>();
  642. }
  643. internal BundleFolderInfo(List<string> path, int depth, BundleFolderInfo parent) : base("", parent)
  644. {
  645. m_Children = new Dictionary<string, BundleInfo>();
  646. m_Name = new BundleNameData("");
  647. m_Name.pathTokens = path.GetRange(0, depth);
  648. }
  649. internal BundleInfo GetChild(string name)
  650. {
  651. if (name == null)
  652. return null;
  653. BundleInfo info = null;
  654. if (m_Children.TryGetValue(name, out info))
  655. return info;
  656. return null;
  657. }
  658. internal Dictionary<string, BundleInfo>.ValueCollection GetChildList()
  659. {
  660. return m_Children.Values;
  661. }
  662. internal abstract void AddChild(BundleInfo info);
  663. internal override bool HandleRename(string newName, int reverseDepth)
  664. {
  665. if (!base.HandleRename(newName, reverseDepth))
  666. return false;
  667. foreach (var child in m_Children)
  668. {
  669. child.Value.HandleRename(newName, reverseDepth + 1);
  670. }
  671. return true;
  672. }
  673. internal override void HandleDelete(bool isRootOfDelete, string forcedNewName="", string forcedNewVariant = "")
  674. {
  675. base.HandleDelete(isRootOfDelete);
  676. foreach (var child in m_Children)
  677. {
  678. child.Value.HandleDelete(false, forcedNewName, forcedNewVariant);
  679. }
  680. m_Children.Clear();
  681. }
  682. internal override bool DoesItemMatchSearch(string search)
  683. {
  684. return false; //folders don't ever match.
  685. }
  686. protected override void RefreshMessages()
  687. {
  688. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.ErrorInChildren, false);
  689. foreach(var child in m_Children)
  690. {
  691. if (child.Value.IsMessageSet(MessageSystem.MessageFlag.Error))
  692. {
  693. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.ErrorInChildren, true);
  694. break;
  695. }
  696. }
  697. base.RefreshMessages();
  698. }
  699. internal override bool RefreshEmptyStatus()
  700. {
  701. bool empty = m_Children.Count == 0;
  702. foreach (var child in m_Children)
  703. {
  704. empty |= child.Value.RefreshEmptyStatus();
  705. }
  706. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.EmptyFolder, empty);
  707. return empty;
  708. }
  709. internal override void RefreshAssetList()
  710. {
  711. foreach (var child in m_Children)
  712. {
  713. child.Value.RefreshAssetList();
  714. }
  715. }
  716. internal override bool RefreshDupeAssetWarning()
  717. {
  718. bool dupeWarning = false;
  719. foreach (var child in m_Children)
  720. {
  721. dupeWarning |= child.Value.RefreshDupeAssetWarning();
  722. }
  723. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.WarningInChildren, dupeWarning);
  724. return dupeWarning;
  725. }
  726. internal override void AddAssetsToNode(AssetTreeItem node)
  727. {
  728. foreach (var child in m_Children)
  729. {
  730. child.Value.AddAssetsToNode(node);
  731. }
  732. m_Dirty = false;
  733. }
  734. internal virtual bool HandleChildRename(string oldName, string newName)
  735. {
  736. if (!System.String.IsNullOrEmpty(newName) && m_Children.ContainsKey(newName))
  737. {
  738. Model.LogWarning("Attempting to name an item '" + newName + "' which matches existing name at this level in hierarchy. If your desire is to merge bundles, drag one on top of the other.");
  739. return false;
  740. }
  741. BundleInfo info = null;
  742. if (m_Children.TryGetValue(oldName, out info))
  743. {
  744. m_Children.Remove(oldName);
  745. if (!System.String.IsNullOrEmpty(newName))
  746. m_Children.Add(newName, info);
  747. }
  748. return true;
  749. }
  750. internal override void Update()
  751. {
  752. m_Dirty = false;
  753. m_DoneUpdating = true;
  754. foreach (var child in m_Children)
  755. {
  756. child.Value.Update();
  757. m_Dirty |= child.Value.dirty;
  758. m_DoneUpdating &= child.Value.doneUpdating;
  759. }
  760. if (m_Dirty || m_DoneUpdating)
  761. RefreshMessages();
  762. }
  763. internal override bool doneUpdating
  764. {
  765. get
  766. {
  767. foreach (var child in m_Children)
  768. {
  769. m_DoneUpdating &= child.Value.doneUpdating;
  770. }
  771. return base.doneUpdating;
  772. }
  773. }
  774. internal override List<AssetInfo> GetDependencies()
  775. {
  776. List<AssetInfo> assets = new List<AssetInfo>();
  777. foreach (var child in m_Children)
  778. {
  779. assets.AddRange(child.Value.GetDependencies());
  780. }
  781. return assets;
  782. }
  783. }
  784. internal class BundleFolderConcreteInfo : BundleFolderInfo
  785. {
  786. internal BundleFolderConcreteInfo(string name, BundleFolderInfo parent) : base(name, parent)
  787. {
  788. }
  789. internal BundleFolderConcreteInfo(List<string> path, int depth, BundleFolderInfo parent) : base(path, depth, parent)
  790. {
  791. }
  792. internal override void AddChild(BundleInfo info)
  793. {
  794. m_Children.Add(info.displayName, info);
  795. }
  796. internal override BundleTreeItem CreateTreeView(int depth)
  797. {
  798. RefreshMessages();
  799. var result = new BundleTreeItem(this, depth, Model.GetFolderIcon());
  800. foreach (var child in m_Children)
  801. {
  802. result.AddChild(child.Value.CreateTreeView(depth + 1));
  803. }
  804. return result;
  805. }
  806. internal override void HandleReparent(string parentName, BundleFolderInfo newParent = null)
  807. {
  808. string newName = System.String.IsNullOrEmpty(parentName) ? "" : parentName + '/';
  809. newName += displayName;
  810. if (newName == m_Name.bundleName)
  811. return;
  812. if (newParent != null && newParent.GetChild(newName) != null)
  813. {
  814. Model.LogWarning("An item named '" + newName + "' already exists at this level in hierarchy. If your desire is to merge bundles, drag one on top of the other.");
  815. return;
  816. }
  817. foreach (var child in m_Children)
  818. {
  819. child.Value.HandleReparent(newName);
  820. }
  821. if (newParent != null)
  822. {
  823. m_Parent.HandleChildRename(m_Name.shortName, string.Empty);
  824. m_Parent = newParent;
  825. m_Parent.AddChild(this);
  826. }
  827. m_Name.SetBundleName(newName, m_Name.variant);
  828. }
  829. }
  830. internal class BundleVariantFolderInfo : BundleFolderInfo
  831. {
  832. internal BundleVariantFolderInfo(string name, BundleFolderInfo parent) : base(name, parent)
  833. {
  834. }
  835. internal override void AddChild(BundleInfo info)
  836. {
  837. m_Children.Add(info.m_Name.variant, info);
  838. }
  839. private bool m_validated;
  840. internal override void Update()
  841. {
  842. m_validated = false;
  843. base.Update();
  844. if(!m_validated)
  845. ValidateVariants();
  846. }
  847. internal void ValidateVariants()
  848. {
  849. m_validated = true;
  850. bool childMismatch = false;
  851. if(m_Children.Count > 1)
  852. {
  853. BundleVariantDataInfo goldChild = null;
  854. foreach(var c in m_Children)
  855. {
  856. var child = c.Value as BundleVariantDataInfo;
  857. child.SetMessageFlag(MessageSystem.MessageFlag.VariantBundleMismatch, false);
  858. if (goldChild == null)
  859. {
  860. goldChild = child;
  861. continue;
  862. }
  863. childMismatch |= goldChild.FindContentMismatch(child);
  864. }
  865. }
  866. m_BundleMessages.SetFlag(MessageSystem.MessageFlag.VariantBundleMismatch, childMismatch);
  867. }
  868. internal override BundleTreeItem CreateTreeView(int depth)
  869. {
  870. RefreshMessages();
  871. Texture2D icon = null;
  872. if ((m_Children.Count > 0) &&
  873. ((m_Children.First().Value as BundleVariantDataInfo).IsSceneVariant()))
  874. {
  875. icon = Model.GetSceneIcon();
  876. }
  877. else
  878. icon = Model.GetBundleIcon();
  879. var result = new BundleTreeItem(this, depth, icon);
  880. foreach (var child in m_Children)
  881. {
  882. result.AddChild(child.Value.CreateTreeView(depth + 1));
  883. }
  884. return result;
  885. }
  886. internal override void HandleReparent(string parentName, BundleFolderInfo newParent = null)
  887. {
  888. string newName = System.String.IsNullOrEmpty(parentName) ? "" : parentName + '/';
  889. newName += displayName;
  890. if (newName == m_Name.bundleName)
  891. return;
  892. if (newParent != null && newParent.GetChild(newName) != null)
  893. {
  894. Model.LogWarning("An item named '" + newName + "' already exists at this level in hierarchy. If your desire is to merge bundles, drag one on top of the other.");
  895. return;
  896. }
  897. foreach (var child in m_Children)
  898. {
  899. child.Value.HandleReparent(parentName);
  900. }
  901. if (newParent != null)
  902. {
  903. m_Parent.HandleChildRename(m_Name.shortName, string.Empty);
  904. m_Parent = newParent;
  905. m_Parent.AddChild(this);
  906. }
  907. m_Name.SetBundleName(newName, string.Empty) ;
  908. }
  909. internal override bool HandleChildRename(string oldName, string newName)
  910. {
  911. var result = base.HandleChildRename(oldName, newName);
  912. if (m_Children.Count == 0)
  913. HandleDelete(true);
  914. return result;
  915. }
  916. }
  917. }