WwiseProjectDatabaseSource.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. #include "WwiseProjectDatabaseSource.h"
  2. #include "IAudiokineticTools.h"
  3. #include "AssetManagement/AkAssetDatabase.h"
  4. #include "Async/Async.h"
  5. #include "WaapiPicker/WwiseTreeItem.h"
  6. #include "Wwise/WwiseProjectDatabase.h"
  7. #include "Wwise/WwiseProjectDatabaseDelegates.h"
  8. #include "Wwise/Metadata/WwiseMetadataProjectInfo.h"
  9. FWwiseProjectDatabaseDataSource::~FWwiseProjectDatabaseDataSource()
  10. {
  11. if (OnDatabaseUpdateCompleteHandle.IsValid())
  12. {
  13. FWwiseProjectDatabaseDelegates::Get().GetOnDatabaseUpdateCompletedDelegate().Remove(OnDatabaseUpdateCompleteHandle);
  14. OnDatabaseUpdateCompleteHandle.Reset();
  15. }
  16. }
  17. FText FWwiseProjectDatabaseDataSource::GetProjectName()
  18. {
  19. auto* ProjectDatabase = FWwiseProjectDatabase::Get();
  20. if (UNLIKELY(!ProjectDatabase))
  21. {
  22. return {};
  23. }
  24. const FWwiseDataStructureScopeLock DataStructure(*ProjectDatabase);
  25. const FWwiseRefPlatform Platform = DataStructure.GetPlatform(ProjectDatabase->GetCurrentPlatform());
  26. if (Platform.IsValid())
  27. {
  28. if (const FWwiseMetadataProjectInfo* ProjectInfo = Platform.ProjectInfo.GetProjectInfo())
  29. {
  30. return FText::FromName(ProjectInfo->Project.Name);
  31. }
  32. }
  33. return {};
  34. }
  35. bool FWwiseProjectDatabaseDataSource::Init()
  36. {
  37. OnDatabaseUpdateCompleteHandle = FWwiseProjectDatabaseDelegates::Get().GetOnDatabaseUpdateCompletedDelegate().AddLambda([this]
  38. {
  39. AsyncTask(ENamedThreads::Type::GameThread, [this]
  40. {
  41. this->ConstructTree(true);
  42. });
  43. });
  44. return true;
  45. }
  46. void FWwiseProjectDatabaseDataSource::ConstructTree(bool bShouldRefresh)
  47. {
  48. UE_LOG(LogAudiokineticTools, Log, TEXT("Rebuilding tree for Wwise Browser"));
  49. FWwiseProjectDatabase* ProjectDatabase = FWwiseProjectDatabase::Get();
  50. if (UNLIKELY(!ProjectDatabase))
  51. {
  52. UE_LOG(LogAudiokineticTools, Error, TEXT("ConstructTree: ProjectDatabase not loaded"));
  53. return;
  54. }
  55. AllValidTreeItemsByGuid.Empty();
  56. {
  57. FScopeLock AutoLock(&RootItemsLock);
  58. RootItems.Empty();
  59. RootItems.SetNum(EWwiseItemType::LastWwiseBrowserType + 1);
  60. }
  61. NodesByPath.Empty();
  62. {
  63. const FWwiseDataStructureScopeLock DataStructure(*ProjectDatabase);
  64. if (DataStructure.GetCurrentPlatformData() == nullptr)
  65. {
  66. return;
  67. }
  68. const WwiseEventGlobalIdsMap& Events = DataStructure.GetEvents();
  69. const WwiseBusGlobalIdsMap& Busses = DataStructure.GetBusses();
  70. const WwiseAuxBusGlobalIdsMap& AuxBusses = DataStructure.GetAuxBusses();
  71. const WwiseAcousticTextureGlobalIdsMap& AcousticTextures = DataStructure.GetAcousticTextures();
  72. const WwiseStateGroupGlobalIdsMap& StateGroups = DataStructure.GetStateGroups();
  73. const WwiseStateGlobalIdsMap& States = DataStructure.GetStates();
  74. const WwiseSwitchGlobalIdsMap& Switches = DataStructure.GetSwitches();
  75. const WwiseGameParameterGlobalIdsMap& GameParameters = DataStructure.GetGameParameters();
  76. const WwiseTriggerGlobalIdsMap& Triggers = DataStructure.GetTriggers();
  77. const WwisePluginShareSetGlobalIdsMap& EffectShareSets = DataStructure.GetPluginShareSets();
  78. const WwiseSwitchGroupGlobalIdsMap SwitchGroups = DataStructure.GetSwitchGroups();
  79. BuildEvents(Events);
  80. BuildBusses(Busses);
  81. BuildAuxBusses(AuxBusses);
  82. BuildAcousticTextures(AcousticTextures);
  83. BuildStateGroups(StateGroups);
  84. BuildStates(States);
  85. BuildSwitchGroups(SwitchGroups);
  86. BuildSwitches(Switches);
  87. BuildGameParameters(GameParameters);
  88. BuildTriggers(Triggers);
  89. BuildEffectShareSets(EffectShareSets);
  90. }
  91. if(bShouldRefresh)
  92. {
  93. ProjectDatabaseDataSourceRefreshed.ExecuteIfBound();
  94. }
  95. }
  96. FWwiseTreeItemPtr FWwiseProjectDatabaseDataSource::ConstructTreeRoot(EWwiseItemType::Type Type)
  97. {
  98. ConstructTree(false);
  99. {
  100. FScopeLock AutoLock(&RootItemsLock);
  101. return RootItems[Type];
  102. }
  103. }
  104. int32 FWwiseProjectDatabaseDataSource::LoadChildren(
  105. const FGuid& InParentId, const FString& InParentPath, TArray<FWwiseTreeItemPtr>& OutChildren)
  106. {
  107. FWwiseTreeItemPtr* TreeItem = NodesByPath.Find(InParentPath);
  108. if (TreeItem && TreeItem->IsValid())
  109. {
  110. OutChildren = TreeItem->Get()->GetChildren();
  111. }
  112. else
  113. {
  114. OutChildren = {};
  115. }
  116. return OutChildren.Num();
  117. }
  118. int32 FWwiseProjectDatabaseDataSource::LoadChildren(FWwiseTreeItemPtr InParentItem)
  119. {
  120. if (!InParentItem)
  121. {
  122. return 0;
  123. }
  124. // For now, we have to construct the whole tree at once, so this can't be individually loaded. So we return what we have.
  125. return InParentItem->GetChildren().Num();
  126. }
  127. int32 FWwiseProjectDatabaseDataSource::GetChildItemCount(const FWwiseTreeItemPtr& InParentItem)
  128. {
  129. return InParentItem->GetChildren().Num();
  130. }
  131. FWwiseTreeItemPtr FWwiseProjectDatabaseDataSource::GetRootItem(EWwiseItemType::Type RootType)
  132. {
  133. check(RootType <= EWwiseItemType::LastWwiseBrowserType)
  134. if (RootType > RootItems.Num() - 1)
  135. {
  136. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to get the Project Database Root Items. Index out of range."));
  137. return nullptr;
  138. }
  139. return RootItems[RootType];
  140. }
  141. FWwiseTreeItemPtr FWwiseProjectDatabaseDataSource::LoadFilteredRootItem(EWwiseItemType::Type ItemType,
  142. TSharedPtr<StringFilter> CurrentFilter)
  143. {
  144. check(CurrentFilter.IsValid())
  145. FWwiseTreeItemPtr CurrentTreeRootItem;
  146. {
  147. FScopeLock AutoLock(&RootItemsLock);
  148. if (ItemType > RootItems.Num())
  149. {
  150. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to get the Project Database Root Items. Index out of range."));
  151. return nullptr;
  152. }
  153. CurrentTreeRootItem = RootItems[ItemType];
  154. FString CurrentFilterText = CurrentFilter->GetRawFilterText().ToString();
  155. if (!CurrentFilterText.IsEmpty() && CurrentTreeRootItem.IsValid())
  156. {
  157. FWwiseTreeItemPtr FilteredTreeRootItem = MakeShared<FWwiseTreeItem>(EWwiseItemType::BrowserDisplayNames[ItemType],
  158. CurrentTreeRootItem->FolderPath, nullptr, EWwiseItemType::Folder, FGuid(CurrentTreeRootItem->ItemId));
  159. FilteredTreeRootItem->ChildCountInWwise = CurrentTreeRootItem->ChildCountInWwise;
  160. if (!OldFilterText.IsEmpty() && CurrentFilterText.StartsWith(OldFilterText))
  161. {
  162. CopyTree(CurrentTreeRootItem, FilteredTreeRootItem);
  163. }
  164. else
  165. {
  166. CopyTree(RootItems[ItemType], FilteredTreeRootItem);
  167. }
  168. FilterTree(FilteredTreeRootItem, CurrentFilter);
  169. OldFilterText = CurrentFilterText;
  170. return FilteredTreeRootItem;
  171. }
  172. if (RootItems[ItemType])
  173. {
  174. return RootItems[ItemType];
  175. }
  176. return nullptr;
  177. }
  178. }
  179. FWwiseTreeItemPtr FWwiseProjectDatabaseDataSource::FindItemFromPath(const FString& InCurrentItemPath)
  180. {
  181. FWwiseTreeItemPtr* FoundItem = NodesByPath.Find(InCurrentItemPath);
  182. if (FoundItem)
  183. {
  184. return *FoundItem;
  185. }
  186. return nullptr;
  187. }
  188. FWwiseTreeItemPtr FWwiseProjectDatabaseDataSource::FindItem(const FWwiseTreeItemPtr InItem)
  189. {
  190. FWwiseTreeItemPtr* FoundItem = AllValidTreeItemsByGuid.Find(InItem->ItemId);
  191. if (FoundItem)
  192. {
  193. return *FoundItem;
  194. }
  195. for(auto TreeItem : AllValidTreeItemsByGuid)
  196. {
  197. if (TreeItem.Value->ShortId == InItem->ShortId && InItem->ShortId > 0)
  198. {
  199. return TreeItem.Value;
  200. }
  201. if(TreeItem.Value->DisplayName == InItem->DisplayName)
  202. {
  203. return TreeItem.Value;
  204. }
  205. }
  206. return nullptr;
  207. }
  208. void FWwiseProjectDatabaseDataSource::BuildEvents(const WwiseEventGlobalIdsMap& Events)
  209. {
  210. const auto& FolderItem = MakeShared<FWwiseTreeItem>(EWwiseItemType::EventsBrowserName, TEXT("\\") + EWwiseItemType::FolderNames[EWwiseItemType::Event], nullptr, EWwiseItemType::Folder, FGuid());
  211. NodesByPath.Add(FolderItem->FolderPath, FolderItem);
  212. {
  213. FScopeLock AutoLock(&RootItemsLock);
  214. RootItems[EWwiseItemType::Event] = FolderItem;
  215. }
  216. for (const auto& Event : Events)
  217. {
  218. const auto& WwiseItem = Event.Value.GetEvent();
  219. UE_LOG(LogAudiokineticTools, VeryVerbose, TEXT("Event Name: %s"), *WwiseItem->Name.ToString());
  220. FWwiseMetadataBasicReference EventRef = FWwiseMetadataBasicReference(WwiseItem->Id, WwiseItem->Name, WwiseItem->ObjectPath, WwiseItem->GUID);
  221. if (!BuildFolderHierarchy(EventRef, EWwiseItemType::Event, FolderItem))
  222. {
  223. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  224. }
  225. }
  226. FolderItem->ChildCountInWwise = FolderItem->GetChildren().Num();
  227. }
  228. void FWwiseProjectDatabaseDataSource::BuildBusses(const WwiseBusGlobalIdsMap& Busses)
  229. {
  230. const auto& FolderItem = MakeShared<FWwiseTreeItem>(EWwiseItemType::BussesBrowserName, TEXT("\\") + EWwiseItemType::FolderNames[EWwiseItemType::AuxBus], nullptr, EWwiseItemType::Folder, FGuid());
  231. NodesByPath.Add(FolderItem->FolderPath, FolderItem);
  232. {
  233. FScopeLock AutoLock(&RootItemsLock);
  234. RootItems[EWwiseItemType::AuxBus] = FolderItem;
  235. }
  236. for (auto& Bus : Busses)
  237. {
  238. const auto& WwiseItem = Bus.Value.GetBus();
  239. UE_LOG(LogAudiokineticTools, VeryVerbose, TEXT("Bus Name: %s"), *WwiseItem->Name.ToString());
  240. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::Bus, FolderItem))
  241. {
  242. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  243. }
  244. }
  245. FolderItem->ChildCountInWwise = FolderItem->GetChildren().Num();
  246. }
  247. void FWwiseProjectDatabaseDataSource::BuildAuxBusses(const WwiseAuxBusGlobalIdsMap& AuxBusses)
  248. {
  249. FWwiseTreeItemPtr FolderItem;
  250. {
  251. FScopeLock AutoLock(&RootItemsLock);
  252. FolderItem = RootItems[EWwiseItemType::AuxBus];
  253. }
  254. for (const auto& AuxBus : AuxBusses)
  255. {
  256. const auto& WwiseItem = AuxBus.Value.GetAuxBus();
  257. UE_LOG(LogAudiokineticTools, VeryVerbose, TEXT("Aux Bus Name: %s"), *WwiseItem->Name.ToString());
  258. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::AuxBus, FolderItem))
  259. {
  260. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  261. }
  262. }
  263. }
  264. void FWwiseProjectDatabaseDataSource::BuildAcousticTextures(const WwiseAcousticTextureGlobalIdsMap& AcousticTextures)
  265. {
  266. const auto& FolderItem = MakeShared<FWwiseTreeItem>(EWwiseItemType::AcousticTexturesBrowserName, TEXT("\\") + EWwiseItemType::FolderNames[EWwiseItemType::AcousticTexture], nullptr, EWwiseItemType::Folder, FGuid());
  267. NodesByPath.Add(FolderItem->FolderPath, FolderItem);
  268. {
  269. FScopeLock AutoLock(&RootItemsLock);
  270. RootItems[EWwiseItemType::AcousticTexture] = FolderItem;
  271. }
  272. for (const auto& AcousticTexture : AcousticTextures)
  273. {
  274. const FWwiseMetadataAcousticTexture* WwiseItem = AcousticTexture.Value.GetAcousticTexture();
  275. UE_LOG(LogAudiokineticTools, VeryVerbose, TEXT("Acoustic Texture Name: %s"), *WwiseItem->Name.ToString());
  276. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::AcousticTexture, FolderItem))
  277. {
  278. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  279. }
  280. }
  281. FolderItem->ChildCountInWwise = FolderItem->GetChildren().Num();
  282. }
  283. void FWwiseProjectDatabaseDataSource::BuildStateGroups(const WwiseStateGroupGlobalIdsMap& StateGroups)
  284. {
  285. const auto& FolderItem = MakeShared<FWwiseTreeItem>(EWwiseItemType::StatesBrowserName, TEXT("\\") + EWwiseItemType::FolderNames[EWwiseItemType::State], nullptr, EWwiseItemType::Folder, FGuid());
  286. NodesByPath.Add(FolderItem->FolderPath, FolderItem);
  287. {
  288. FScopeLock AutoLock(&RootItemsLock);
  289. RootItems[EWwiseItemType::State] = FolderItem;
  290. }
  291. for (const auto& StateGroup : StateGroups)
  292. {
  293. const auto& WwiseItem = StateGroup.Value.GetStateGroup();
  294. UE_LOG(LogAudiokineticTools, VeryVerbose, TEXT("State Group Name: %s"), *WwiseItem->Name.ToString());
  295. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::StateGroup, FolderItem))
  296. {
  297. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  298. }
  299. }
  300. FolderItem->ChildCountInWwise = FolderItem->GetChildren().Num();
  301. }
  302. void FWwiseProjectDatabaseDataSource::BuildStates(const WwiseStateGlobalIdsMap& States)
  303. {
  304. FWwiseTreeItemPtr StateGroupFolderItem;
  305. {
  306. FScopeLock AutoLock(&RootItemsLock);
  307. StateGroupFolderItem = RootItems[EWwiseItemType::State];
  308. }
  309. for (const auto& State : States)
  310. {
  311. const auto& WwiseItem = State.Value.GetState();
  312. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::State, StateGroupFolderItem))
  313. {
  314. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  315. }
  316. }
  317. }
  318. void FWwiseProjectDatabaseDataSource::BuildSwitchGroups(const WwiseSwitchGroupGlobalIdsMap& SwitchGroups)
  319. {
  320. const auto& FolderItem = MakeShared<FWwiseTreeItem>(EWwiseItemType::SwitchesBrowserName, TEXT("\\") + EWwiseItemType::FolderNames[EWwiseItemType::Switch], nullptr, EWwiseItemType::Folder, FGuid());
  321. NodesByPath.Add(FolderItem->FolderPath, FolderItem);
  322. {
  323. FScopeLock AutoLock(&RootItemsLock);
  324. RootItems[EWwiseItemType::Switch] = FolderItem;
  325. }
  326. for (const auto& SwitchGroup : SwitchGroups)
  327. {
  328. const auto& WwiseItem = SwitchGroup.Value.GetSwitchGroup();
  329. UE_LOG(LogAudiokineticTools, VeryVerbose, TEXT("Switch Group Name: %s"), *WwiseItem->Name.ToString());
  330. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::SwitchGroup, FolderItem))
  331. {
  332. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  333. }
  334. }
  335. FolderItem->ChildCountInWwise = FolderItem->GetChildren().Num();
  336. }
  337. void FWwiseProjectDatabaseDataSource::BuildSwitches(const WwiseSwitchGlobalIdsMap& Switches)
  338. {
  339. FWwiseTreeItemPtr SwitchGroupFolderItem;
  340. {
  341. FScopeLock AutoLock(&RootItemsLock);
  342. SwitchGroupFolderItem = RootItems[EWwiseItemType::Switch];
  343. }
  344. for (const auto& Switch : Switches)
  345. {
  346. const auto& WwiseItem = Switch.Value.GetSwitch();
  347. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::Switch, SwitchGroupFolderItem))
  348. {
  349. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  350. }
  351. }
  352. }
  353. void FWwiseProjectDatabaseDataSource::BuildGameParameters(const WwiseGameParameterGlobalIdsMap& GameParameters)
  354. {
  355. const auto& FolderItem = MakeShared<FWwiseTreeItem>(EWwiseItemType::GameParametersBrowserName, TEXT("\\") + EWwiseItemType::FolderNames[EWwiseItemType::GameParameter], nullptr, EWwiseItemType::Folder, FGuid());
  356. NodesByPath.Add(FolderItem->FolderPath, FolderItem);
  357. {
  358. FScopeLock AutoLock(&RootItemsLock);
  359. RootItems[EWwiseItemType::GameParameter] = FolderItem;
  360. }
  361. for (const auto& GameParameter : GameParameters)
  362. {
  363. const FWwiseMetadataGameParameter* WwiseItem = GameParameter.Value.GetGameParameter();
  364. UE_LOG(LogAudiokineticTools, VeryVerbose, TEXT("GameParameter Name: %s"), *WwiseItem->Name.ToString());
  365. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::GameParameter, FolderItem))
  366. {
  367. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  368. }
  369. }
  370. FolderItem->ChildCountInWwise = FolderItem->GetChildren().Num();
  371. }
  372. void FWwiseProjectDatabaseDataSource::BuildTriggers(const WwiseTriggerGlobalIdsMap& Triggers)
  373. {
  374. const auto& FolderItem = MakeShared<FWwiseTreeItem>(EWwiseItemType::TriggersBrowserName, TEXT("\\") + EWwiseItemType::FolderNames[EWwiseItemType::Trigger], nullptr, EWwiseItemType::Folder, FGuid());
  375. NodesByPath.Add(FolderItem->FolderPath, FolderItem);
  376. {
  377. FScopeLock AutoLock(&RootItemsLock);
  378. RootItems[EWwiseItemType::Trigger] = FolderItem;
  379. }
  380. for (const auto& Trigger : Triggers)
  381. {
  382. const auto& WwiseItem = Trigger.Value.GetTrigger();
  383. UE_LOG(LogAudiokineticTools, VeryVerbose, TEXT("Trigger Name: %s"), *WwiseItem->Name.ToString());
  384. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::Trigger, FolderItem))
  385. {
  386. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  387. }
  388. }
  389. FolderItem->ChildCountInWwise = FolderItem->GetChildren().Num();
  390. }
  391. void FWwiseProjectDatabaseDataSource::BuildEffectShareSets(const WwisePluginShareSetGlobalIdsMap& EffectShareSets)
  392. {
  393. const auto& FolderItem = MakeShared<FWwiseTreeItem>(EWwiseItemType::ShareSetsBrowserName, TEXT("\\") + EWwiseItemType::FolderNames[EWwiseItemType::EffectShareSet], nullptr, EWwiseItemType::Folder, FGuid());
  394. NodesByPath.Add(FolderItem->FolderPath, FolderItem);
  395. {
  396. FScopeLock AutoLock(&RootItemsLock);
  397. RootItems[EWwiseItemType::EffectShareSet] = FolderItem;
  398. }
  399. for (const auto& EffectShareSet : EffectShareSets)
  400. {
  401. const auto& WwiseItem = EffectShareSet.Value.GetPlugin();
  402. UE_LOG(LogAudiokineticTools, VeryVerbose, TEXT("ShareSet Name: %s"), *WwiseItem->Name.ToString());
  403. if (!BuildFolderHierarchy(*WwiseItem, EWwiseItemType::EffectShareSet, FolderItem))
  404. {
  405. UE_LOG(LogAudiokineticTools, Error, TEXT("Failed to place %s in the Wwise Browser"), *WwiseItem->ObjectPath.ToString());
  406. }
  407. }
  408. FolderItem->ChildCountInWwise = FolderItem->GetChildren().Num();
  409. }
  410. bool FWwiseProjectDatabaseDataSource::ParseTreePath(const FString& ObjectPath, WwiseItemTreePath& OutItemPath)
  411. {
  412. TArray<FString> SwitchPartsArray;
  413. ObjectPath.ParseIntoArray(SwitchPartsArray, TEXT("\\"));
  414. if (SwitchPartsArray.Num() < 3)
  415. {
  416. UE_LOG(LogAudiokineticTools, Warning, TEXT("Failed to determine object hierarchy from path: %s"), *ObjectPath);
  417. return false;
  418. }
  419. OutItemPath.HierarchyName = SwitchPartsArray[0];
  420. OutItemPath.RootFolder = SwitchPartsArray[1];
  421. OutItemPath.ItemName = SwitchPartsArray[SwitchPartsArray.Num() - 1];
  422. for (int i = 2; i < SwitchPartsArray.Num() - 1; ++i)
  423. {
  424. OutItemPath.IntermediateFolders.Add(SwitchPartsArray[i]);
  425. }
  426. return true;
  427. }
  428. bool FWwiseProjectDatabaseDataSource::IsContainer(EWwiseItemType::Type ItemType) const
  429. {
  430. return ItemType == EWwiseItemType::Bus || ItemType == EWwiseItemType::SwitchGroup || ItemType ==
  431. EWwiseItemType::StateGroup || ItemType == EWwiseItemType::AuxBus || ItemType == EWwiseItemType::MotionBus;
  432. }
  433. bool FWwiseProjectDatabaseDataSource::BuildFolderHierarchy(
  434. const FWwiseMetadataBasicReference& WwiseItem, EWwiseItemType::Type
  435. ItemType, const FWwiseTreeItemPtr CurrentRootFolder)
  436. {
  437. const FString ItemPath = WwiseItem.ObjectPath.ToString();
  438. WwiseItemTreePath TreePath;
  439. FWwiseTreeItemPtr ParentItem = CurrentRootFolder;
  440. if (ParseTreePath(ItemPath, TreePath))
  441. {
  442. FString CurrentPath = "\\" + TreePath.HierarchyName;
  443. TArray<FString> AllFolders = TArray<FString>{ TreePath.RootFolder };
  444. AllFolders.Append(TreePath.IntermediateFolders);
  445. for (FString FolderName : AllFolders)
  446. {
  447. CurrentPath.Append("\\").Append(FolderName);
  448. FWwiseTreeItemPtr FolderItem;
  449. FWwiseTreeItemPtr* FolderItemPtr = NodesByPath.Find(CurrentPath);
  450. if (!FolderItemPtr)
  451. {
  452. FolderItem = MakeShared<FWwiseTreeItem>(FolderName, CurrentPath, ParentItem,
  453. EWwiseItemType::Folder, FGuid());
  454. NodesByPath.Add(CurrentPath, FolderItem);
  455. ParentItem->AddChild(FolderItem);
  456. ParentItem->ChildCountInWwise = ParentItem->GetChildren().Num();
  457. }
  458. else
  459. {
  460. FolderItem = *FolderItemPtr;
  461. }
  462. ParentItem = FolderItem;
  463. }
  464. if (!AllValidTreeItemsByGuid.Find(WwiseItem.GUID))
  465. {
  466. if(auto TreeItemPtr = NodesByPath.Find(WwiseItem.ObjectPath.ToString()))
  467. {
  468. auto TreeItem = *TreeItemPtr;
  469. TreeItem->ItemType = ItemType;
  470. TreeItem->ItemId = WwiseItem.GUID;
  471. TreeItem->ShortId = WwiseItem.Id;
  472. }
  473. else
  474. {
  475. const auto& NewWwiseTreeItem = MakeShared<FWwiseTreeItem>(WwiseItem, ParentItem, ItemType);
  476. NewWwiseTreeItem->ShortId = WwiseItem.Id;
  477. ParentItem->AddChild(NewWwiseTreeItem);
  478. AllValidTreeItemsByGuid.Add(NewWwiseTreeItem->ItemId, NewWwiseTreeItem);
  479. if (IsContainer(ItemType))
  480. {
  481. NodesByPath.Add(WwiseItem.ObjectPath.ToString(), NewWwiseTreeItem);
  482. }
  483. }
  484. }
  485. return true;
  486. }
  487. return false;
  488. }
  489. void FWwiseProjectDatabaseDataSource::CopyTree(FWwiseTreeItemPtr SourceTreeItem, FWwiseTreeItemPtr DestTreeItem)
  490. {
  491. for (auto& CurrItem: SourceTreeItem->GetChildren())
  492. {
  493. FWwiseTreeItemPtr NewItem = MakeShared<FWwiseTreeItem>(CurrItem->DisplayName, CurrItem->FolderPath, CurrItem->Parent.Pin(), CurrItem->ItemType, CurrItem->ItemId);
  494. NewItem->WwiseItemRef = CurrItem->WwiseItemRef;
  495. DestTreeItem->AddChild(NewItem);
  496. DestTreeItem->ChildCountInWwise = SourceTreeItem->ChildCountInWwise;
  497. CopyTree(CurrItem, NewItem);
  498. }
  499. }
  500. void FWwiseProjectDatabaseDataSource::FilterTree(FWwiseTreeItemPtr TreeItem, TSharedPtr<StringFilter> SearchFilter)
  501. {
  502. TArray<FWwiseTreeItemPtr> ItemsToRemove;
  503. for (auto& CurrItem: TreeItem->GetChildren())
  504. {
  505. FilterTree(CurrItem, SearchFilter);
  506. if (!SearchFilter->PassesFilter(CurrItem->DisplayName) && CurrItem->GetChildren().Num() == 0)
  507. {
  508. ItemsToRemove.Add(CurrItem);
  509. }
  510. }
  511. for (int32 i = 0; i < ItemsToRemove.Num(); i++)
  512. {
  513. TreeItem->RemoveChild(ItemsToRemove[i]);
  514. }
  515. TreeItem->ChildCountInWwise = TreeItem->GetChildren().Num();
  516. }