WwiseResourceLoaderImpl.cpp 104 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. #include "Wwise/WwiseResourceLoaderImpl.h"
  16. #include "Wwise/CookedData/WwiseInitBankCookedData.h"
  17. #include "Wwise/CookedData/WwiseLocalizedAuxBusCookedData.h"
  18. #include "Wwise/CookedData/WwiseLocalizedSoundBankCookedData.h"
  19. #include "Wwise/CookedData/WwiseLocalizedEventCookedData.h"
  20. #include "Wwise/CookedData/WwiseLocalizedShareSetCookedData.h"
  21. #include "Wwise/API/WwiseSoundEngineAPI.h"
  22. #include "Wwise/Stats/AsyncStats.h"
  23. #include "Wwise/WwiseExternalSourceManager.h"
  24. #include "Wwise/WwiseGlobalCallbacks.h"
  25. #include "Wwise/WwiseMediaManager.h"
  26. #include "Wwise/WwiseResourceLoader.h"
  27. #include "Wwise/WwiseSoundBankManager.h"
  28. #include "Async/Async.h"
  29. #include <inttypes.h>
  30. FWwiseSwitchContainerLeafGroupValueUsageCount::FLoadedData::FLoadedData()
  31. {
  32. }
  33. bool FWwiseSwitchContainerLeafGroupValueUsageCount::FLoadedData::IsLoaded() const
  34. {
  35. return LoadedSoundBanks.Num() > 0 || LoadedExternalSources.Num() > 0 || LoadedMedia.Num() > 0;
  36. }
  37. FWwiseSwitchContainerLeafGroupValueUsageCount::FWwiseSwitchContainerLeafGroupValueUsageCount(
  38. const FWwiseSwitchContainerLeafCookedData& InKey):
  39. Key(InKey)
  40. {}
  41. bool FWwiseSwitchContainerLeafGroupValueUsageCount::HaveAllKeys() const
  42. {
  43. if (UNLIKELY(Key.GroupValueSet.Num() < LoadedGroupValues.Num()))
  44. {
  45. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Have more keys loaded (%d) than existing in key (%d) @ %p for key %s"),
  46. LoadedGroupValues.Num(), Key.GroupValueSet.Num(), &LoadedData, *Key.GetDebugString());
  47. return true;
  48. }
  49. return Key.GroupValueSet.Num() == LoadedGroupValues.Num();
  50. }
  51. FWwiseResourceLoaderImpl::FWwiseResourceLoaderImpl()
  52. {
  53. }
  54. FName FWwiseResourceLoaderImpl::GetUnrealExternalSourcePath() const
  55. {
  56. #if WITH_EDITORONLY_DATA
  57. return FName(GeneratedSoundBanksPath.Path / CurrentPlatform.Platform->PathRelativeToGeneratedSoundBanks.ToString() / CurrentPlatform.Platform->ExternalSourceRootPath.ToString());
  58. #else
  59. auto* ExternalSourceManager = IWwiseExternalSourceManager::Get();
  60. if (UNLIKELY(!ExternalSourceManager))
  61. {
  62. UE_LOG(LogWwiseResourceLoader, Error, TEXT("GetUnrealExternalSourcePath: Failed to retrieve External Source Manager, returning empty string."));
  63. return {};
  64. }
  65. return FName(FPaths::ProjectContentDir() / ExternalSourceManager->GetStagingDirectory());
  66. #endif
  67. }
  68. FString FWwiseResourceLoaderImpl::GetUnrealPath() const
  69. {
  70. #if WITH_EDITOR
  71. return GeneratedSoundBanksPath.Path / CurrentPlatform.Platform->PathRelativeToGeneratedSoundBanks.ToString();
  72. #elif WITH_EDITORONLY_DATA
  73. UE_LOG(LogWwiseResourceLoader, Error, TEXT("GetUnrealPath should not be used in WITH_EDITORONLY_DATA (Getting path for %s)"), *InPath);
  74. return GeneratedSoundBanksPath.Path / CurrentPlatform.Platform->PathRelativeToGeneratedSoundBanks;
  75. #else
  76. return StagePath;
  77. #endif
  78. }
  79. FString FWwiseResourceLoaderImpl::GetUnrealPath(const FString& InPath) const
  80. {
  81. #if WITH_EDITOR
  82. return GetUnrealGeneratedSoundBanksPath(InPath);
  83. #elif WITH_EDITORONLY_DATA
  84. UE_LOG(LogWwiseResourceLoader, Error, TEXT("GetUnrealPath should not be used in WITH_EDITORONLY_DATA (Getting path for %s)"), *InPath);
  85. return GetUnrealGeneratedSoundBanksPath(InPath);
  86. #else
  87. return GetUnrealStagePath(InPath);
  88. #endif
  89. }
  90. FString FWwiseResourceLoaderImpl::GetUnrealStagePath(const FString& InPath) const
  91. {
  92. if (UNLIKELY(StagePath.IsEmpty()))
  93. {
  94. UE_LOG(LogWwiseResourceLoader, Error, TEXT("StagePath not set up (GetUnrealStagePath for %s)"), *InPath);
  95. }
  96. return StagePath / InPath;
  97. }
  98. #if WITH_EDITORONLY_DATA
  99. FString FWwiseResourceLoaderImpl::GetUnrealGeneratedSoundBanksPath(const FString& InPath) const
  100. {
  101. if (UNLIKELY(GeneratedSoundBanksPath.Path.IsEmpty()))
  102. {
  103. UE_LOG(LogWwiseResourceLoader, Error, TEXT("GeneratedSoundBanksPath not set up (GetUnrealGeneratedSoundBanksPath for %s)"), *InPath);
  104. }
  105. return GeneratedSoundBanksPath.Path / CurrentPlatform.Platform->PathRelativeToGeneratedSoundBanks.ToString() / InPath;
  106. }
  107. #endif
  108. EWwiseResourceLoaderState FWwiseResourceLoaderImpl::GetResourceLoaderState()
  109. {
  110. return WwiseResourceLoaderState;
  111. }
  112. void FWwiseResourceLoaderImpl::SetResourceLoaderState(EWwiseResourceLoaderState State)
  113. {
  114. WwiseResourceLoaderState = State;
  115. }
  116. bool FWwiseResourceLoaderImpl::IsEnabled()
  117. {
  118. return WwiseResourceLoaderState == EWwiseResourceLoaderState::Enabled;
  119. }
  120. void FWwiseResourceLoaderImpl::Disable()
  121. {
  122. SetResourceLoaderState(EWwiseResourceLoaderState::AlwaysDisabled);
  123. }
  124. void FWwiseResourceLoaderImpl::Enable()
  125. {
  126. SetResourceLoaderState(EWwiseResourceLoaderState::Enabled);
  127. }
  128. void FWwiseResourceLoaderImpl::SetLanguageAsync(FWwiseSetLanguagePromise&& Promise, const FWwiseLanguageCookedData& InLanguage, EWwiseReloadLanguage InReloadLanguage)
  129. {
  130. SCOPED_WWISERESOURCELOADER_EVENT(TEXT("SetLanguageAsync"));
  131. SCOPE_CYCLE_COUNTER(STAT_WwiseResourceLoaderTiming);
  132. auto OldLanguage = CurrentLanguage;
  133. auto NewLanguage = InLanguage;
  134. if (OldLanguage == NewLanguage)
  135. {
  136. return Promise.EmplaceValue();
  137. }
  138. UE_CLOG(!OldLanguage.GetLanguageName().IsValid(), LogWwiseResourceLoader, Log, TEXT("[SetLanguage] To %s"), *NewLanguage.GetLanguageName().ToString());
  139. UE_CLOG(OldLanguage.GetLanguageName().IsValid(), LogWwiseResourceLoader, Log, TEXT("[SetLanguage] from %s to %s"), *OldLanguage.GetLanguageName().ToString(), *NewLanguage.GetLanguageName().ToString());
  140. FCompletionFuture Future = MakeFulfilledWwisePromise<void>().GetFuture();
  141. if (InReloadLanguage == EWwiseReloadLanguage::Safe)
  142. {
  143. UE_LOG(LogWwiseResourceLoader, Verbose, TEXT("SetLanguage: Stopping all sounds"));
  144. auto* SoundEngine = IWwiseSoundEngineAPI::Get();
  145. if (UNLIKELY(!SoundEngine))
  146. {
  147. UE_LOG(LogWwiseResourceLoader, Error, TEXT("SetLanguage: SoundEngine not available to stop all sounds"));
  148. }
  149. else
  150. {
  151. SoundEngine->StopAll();
  152. // Wait two audio processing passes to make sure our StopAll was processed.
  153. FCompletionPromise EndPromise;
  154. auto EndFuture = EndPromise.GetFuture();
  155. Future.Next([Promise = MoveTemp(EndPromise)](int) mutable
  156. {
  157. if(auto* WwiseGlobalCallbacks = FWwiseGlobalCallbacks::Get())
  158. {
  159. FWwiseGlobalCallbacks::FCompletionPromise WaitPromise;
  160. auto WaitFuture = WaitPromise.GetFuture();
  161. WwiseGlobalCallbacks->EndCompletion(MoveTemp(WaitPromise), 2);
  162. WaitFuture.Next([Promise = MoveTemp(Promise)](int) mutable
  163. {
  164. Promise.EmplaceValue();
  165. });
  166. }
  167. else
  168. {
  169. Promise.EmplaceValue();
  170. }
  171. });
  172. Future = MoveTemp(EndFuture);
  173. }
  174. }
  175. CurrentLanguage = NewLanguage;
  176. if (InReloadLanguage == EWwiseReloadLanguage::Manual)
  177. {
  178. Future.Next([Promise = MoveTemp(Promise)](int) mutable
  179. {
  180. UE_LOG(LogWwiseResourceLoader, Verbose, TEXT("SetLanguage: Done (Manual)"));
  181. Promise.EmplaceValue();
  182. });
  183. return;
  184. }
  185. Future.Next([this, OldLanguage = MoveTemp(OldLanguage), NewLanguage = MoveTemp(NewLanguage), Promise = MoveTemp(Promise)](int) mutable
  186. {
  187. LoadedListExecutionQueue.Async([this, OldLanguage = MoveTemp(OldLanguage), NewLanguage = MoveTemp(NewLanguage), Promise = MoveTemp(Promise)]() mutable
  188. {
  189. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("SetLanguageAsync Unloading"));
  190. // Note: these are written as "Log" since it's more dangerous to do loading and unloading operations while the
  191. // asynchronous SetLanguage is executed. This allows for better debugging.
  192. UE_LOG(LogWwiseResourceLoader, Log, TEXT("SetLanguage: Switching languages. Unloading old language %s."),
  193. *OldLanguage.GetLanguageName().ToString());
  194. TArray<FWwiseLoadedSoundBankInfo*> AffectedSoundBanks;
  195. TArray<FWwiseLoadedAuxBusInfo*> AffectedAuxBusses;
  196. TArray<FWwiseLoadedShareSetInfo*> AffectedShareSets;
  197. TArray<FWwiseLoadedEventInfo*> AffectedEvents;
  198. // Unload all objects with a language equal to the old language
  199. FCompletionFutureArray UnloadFutureArray;
  200. for (auto& LoadedSoundBank : LoadedSoundBankList)
  201. {
  202. if (LoadedSoundBank.LanguageRef != OldLanguage)
  203. {
  204. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("SetLanguage: Skipping SoundBank %s with language %s"),
  205. *LoadedSoundBank.LocalizedSoundBankCookedData.DebugName.ToString(), *LoadedSoundBank.LanguageRef.GetLanguageName().ToString());
  206. continue;
  207. }
  208. auto* SoundBank = LoadedSoundBank.LocalizedSoundBankCookedData.SoundBankLanguageMap.Find(LoadedSoundBank.LanguageRef);
  209. if (LIKELY(SoundBank))
  210. {
  211. AffectedSoundBanks.Add(&LoadedSoundBank);
  212. FCompletionPromise UnloadPromise;
  213. UnloadFutureArray.Add(UnloadPromise.GetFuture());
  214. UnloadSoundBankResources(MoveTemp(UnloadPromise), LoadedSoundBank.LoadedData, *SoundBank);
  215. }
  216. else
  217. {
  218. UE_LOG(LogWwiseResourceLoader, Error, TEXT("SetLanguage: Could not find SoundBank %s with language %s"),
  219. *LoadedSoundBank.LocalizedSoundBankCookedData.DebugName.ToString(), *LoadedSoundBank.LanguageRef.GetLanguageName().ToString());
  220. }
  221. }
  222. for (auto& LoadedAuxBus : LoadedAuxBusList)
  223. {
  224. if (LoadedAuxBus.LanguageRef != OldLanguage)
  225. {
  226. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("SetLanguage: Skipping AuxBus %s with language %s"),
  227. *LoadedAuxBus.LocalizedAuxBusCookedData.DebugName.ToString(), *LoadedAuxBus.LanguageRef.GetLanguageName().ToString());
  228. continue;
  229. }
  230. auto* AuxBus = LoadedAuxBus.LocalizedAuxBusCookedData.AuxBusLanguageMap.Find(LoadedAuxBus.LanguageRef);
  231. if (LIKELY(AuxBus))
  232. {
  233. AffectedAuxBusses.Add(&LoadedAuxBus);
  234. FCompletionPromise UnloadPromise;
  235. UnloadFutureArray.Add(UnloadPromise.GetFuture());
  236. UnloadAuxBusResources(MoveTemp(UnloadPromise), LoadedAuxBus.LoadedData, *AuxBus);
  237. }
  238. else
  239. {
  240. UE_LOG(LogWwiseResourceLoader, Error, TEXT("SetLanguage: Could not find AuxBus %s with language %s"),
  241. *LoadedAuxBus.LocalizedAuxBusCookedData.DebugName.ToString(), *LoadedAuxBus.LanguageRef.GetLanguageName().ToString());
  242. }
  243. }
  244. for (auto& LoadedShareSet : LoadedShareSetList)
  245. {
  246. if (LoadedShareSet.LanguageRef != OldLanguage)
  247. {
  248. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("SetLanguage: Skipping ShareSet %s with language %s"),
  249. *LoadedShareSet.LocalizedShareSetCookedData.DebugName.ToString(), *LoadedShareSet.LanguageRef.GetLanguageName().ToString());
  250. continue;
  251. }
  252. auto* ShareSet = LoadedShareSet.LocalizedShareSetCookedData.ShareSetLanguageMap.Find(LoadedShareSet.LanguageRef);
  253. if (LIKELY(ShareSet))
  254. {
  255. AffectedShareSets.Add(&LoadedShareSet);
  256. FCompletionPromise UnloadPromise;
  257. UnloadFutureArray.Add(UnloadPromise.GetFuture());
  258. UnloadShareSetResources(MoveTemp(UnloadPromise), LoadedShareSet.LoadedData, *ShareSet);
  259. }
  260. else
  261. {
  262. UE_LOG(LogWwiseResourceLoader, Error, TEXT("SetLanguage: Could not find ShareSet %s with language %s"),
  263. *LoadedShareSet.LocalizedShareSetCookedData.DebugName.ToString(), *LoadedShareSet.LanguageRef.GetLanguageName().ToString());
  264. }
  265. }
  266. for (auto& LoadedEvent : LoadedEventList)
  267. {
  268. if (LoadedEvent.LanguageRef != OldLanguage)
  269. {
  270. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("SetLanguage: Skipping Event %s with language %s"),
  271. *LoadedEvent.LocalizedEventCookedData.DebugName.ToString(), *LoadedEvent.LanguageRef.GetLanguageName().ToString());
  272. continue;
  273. }
  274. auto* Event = LoadedEvent.LocalizedEventCookedData.EventLanguageMap.Find(LoadedEvent.LanguageRef);
  275. if (LIKELY(Event))
  276. {
  277. AffectedEvents.Add(&LoadedEvent);
  278. FCompletionPromise UnloadPromise;
  279. UnloadFutureArray.Add(UnloadPromise.GetFuture());
  280. UnloadEventResources(MoveTemp(UnloadPromise), LoadedEvent.LoadedData, *Event);
  281. }
  282. else
  283. {
  284. UE_LOG(LogWwiseResourceLoader, Error, TEXT("SetLanguage: Could not find Event %s with language %s"),
  285. *LoadedEvent.LocalizedEventCookedData.DebugName.ToString(), *LoadedEvent.LanguageRef.GetLanguageName().ToString());
  286. }
  287. }
  288. WaitForFutures(MoveTemp(UnloadFutureArray), [this,
  289. OldLanguage = MoveTemp(OldLanguage),
  290. NewLanguage = MoveTemp(NewLanguage),
  291. Promise = MoveTemp(Promise),
  292. AffectedAuxBusses = MoveTemp(AffectedAuxBusses),
  293. AffectedEvents = MoveTemp(AffectedEvents),
  294. AffectedShareSets = MoveTemp(AffectedShareSets),
  295. AffectedSoundBanks = MoveTemp(AffectedSoundBanks)]() mutable
  296. {
  297. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("SetLanguageAsync Loading"));
  298. UE_LOG(LogWwiseResourceLoader, Log, TEXT("SetLanguage: Loading new language %s."),
  299. *NewLanguage.GetLanguageName().ToString());
  300. FCompletionFutureArray LoadFutureArray;
  301. // Note: The results are ignored. Reloading Wwise objects can individually fail for any given reasons, and it's Out Of Scope
  302. // for the end product to know SetLanguage wasn't totally successful, since there's no real recourse at that point.
  303. for (auto* LoadedSoundBank : AffectedSoundBanks)
  304. {
  305. LoadedSoundBank->LanguageRef = NewLanguage;
  306. auto* SoundBank = LoadedSoundBank->LocalizedSoundBankCookedData.SoundBankLanguageMap.Find(LoadedSoundBank->LanguageRef);
  307. if (LIKELY(SoundBank))
  308. {
  309. FCompletionPromise LoadPromise;
  310. LoadFutureArray.Add(LoadPromise.GetFuture());
  311. FWwiseResourceLoadPromise ResourceLoadPromise;
  312. ResourceLoadPromise.GetFuture().Next([LoadPromise = MoveTemp(LoadPromise)](int) mutable
  313. {
  314. LoadPromise.EmplaceValue();
  315. });
  316. LoadSoundBankResources(MoveTemp(ResourceLoadPromise), LoadedSoundBank->LoadedData, *SoundBank);
  317. }
  318. else
  319. {
  320. UE_LOG(LogWwiseResourceLoader, Error, TEXT("SetLanguage: Could not find SoundBank %s with language %s"),
  321. *LoadedSoundBank->LocalizedSoundBankCookedData.DebugName.ToString(), *LoadedSoundBank->LanguageRef.GetLanguageName().ToString());
  322. }
  323. }
  324. for (auto* LoadedAuxBus : AffectedAuxBusses)
  325. {
  326. LoadedAuxBus->LanguageRef = NewLanguage;
  327. auto* AuxBus = LoadedAuxBus->LocalizedAuxBusCookedData.AuxBusLanguageMap.Find(LoadedAuxBus->LanguageRef);
  328. if (LIKELY(AuxBus))
  329. {
  330. FCompletionPromise LoadPromise;
  331. LoadFutureArray.Add(LoadPromise.GetFuture());
  332. FWwiseResourceLoadPromise ResourceLoadPromise;
  333. ResourceLoadPromise.GetFuture().Next([LoadPromise = MoveTemp(LoadPromise)](int) mutable
  334. {
  335. LoadPromise.EmplaceValue();
  336. });
  337. LoadAuxBusResources(MoveTemp(ResourceLoadPromise), LoadedAuxBus->LoadedData, *AuxBus);
  338. }
  339. else
  340. {
  341. UE_LOG(LogWwiseResourceLoader, Error, TEXT("SetLanguage: Could not find AuxBus %s with language %s"),
  342. *LoadedAuxBus->LocalizedAuxBusCookedData.DebugName.ToString(), *LoadedAuxBus->LanguageRef.GetLanguageName().ToString());
  343. }
  344. }
  345. for (auto* LoadedShareSet : AffectedShareSets)
  346. {
  347. LoadedShareSet->LanguageRef = NewLanguage;
  348. auto* ShareSet = LoadedShareSet->LocalizedShareSetCookedData.ShareSetLanguageMap.Find(LoadedShareSet->LanguageRef);
  349. if (LIKELY(ShareSet))
  350. {
  351. FCompletionPromise LoadPromise;
  352. LoadFutureArray.Add(LoadPromise.GetFuture());
  353. FWwiseResourceLoadPromise ResourceLoadPromise;
  354. ResourceLoadPromise.GetFuture().Next([LoadPromise = MoveTemp(LoadPromise)](int) mutable
  355. {
  356. LoadPromise.EmplaceValue();
  357. });
  358. LoadShareSetResources(MoveTemp(ResourceLoadPromise), LoadedShareSet->LoadedData, *ShareSet);
  359. }
  360. else
  361. {
  362. UE_LOG(LogWwiseResourceLoader, Error, TEXT("SetLanguage: Could not find ShareSet %s with language %s"),
  363. *LoadedShareSet->LocalizedShareSetCookedData.DebugName.ToString(), *LoadedShareSet->LanguageRef.GetLanguageName().ToString());
  364. }
  365. }
  366. for (auto* LoadedEvent : AffectedEvents)
  367. {
  368. LoadedEvent->LanguageRef = NewLanguage;
  369. auto* Event = LoadedEvent->LocalizedEventCookedData.EventLanguageMap.Find(LoadedEvent->LanguageRef);
  370. if (LIKELY(Event))
  371. {
  372. FCompletionPromise LoadPromise;
  373. LoadFutureArray.Add(LoadPromise.GetFuture());
  374. FWwiseResourceLoadPromise ResourceLoadPromise;
  375. ResourceLoadPromise.GetFuture().Next([LoadPromise = MoveTemp(LoadPromise)](int) mutable
  376. {
  377. LoadPromise.EmplaceValue();
  378. });
  379. LoadEventResources(MoveTemp(ResourceLoadPromise), LoadedEvent->LoadedData, *Event);
  380. }
  381. else
  382. {
  383. UE_LOG(LogWwiseResourceLoader, Error, TEXT("SetLanguage: Could not find Event %s with language %s"),
  384. *LoadedEvent->LocalizedEventCookedData.DebugName.ToString(), *LoadedEvent->LanguageRef.GetLanguageName().ToString());
  385. }
  386. }
  387. WaitForFutures(MoveTemp(LoadFutureArray), [
  388. OldLanguage = MoveTemp(OldLanguage),
  389. NewLanguage = MoveTemp(NewLanguage),
  390. Promise = MoveTemp(Promise)]() mutable
  391. {
  392. UE_LOG(LogWwiseResourceLoader, Log, TEXT("SetLanguage: Done switching assets from language %s to language %s."),
  393. *OldLanguage.GetLanguageName().ToString(), *NewLanguage.GetLanguageName().ToString());
  394. Promise.EmplaceValue();
  395. });
  396. });
  397. });
  398. });
  399. }
  400. void FWwiseResourceLoaderImpl::SetPlatform(const FWwiseSharedPlatformId& InPlatform)
  401. {
  402. UE_LOG(LogWwiseResourceLoader, Log, TEXT("SetPlatform: Updating platform from %s (%s) to %s (%s)."),
  403. *CurrentPlatform.GetPlatformName().ToString(), *CurrentPlatform.GetPlatformGuid().ToString(),
  404. *InPlatform.GetPlatformName().ToString(), *InPlatform.GetPlatformGuid().ToString());
  405. CurrentPlatform = InPlatform;
  406. }
  407. FWwiseLoadedAuxBus FWwiseResourceLoaderImpl::CreateAuxBusNode(
  408. const FWwiseLocalizedAuxBusCookedData& InAuxBusCookedData, const FWwiseLanguageCookedData* InLanguageOverride)
  409. {
  410. const auto* LanguageKey = GetLanguageMapKey(InAuxBusCookedData.AuxBusLanguageMap, InLanguageOverride, InAuxBusCookedData.DebugName);
  411. if (UNLIKELY(!LanguageKey))
  412. {
  413. UE_LOG(LogWwiseResourceLoader, Error, TEXT("CreateAuxBusNode: Could not find language for Aux Bus %s"), *InAuxBusCookedData.DebugName.ToString());
  414. return nullptr;
  415. }
  416. return new FWwiseLoadedAuxBusListNode(FWwiseLoadedAuxBusInfo(InAuxBusCookedData, *LanguageKey));
  417. }
  418. void FWwiseResourceLoaderImpl::LoadAuxBusAsync(FWwiseLoadedAuxBusPromise&& Promise, FWwiseLoadedAuxBus&& InAuxBusListNode)
  419. {
  420. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadAuxBusAsync"));
  421. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  422. auto& LoadedAuxBus = InAuxBusListNode->GetValue();
  423. LogLoad(LoadedAuxBus);
  424. const FWwiseAuxBusCookedData* AuxBus = LoadedAuxBus.LocalizedAuxBusCookedData.AuxBusLanguageMap.Find(LoadedAuxBus.LanguageRef);
  425. if (UNLIKELY(!AuxBus))
  426. {
  427. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadAuxBusAsync: Could not find AuxBus %s (%" PRIu32 ") in language %s (%" PRIu32 ")"),
  428. *LoadedAuxBus.LocalizedAuxBusCookedData.DebugName.ToString(), LoadedAuxBus.LocalizedAuxBusCookedData.AuxBusId, *LoadedAuxBus.LanguageRef.LanguageName.ToString(), LoadedAuxBus.LanguageRef.LanguageId);
  429. delete InAuxBusListNode;
  430. Timing.Stop();
  431. Promise.EmplaceValue(nullptr);
  432. return;
  433. }
  434. FWwiseResourceLoadPromise ResourceLoadPromise;
  435. auto Future = ResourceLoadPromise.GetFuture();
  436. LoadAuxBusResources(MoveTemp(ResourceLoadPromise), LoadedAuxBus.LoadedData, *AuxBus);
  437. Future.Next([this, &LoadedAuxBus, AuxBus, InAuxBusListNode = MoveTemp(InAuxBusListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](bool bResult) mutable
  438. {
  439. if (UNLIKELY(!bResult))
  440. {
  441. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadAuxBusAsync: Could not load AuxBus %s (%" PRIu32 ") in language %s (%" PRIu32 ")"),
  442. *LoadedAuxBus.LocalizedAuxBusCookedData.DebugName.ToString(), LoadedAuxBus.LocalizedAuxBusCookedData.AuxBusId, *LoadedAuxBus.LanguageRef.LanguageName.ToString(), LoadedAuxBus.LanguageRef.LanguageId);
  443. delete InAuxBusListNode;
  444. Timing.Stop();
  445. Promise.EmplaceValue(nullptr);
  446. return;
  447. }
  448. AttachAuxBusNode(InAuxBusListNode)
  449. .Next([InAuxBusListNode = MoveTemp(InAuxBusListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  450. {
  451. Timing.Stop();
  452. Promise.EmplaceValue(InAuxBusListNode);
  453. });
  454. });
  455. }
  456. void FWwiseResourceLoaderImpl::UnloadAuxBusAsync(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedAuxBus&& InAuxBusListNode)
  457. {
  458. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadAuxBusAsync"));
  459. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  460. auto& LoadedAuxBus = InAuxBusListNode->GetValue();
  461. LogUnload(LoadedAuxBus);
  462. const FWwiseAuxBusCookedData* AuxBus = LoadedAuxBus.LocalizedAuxBusCookedData.AuxBusLanguageMap.Find(LoadedAuxBus.LanguageRef);
  463. if (UNLIKELY(!AuxBus))
  464. {
  465. UE_LOG(LogWwiseResourceLoader, Error, TEXT("UnloadAuxBusAsync: Could not find AuxBus %s (%" PRIu32 ") in language %s (%" PRIu32 "). Leaking!"),
  466. *LoadedAuxBus.LocalizedAuxBusCookedData.DebugName.ToString(), LoadedAuxBus.LocalizedAuxBusCookedData.AuxBusId, *LoadedAuxBus.LanguageRef.LanguageName.ToString(), LoadedAuxBus.LanguageRef.LanguageId);
  467. Timing.Stop();
  468. Promise.EmplaceValue();
  469. return;
  470. }
  471. DetachAuxBusNode(InAuxBusListNode)
  472. .Next([this, &LoadedAuxBus, AuxBus, InAuxBusListNode = MoveTemp(InAuxBusListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  473. {
  474. FWwiseResourceUnloadPromise ResourceUnloadPromise;
  475. auto Future = ResourceUnloadPromise.GetFuture();
  476. UnloadAuxBusResources(MoveTemp(ResourceUnloadPromise), LoadedAuxBus.LoadedData, *AuxBus);
  477. Future.Next([this, &LoadedAuxBus, AuxBus, InAuxBusListNode = MoveTemp(InAuxBusListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  478. {
  479. delete InAuxBusListNode;
  480. Timing.Stop();
  481. Promise.EmplaceValue();
  482. });
  483. });
  484. }
  485. FWwiseLoadedEvent FWwiseResourceLoaderImpl::CreateEventNode(
  486. const FWwiseLocalizedEventCookedData& InEventCookedData, const FWwiseLanguageCookedData* InLanguageOverride)
  487. {
  488. const auto* LanguageKey = GetLanguageMapKey(InEventCookedData.EventLanguageMap, InLanguageOverride, InEventCookedData.DebugName);
  489. if (UNLIKELY(!LanguageKey))
  490. {
  491. UE_LOG(LogWwiseResourceLoader, Error, TEXT("CreateEventNode: Could not find language for Event %s"), *InEventCookedData.DebugName.ToString());
  492. return nullptr;
  493. }
  494. return new FWwiseLoadedEventListNode(FWwiseLoadedEventInfo(InEventCookedData, *LanguageKey));
  495. }
  496. void FWwiseResourceLoaderImpl::LoadEventAsync(FWwiseLoadedEventPromise&& Promise, FWwiseLoadedEvent&& InEventListNode)
  497. {
  498. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadEventAsync"));
  499. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  500. auto& LoadedEvent = InEventListNode->GetValue();
  501. LogLoad(LoadedEvent);
  502. const FWwiseEventCookedData* Event = LoadedEvent.LocalizedEventCookedData.EventLanguageMap.Find(LoadedEvent.LanguageRef);
  503. if (UNLIKELY(!Event))
  504. {
  505. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadEventAsync: Could not find Event %s (%" PRIu32 ") in language %s (%" PRIu32 ")"),
  506. *LoadedEvent.LocalizedEventCookedData.DebugName.ToString(), LoadedEvent.LocalizedEventCookedData.EventId, *LoadedEvent.LanguageRef.LanguageName.ToString(), LoadedEvent.LanguageRef.LanguageId);
  507. delete InEventListNode;
  508. Timing.Stop();
  509. Promise.EmplaceValue(nullptr);
  510. return;
  511. }
  512. FWwiseResourceLoadPromise ResourceLoadPromise;
  513. auto Future = ResourceLoadPromise.GetFuture();
  514. LoadEventResources(MoveTemp(ResourceLoadPromise), LoadedEvent.LoadedData, *Event);
  515. Future.Next([this, &LoadedEvent, Event, InEventListNode = MoveTemp(InEventListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](bool bResult) mutable
  516. {
  517. if (UNLIKELY(!bResult))
  518. {
  519. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadEventAsync: Could not load Event %s (%" PRIu32 ") in language %s (%" PRIu32 ")"),
  520. *LoadedEvent.LocalizedEventCookedData.DebugName.ToString(), LoadedEvent.LocalizedEventCookedData.EventId, *LoadedEvent.LanguageRef.LanguageName.ToString(), LoadedEvent.LanguageRef.LanguageId);
  521. delete InEventListNode;
  522. Timing.Stop();
  523. Promise.EmplaceValue(nullptr);
  524. return;
  525. }
  526. AttachEventNode(InEventListNode)
  527. .Next([this, InEventListNode = MoveTemp(InEventListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  528. {
  529. Timing.Stop();
  530. Promise.EmplaceValue(InEventListNode);
  531. });
  532. });
  533. }
  534. void FWwiseResourceLoaderImpl::UnloadEventAsync(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedEvent&& InEventListNode)
  535. {
  536. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadEventAsync"));
  537. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  538. auto& LoadedEvent = InEventListNode->GetValue();
  539. LogUnload(LoadedEvent);
  540. const FWwiseEventCookedData* Event = LoadedEvent.LocalizedEventCookedData.EventLanguageMap.Find(LoadedEvent.LanguageRef);
  541. if (UNLIKELY(!Event))
  542. {
  543. UE_LOG(LogWwiseResourceLoader, Error, TEXT("UnloadEventAsync: Could not find Event %s (%" PRIu32 ") in language %s (%" PRIu32 "). Leaking!"),
  544. *LoadedEvent.LocalizedEventCookedData.DebugName.ToString(), LoadedEvent.LocalizedEventCookedData.EventId, *LoadedEvent.LanguageRef.LanguageName.ToString(), LoadedEvent.LanguageRef.LanguageId);
  545. Timing.Stop();
  546. Promise.EmplaceValue();
  547. return;
  548. }
  549. DetachEventNode(InEventListNode)
  550. .Next([this, &LoadedEvent, Event, InEventListNode = MoveTemp(InEventListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  551. {
  552. FWwiseResourceUnloadPromise ResourceUnloadPromise;
  553. auto Future = ResourceUnloadPromise.GetFuture();
  554. UnloadEventResources(MoveTemp(ResourceUnloadPromise), LoadedEvent.LoadedData, *Event);
  555. Future.Next([this, &LoadedEvent, Event, InEventListNode = MoveTemp(InEventListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  556. {
  557. delete InEventListNode;
  558. Timing.Stop();
  559. Promise.EmplaceValue();
  560. });
  561. });
  562. }
  563. FWwiseLoadedExternalSource FWwiseResourceLoaderImpl::CreateExternalSourceNode(
  564. const FWwiseExternalSourceCookedData& InExternalSourceCookedData)
  565. {
  566. return new FWwiseLoadedExternalSourceListNode(FWwiseLoadedExternalSourceInfo(InExternalSourceCookedData));
  567. }
  568. void FWwiseResourceLoaderImpl::LoadExternalSourceAsync(FWwiseLoadedExternalSourcePromise&& Promise, FWwiseLoadedExternalSource&& InExternalSourceListNode)
  569. {
  570. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadExternalSourceAsync"));
  571. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  572. auto& LoadedExternalSource = InExternalSourceListNode->GetValue();
  573. LogLoad(LoadedExternalSource);
  574. const FWwiseExternalSourceCookedData* ExternalSource = &LoadedExternalSource.ExternalSourceCookedData;
  575. FWwiseResourceLoadPromise ResourceLoadPromise;
  576. auto Future = ResourceLoadPromise.GetFuture();
  577. LoadExternalSourceResources(MoveTemp(ResourceLoadPromise), LoadedExternalSource.LoadedData, *ExternalSource);
  578. Future.Next([this, &LoadedExternalSource, ExternalSource, InExternalSourceListNode = MoveTemp(InExternalSourceListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](bool bResult) mutable
  579. {
  580. if (UNLIKELY(!bResult))
  581. {
  582. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadExternalSourceAsync: Could not load ExternalSource %s (%" PRIu32 ")"),
  583. *LoadedExternalSource.ExternalSourceCookedData.DebugName.ToString(), LoadedExternalSource.ExternalSourceCookedData.Cookie);
  584. delete InExternalSourceListNode;
  585. Timing.Stop();
  586. Promise.EmplaceValue(nullptr);
  587. return;
  588. }
  589. AttachExternalSourceNode(InExternalSourceListNode)
  590. .Next([this, InExternalSourceListNode = MoveTemp(InExternalSourceListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  591. {
  592. Timing.Stop();
  593. Promise.EmplaceValue(InExternalSourceListNode);
  594. });
  595. });
  596. }
  597. void FWwiseResourceLoaderImpl::UnloadExternalSourceAsync(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedExternalSource&& InExternalSourceListNode)
  598. {
  599. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadExternalSourceAsync"));
  600. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  601. auto& LoadedExternalSource = InExternalSourceListNode->GetValue();
  602. LogUnload(LoadedExternalSource);
  603. const FWwiseExternalSourceCookedData* ExternalSource = &LoadedExternalSource.ExternalSourceCookedData;
  604. DetachExternalSourceNode(InExternalSourceListNode)
  605. .Next([this, &LoadedExternalSource, ExternalSource, InExternalSourceListNode = MoveTemp(InExternalSourceListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  606. {
  607. FWwiseResourceUnloadPromise ResourceUnloadPromise;
  608. auto Future = ResourceUnloadPromise.GetFuture();
  609. UnloadExternalSourceResources(MoveTemp(ResourceUnloadPromise), LoadedExternalSource.LoadedData, *ExternalSource);
  610. Future.Next([this, &LoadedExternalSource, ExternalSource, InExternalSourceListNode = MoveTemp(InExternalSourceListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  611. {
  612. delete InExternalSourceListNode;
  613. Timing.Stop();
  614. Promise.EmplaceValue();
  615. });
  616. });
  617. }
  618. FWwiseLoadedGroupValue FWwiseResourceLoaderImpl::CreateGroupValueNode(
  619. const FWwiseGroupValueCookedData& InGroupValueCookedData)
  620. {
  621. return new FWwiseLoadedGroupValueListNode(FWwiseLoadedGroupValueInfo(InGroupValueCookedData));
  622. }
  623. void FWwiseResourceLoaderImpl::LoadGroupValueAsync(FWwiseLoadedGroupValuePromise&& Promise, FWwiseLoadedGroupValue&& InGroupValueListNode)
  624. {
  625. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadGroupValueAsync"));
  626. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  627. auto& LoadedGroupValue = InGroupValueListNode->GetValue();
  628. LogLoad(LoadedGroupValue);
  629. const FWwiseGroupValueCookedData* GroupValue = &LoadedGroupValue.GroupValueCookedData;
  630. FWwiseResourceLoadPromise ResourceLoadPromise;
  631. auto Future = ResourceLoadPromise.GetFuture();
  632. LoadGroupValueResources(MoveTemp(ResourceLoadPromise), LoadedGroupValue.LoadedData, *GroupValue);
  633. Future.Next([this, &LoadedGroupValue, GroupValue, InGroupValueListNode = MoveTemp(InGroupValueListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](bool bResult) mutable
  634. {
  635. if (UNLIKELY(!bResult))
  636. {
  637. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadGroupValueAsync: Could not load GroupValue %s (%s %" PRIu32 ":%" PRIu32 ")"),
  638. *LoadedGroupValue.GroupValueCookedData.DebugName.ToString(), *LoadedGroupValue.GroupValueCookedData.GetTypeName(), LoadedGroupValue.GroupValueCookedData.GroupId, LoadedGroupValue.GroupValueCookedData.Id);
  639. delete InGroupValueListNode;
  640. Timing.Stop();
  641. Promise.EmplaceValue(nullptr);
  642. return;
  643. }
  644. AttachGroupValueNode(InGroupValueListNode)
  645. .Next([this, InGroupValueListNode = MoveTemp(InGroupValueListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  646. {
  647. Timing.Stop();
  648. Promise.EmplaceValue(InGroupValueListNode);
  649. });
  650. });
  651. }
  652. void FWwiseResourceLoaderImpl::UnloadGroupValueAsync(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedGroupValue&& InGroupValueListNode)
  653. {
  654. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadGroupValueAsync"));
  655. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  656. auto& LoadedGroupValue = InGroupValueListNode->GetValue();
  657. LogUnload(LoadedGroupValue);
  658. const FWwiseGroupValueCookedData* GroupValue = &LoadedGroupValue.GroupValueCookedData;
  659. DetachGroupValueNode(InGroupValueListNode)
  660. .Next([this, &LoadedGroupValue, GroupValue, InGroupValueListNode = MoveTemp(InGroupValueListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  661. {
  662. FWwiseResourceUnloadPromise ResourceUnloadPromise;
  663. auto Future = ResourceUnloadPromise.GetFuture();
  664. UnloadGroupValueResources(MoveTemp(ResourceUnloadPromise), LoadedGroupValue.LoadedData, *GroupValue);
  665. Future.Next([this, &LoadedGroupValue, GroupValue, InGroupValueListNode = MoveTemp(InGroupValueListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  666. {
  667. delete InGroupValueListNode;
  668. Timing.Stop();
  669. Promise.EmplaceValue();
  670. });
  671. });
  672. }
  673. FWwiseLoadedInitBank FWwiseResourceLoaderImpl::CreateInitBankNode(
  674. const FWwiseInitBankCookedData& InInitBankCookedData)
  675. {
  676. return new FWwiseLoadedInitBankListNode(FWwiseLoadedInitBankInfo(InInitBankCookedData));
  677. }
  678. void FWwiseResourceLoaderImpl::LoadInitBankAsync(FWwiseLoadedInitBankPromise&& Promise, FWwiseLoadedInitBank&& InInitBankListNode)
  679. {
  680. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadInitBankAsync"));
  681. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  682. auto& LoadedInitBank = InInitBankListNode->GetValue();
  683. LogLoad(LoadedInitBank);
  684. const FWwiseInitBankCookedData* InitBank = &LoadedInitBank.InitBankCookedData;
  685. FWwiseResourceLoadPromise ResourceLoadPromise;
  686. auto Future = ResourceLoadPromise.GetFuture();
  687. LoadInitBankResources(MoveTemp(ResourceLoadPromise), LoadedInitBank.LoadedData, *InitBank);
  688. Future.Next([this, &LoadedInitBank, InitBank, InInitBankListNode = MoveTemp(InInitBankListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](bool bResult) mutable
  689. {
  690. if (UNLIKELY(!bResult))
  691. {
  692. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadInitBankAsync: Could not load InitBank %s (%" PRIu32 ")"),
  693. *LoadedInitBank.InitBankCookedData.DebugName.ToString(), LoadedInitBank.InitBankCookedData.SoundBankId);
  694. delete InInitBankListNode;
  695. Timing.Stop();
  696. Promise.EmplaceValue(nullptr);
  697. return;
  698. }
  699. AttachInitBankNode(InInitBankListNode)
  700. .Next([this, InInitBankListNode = MoveTemp(InInitBankListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  701. {
  702. Timing.Stop();
  703. Promise.EmplaceValue(InInitBankListNode);
  704. });
  705. });
  706. }
  707. void FWwiseResourceLoaderImpl::UnloadInitBankAsync(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedInitBank&& InInitBankListNode)
  708. {
  709. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadInitBankAsync"));
  710. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  711. auto& LoadedInitBank = InInitBankListNode->GetValue();
  712. LogUnload(LoadedInitBank);
  713. const FWwiseInitBankCookedData* InitBank = &LoadedInitBank.InitBankCookedData;
  714. DetachInitBankNode(InInitBankListNode)
  715. .Next([this, &LoadedInitBank, InitBank, InInitBankListNode = MoveTemp(InInitBankListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  716. {
  717. FWwiseResourceUnloadPromise ResourceUnloadPromise;
  718. auto Future = ResourceUnloadPromise.GetFuture();
  719. UnloadInitBankResources(MoveTemp(ResourceUnloadPromise), LoadedInitBank.LoadedData, *InitBank);
  720. Future.Next([this, &LoadedInitBank, InitBank, InInitBankListNode = MoveTemp(InInitBankListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  721. {
  722. delete InInitBankListNode;
  723. Timing.Stop();
  724. Promise.EmplaceValue();
  725. });
  726. });
  727. }
  728. FWwiseLoadedMedia FWwiseResourceLoaderImpl::CreateMediaNode(const FWwiseMediaCookedData& InMediaCookedData)
  729. {
  730. return new FWwiseLoadedMediaListNode(FWwiseLoadedMediaInfo(InMediaCookedData));
  731. }
  732. void FWwiseResourceLoaderImpl::LoadMediaAsync(FWwiseLoadedMediaPromise&& Promise, FWwiseLoadedMedia&& InMediaListNode)
  733. {
  734. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadMediaAsync"));
  735. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  736. auto& LoadedMedia = InMediaListNode->GetValue();
  737. LogLoad(LoadedMedia);
  738. const FWwiseMediaCookedData* Media = &LoadedMedia.MediaCookedData;
  739. FWwiseResourceLoadPromise ResourceLoadPromise;
  740. auto Future = ResourceLoadPromise.GetFuture();
  741. LoadMediaResources(MoveTemp(ResourceLoadPromise), LoadedMedia.LoadedData, *Media);
  742. Future.Next([this, &LoadedMedia, Media, InMediaListNode = MoveTemp(InMediaListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](bool bResult) mutable
  743. {
  744. if (UNLIKELY(!bResult))
  745. {
  746. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadMediaAsync: Could not load Media %s (%" PRIu32 ")"),
  747. *LoadedMedia.MediaCookedData.DebugName.ToString(), LoadedMedia.MediaCookedData.MediaId);
  748. delete InMediaListNode;
  749. Timing.Stop();
  750. Promise.EmplaceValue(nullptr);
  751. return;
  752. }
  753. AttachMediaNode(InMediaListNode)
  754. .Next([this, InMediaListNode = MoveTemp(InMediaListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  755. {
  756. Timing.Stop();
  757. Promise.EmplaceValue(InMediaListNode);
  758. });
  759. });
  760. }
  761. void FWwiseResourceLoaderImpl::UnloadMediaAsync(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedMedia&& InMediaListNode)
  762. {
  763. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadMediaAsync"));
  764. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  765. auto& LoadedMedia = InMediaListNode->GetValue();
  766. LogUnload(LoadedMedia);
  767. const FWwiseMediaCookedData* Media = &LoadedMedia.MediaCookedData;
  768. DetachMediaNode(InMediaListNode)
  769. .Next([this, &LoadedMedia, Media, InMediaListNode = MoveTemp(InMediaListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  770. {
  771. FWwiseResourceUnloadPromise ResourceUnloadPromise;
  772. auto Future = ResourceUnloadPromise.GetFuture();
  773. UnloadMediaResources(MoveTemp(ResourceUnloadPromise), LoadedMedia.LoadedData, *Media);
  774. Future.Next([this, &LoadedMedia, Media, InMediaListNode = MoveTemp(InMediaListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  775. {
  776. delete InMediaListNode;
  777. Timing.Stop();
  778. Promise.EmplaceValue();
  779. });
  780. });
  781. }
  782. FWwiseLoadedShareSet FWwiseResourceLoaderImpl::CreateShareSetNode(
  783. const FWwiseLocalizedShareSetCookedData& InShareSetCookedData, const FWwiseLanguageCookedData* InLanguageOverride)
  784. {
  785. const auto* LanguageKey = GetLanguageMapKey(InShareSetCookedData.ShareSetLanguageMap, InLanguageOverride, InShareSetCookedData.DebugName);
  786. if (UNLIKELY(!LanguageKey))
  787. {
  788. UE_LOG(LogWwiseResourceLoader, Error, TEXT("CreateShareSetNode: Could not find language for ShareSet %s"), *InShareSetCookedData.DebugName.ToString());
  789. return nullptr;
  790. }
  791. return new FWwiseLoadedShareSetListNode(FWwiseLoadedShareSetInfo(InShareSetCookedData, *LanguageKey));
  792. }
  793. void FWwiseResourceLoaderImpl::LoadShareSetAsync(FWwiseLoadedShareSetPromise&& Promise, FWwiseLoadedShareSet&& InShareSetListNode)
  794. {
  795. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadShareSetAsync"));
  796. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  797. auto& LoadedShareSet = InShareSetListNode->GetValue();
  798. LogLoad(LoadedShareSet);
  799. const FWwiseShareSetCookedData* ShareSet = LoadedShareSet.LocalizedShareSetCookedData.ShareSetLanguageMap.Find(LoadedShareSet.LanguageRef);
  800. if (UNLIKELY(!ShareSet))
  801. {
  802. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadShareSetAsync: Could not find ShareSet %s (%" PRIu32 ") in language %s (%" PRIu32 ")"),
  803. *LoadedShareSet.LocalizedShareSetCookedData.DebugName.ToString(), LoadedShareSet.LocalizedShareSetCookedData.ShareSetId, *LoadedShareSet.LanguageRef.LanguageName.ToString(), LoadedShareSet.LanguageRef.LanguageId);
  804. delete InShareSetListNode;
  805. Timing.Stop();
  806. Promise.EmplaceValue(nullptr);
  807. return;
  808. }
  809. FWwiseResourceLoadPromise ResourceLoadPromise;
  810. auto Future = ResourceLoadPromise.GetFuture();
  811. LoadShareSetResources(MoveTemp(ResourceLoadPromise), LoadedShareSet.LoadedData, *ShareSet);
  812. Future.Next([this, &LoadedShareSet, ShareSet, InShareSetListNode = MoveTemp(InShareSetListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](bool bResult) mutable
  813. {
  814. if (UNLIKELY(!bResult))
  815. {
  816. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadShareSetAsync: Could not load ShareSet %s (%" PRIu32 ") in language %s (%" PRIu32 ")"),
  817. *LoadedShareSet.LocalizedShareSetCookedData.DebugName.ToString(), LoadedShareSet.LocalizedShareSetCookedData.ShareSetId, *LoadedShareSet.LanguageRef.LanguageName.ToString(), LoadedShareSet.LanguageRef.LanguageId);
  818. delete InShareSetListNode;
  819. Timing.Stop();
  820. Promise.EmplaceValue(nullptr);
  821. return;
  822. }
  823. AttachShareSetNode(InShareSetListNode)
  824. .Next([this, InShareSetListNode = MoveTemp(InShareSetListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  825. {
  826. Timing.Stop();
  827. Promise.EmplaceValue(InShareSetListNode);
  828. });
  829. });
  830. }
  831. void FWwiseResourceLoaderImpl::UnloadShareSetAsync(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedShareSet&& InShareSetListNode)
  832. {
  833. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadShareSetAsync"));
  834. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  835. auto& LoadedShareSet = InShareSetListNode->GetValue();
  836. LogUnload(LoadedShareSet);
  837. const FWwiseShareSetCookedData* ShareSet = LoadedShareSet.LocalizedShareSetCookedData.ShareSetLanguageMap.Find(LoadedShareSet.LanguageRef);
  838. if (UNLIKELY(!ShareSet))
  839. {
  840. UE_LOG(LogWwiseResourceLoader, Error, TEXT("UnloadShareSetAsync: Could not find ShareSet %s (%" PRIu32 ") in language %s (%" PRIu32 "). Leaking!"),
  841. *LoadedShareSet.LocalizedShareSetCookedData.DebugName.ToString(), LoadedShareSet.LocalizedShareSetCookedData.ShareSetId, *LoadedShareSet.LanguageRef.LanguageName.ToString(), LoadedShareSet.LanguageRef.LanguageId);
  842. Timing.Stop();
  843. Promise.EmplaceValue();
  844. return;
  845. }
  846. DetachShareSetNode(InShareSetListNode)
  847. .Next([this, &LoadedShareSet, ShareSet, InShareSetListNode = MoveTemp(InShareSetListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  848. {
  849. FWwiseResourceUnloadPromise ResourceUnloadPromise;
  850. auto Future = ResourceUnloadPromise.GetFuture();
  851. UnloadShareSetResources(MoveTemp(ResourceUnloadPromise), LoadedShareSet.LoadedData, *ShareSet);
  852. Future.Next([this, &LoadedShareSet, ShareSet, InShareSetListNode = MoveTemp(InShareSetListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  853. {
  854. delete InShareSetListNode;
  855. Timing.Stop();
  856. Promise.EmplaceValue();
  857. });
  858. });
  859. }
  860. FWwiseLoadedSoundBank FWwiseResourceLoaderImpl::CreateSoundBankNode(
  861. const FWwiseLocalizedSoundBankCookedData& InSoundBankCookedData, const FWwiseLanguageCookedData* InLanguageOverride)
  862. {
  863. const auto* LanguageKey = GetLanguageMapKey(InSoundBankCookedData.SoundBankLanguageMap, InLanguageOverride, InSoundBankCookedData.DebugName);
  864. if (UNLIKELY(!LanguageKey))
  865. {
  866. UE_LOG(LogWwiseResourceLoader, Error, TEXT("CreateSoundBankNode: Could not find language for SoundBank %s"), *InSoundBankCookedData.DebugName.ToString());
  867. return nullptr;
  868. }
  869. return new FWwiseLoadedSoundBankListNode(FWwiseLoadedSoundBankInfo(InSoundBankCookedData, *LanguageKey));
  870. }
  871. void FWwiseResourceLoaderImpl::LoadSoundBankAsync(FWwiseLoadedSoundBankPromise&& Promise, FWwiseLoadedSoundBank&& InSoundBankListNode)
  872. {
  873. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadSoundBankAsync"));
  874. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  875. auto& LoadedSoundBank = InSoundBankListNode->GetValue();
  876. LogLoad(LoadedSoundBank);
  877. const FWwiseSoundBankCookedData* SoundBank = LoadedSoundBank.LocalizedSoundBankCookedData.SoundBankLanguageMap.Find(LoadedSoundBank.LanguageRef);
  878. if (UNLIKELY(!SoundBank))
  879. {
  880. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadSoundBankAsync: Could not find SoundBank %s (%" PRIu32 ") in language %s (%" PRIu32 ")"),
  881. *LoadedSoundBank.LocalizedSoundBankCookedData.DebugName.ToString(), LoadedSoundBank.LocalizedSoundBankCookedData.SoundBankId, *LoadedSoundBank.LanguageRef.LanguageName.ToString(), LoadedSoundBank.LanguageRef.LanguageId);
  882. delete InSoundBankListNode;
  883. Timing.Stop();
  884. Promise.EmplaceValue(nullptr);
  885. return;
  886. }
  887. FWwiseResourceLoadPromise ResourceLoadPromise;
  888. auto Future = ResourceLoadPromise.GetFuture();
  889. LoadSoundBankResources(MoveTemp(ResourceLoadPromise), LoadedSoundBank.LoadedData, *SoundBank);
  890. Future.Next([this, &LoadedSoundBank, SoundBank, InSoundBankListNode = MoveTemp(InSoundBankListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](bool bResult) mutable
  891. {
  892. if (UNLIKELY(!bResult))
  893. {
  894. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadSoundBankAsync: Could not load SoundBank %s (%" PRIu32 ") in language %s (%" PRIu32 ")"),
  895. *LoadedSoundBank.LocalizedSoundBankCookedData.DebugName.ToString(), LoadedSoundBank.LocalizedSoundBankCookedData.SoundBankId, *LoadedSoundBank.LanguageRef.LanguageName.ToString(), LoadedSoundBank.LanguageRef.LanguageId);
  896. delete InSoundBankListNode;
  897. Timing.Stop();
  898. Promise.EmplaceValue(nullptr);
  899. return;
  900. }
  901. AttachSoundBankNode(InSoundBankListNode)
  902. .Next([this, InSoundBankListNode = MoveTemp(InSoundBankListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  903. {
  904. Timing.Stop();
  905. Promise.EmplaceValue(InSoundBankListNode);
  906. });
  907. });
  908. }
  909. void FWwiseResourceLoaderImpl::UnloadSoundBankAsync(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedSoundBank&& InSoundBankListNode)
  910. {
  911. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadSoundBankAsync"));
  912. FWwiseAsyncCycleCounter Timing(GET_STATID(STAT_WwiseResourceLoaderTiming));
  913. auto& LoadedSoundBank = InSoundBankListNode->GetValue();
  914. LogUnload(LoadedSoundBank);
  915. const FWwiseSoundBankCookedData* SoundBank = LoadedSoundBank.LocalizedSoundBankCookedData.SoundBankLanguageMap.Find(LoadedSoundBank.LanguageRef);
  916. if (UNLIKELY(!SoundBank))
  917. {
  918. UE_LOG(LogWwiseResourceLoader, Error, TEXT("UnloadSoundBankAsync: Could not find SoundBank %s (%" PRIu32 ") in language %s (%" PRIu32 "). Leaking!"),
  919. *LoadedSoundBank.LocalizedSoundBankCookedData.DebugName.ToString(), LoadedSoundBank.LocalizedSoundBankCookedData.SoundBankId, *LoadedSoundBank.LanguageRef.LanguageName.ToString(), LoadedSoundBank.LanguageRef.LanguageId);
  920. Timing.Stop();
  921. Promise.EmplaceValue();
  922. return;
  923. }
  924. DetachSoundBankNode(InSoundBankListNode)
  925. .Next([this, &LoadedSoundBank, SoundBank, InSoundBankListNode = MoveTemp(InSoundBankListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  926. {
  927. FWwiseResourceUnloadPromise ResourceUnloadPromise;
  928. auto Future = ResourceUnloadPromise.GetFuture();
  929. UnloadSoundBankResources(MoveTemp(ResourceUnloadPromise), LoadedSoundBank.LoadedData, *SoundBank);
  930. Future.Next([this, &LoadedSoundBank, SoundBank, InSoundBankListNode = MoveTemp(InSoundBankListNode), Promise = MoveTemp(Promise), Timing = MoveTemp(Timing)](int) mutable
  931. {
  932. delete InSoundBankListNode;
  933. Timing.Stop();
  934. Promise.EmplaceValue();
  935. });
  936. });
  937. }
  938. void FWwiseResourceLoaderImpl::LoadAuxBusResources(FWwiseResourceLoadPromise&& Promise, FWwiseLoadedAuxBusInfo::FLoadedData& LoadedData, const FWwiseAuxBusCookedData& InCookedData)
  939. {
  940. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadAuxBusResources"));
  941. LogLoadResources(InCookedData);
  942. auto& LoadedSoundBanks = LoadedData.LoadedSoundBanks;
  943. auto& LoadedMedia = LoadedData.LoadedMedia;
  944. if (UNLIKELY(LoadedData.IsLoaded()))
  945. {
  946. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadAuxBusResources: AuxBus %s (%" PRIu32 ") is already loaded."),
  947. *InCookedData.DebugName.ToString(), (uint32)InCookedData.AuxBusId);
  948. return Promise.EmplaceValue(false);
  949. }
  950. FCompletionFutureArray FutureArray;
  951. AddLoadMediaFutures(FutureArray, LoadedMedia, InCookedData.Media, TEXT("AuxBus"), InCookedData.DebugName, InCookedData.AuxBusId);
  952. AddLoadSoundBankFutures(FutureArray, LoadedSoundBanks, InCookedData.SoundBanks, TEXT("AuxBus"), InCookedData.DebugName, InCookedData.AuxBusId);
  953. WaitForFutures(MoveTemp(FutureArray), [this, Promise = MoveTemp(Promise), &LoadedData, &LoadedSoundBanks, &InCookedData]() mutable
  954. {
  955. if (UNLIKELY(LoadedSoundBanks.Num() != InCookedData.SoundBanks.Num()))
  956. {
  957. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadAuxBusResources: Could not load %d prerequisites for AuxBus %s (%" PRIu32 "). Unloading and failing."),
  958. InCookedData.SoundBanks.Num() - LoadedSoundBanks.Num(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.AuxBusId);
  959. FWwiseResourceUnloadPromise UnloadPromise;
  960. auto UnloadFuture = UnloadPromise.GetFuture();
  961. UnloadAuxBusResources(MoveTemp(UnloadPromise), LoadedData, InCookedData);
  962. UnloadFuture.Next([Promise = MoveTemp(Promise)](int) mutable
  963. {
  964. return Promise.EmplaceValue(false);
  965. });
  966. }
  967. else
  968. {
  969. return Promise.EmplaceValue(true);
  970. }
  971. });
  972. }
  973. void FWwiseResourceLoaderImpl::LoadEventResources(FWwiseResourceLoadPromise&& Promise, FWwiseLoadedEventInfo::FLoadedData& LoadedData, const FWwiseEventCookedData& InCookedData)
  974. {
  975. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadEventResources"));
  976. LogLoadResources(InCookedData);
  977. auto& LoadedSoundBanks = LoadedData.LoadedSoundBanks;
  978. auto& LoadedExternalSources = LoadedData.LoadedExternalSources;
  979. auto& LoadedMedia = LoadedData.LoadedMedia;
  980. if (UNLIKELY(LoadedData.IsLoaded()))
  981. {
  982. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadEventResources: Event %s (%" PRIu32 ") is already loaded."),
  983. *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  984. return Promise.EmplaceValue(false);
  985. }
  986. FWwiseResourceLoadPromise SwitchContainerPromise;
  987. auto SwitchContainerFuture = SwitchContainerPromise.GetFuture();
  988. if (InCookedData.RequiredGroupValueSet.Num() > 0 || InCookedData.SwitchContainerLeaves.Num() > 0)
  989. {
  990. LoadEventSwitchContainerResources(MoveTemp(SwitchContainerPromise), LoadedData, InCookedData);
  991. }
  992. else
  993. {
  994. SwitchContainerPromise.EmplaceValue(true);
  995. }
  996. FCompletionFutureArray FutureArray;
  997. AddLoadExternalSourceFutures(FutureArray, LoadedExternalSources, InCookedData.ExternalSources, TEXT("Event"), InCookedData.DebugName, InCookedData.EventId);
  998. AddLoadMediaFutures(FutureArray, LoadedMedia, InCookedData.Media, TEXT("Event"), InCookedData.DebugName, InCookedData.EventId);
  999. AddLoadSoundBankFutures(FutureArray, LoadedSoundBanks, InCookedData.SoundBanks, TEXT("Event"), InCookedData.DebugName, InCookedData.EventId);
  1000. SwitchContainerFuture.Next([this, FutureArray = MoveTemp(FutureArray), Promise = MoveTemp(Promise), &LoadedData, &LoadedSoundBanks, &InCookedData](bool bResult) mutable
  1001. {
  1002. WaitForFutures(MoveTemp(FutureArray), [this, Promise = MoveTemp(Promise), &LoadedData, &LoadedSoundBanks, &InCookedData, bSwitchContainerResult = bResult]() mutable
  1003. {
  1004. if (UNLIKELY(LoadedSoundBanks.Num() != InCookedData.SoundBanks.Num()))
  1005. {
  1006. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadEventResources: Could not load %d prerequisites for Event %s (%" PRIu32 "). Unloading and failing."),
  1007. InCookedData.SoundBanks.Num() - LoadedSoundBanks.Num(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1008. FWwiseResourceUnloadPromise UnloadPromise;
  1009. auto UnloadFuture = UnloadPromise.GetFuture();
  1010. UnloadEventResources(MoveTemp(UnloadPromise), LoadedData, InCookedData);
  1011. UnloadFuture.Next([Promise = MoveTemp(Promise)](int) mutable
  1012. {
  1013. return Promise.EmplaceValue(false);
  1014. });
  1015. }
  1016. else
  1017. {
  1018. return Promise.EmplaceValue(true);
  1019. }
  1020. });
  1021. });
  1022. }
  1023. void FWwiseResourceLoaderImpl::LoadEventSwitchContainerResources(FWwiseResourceLoadPromise&& Promise, FWwiseLoadedEventInfo::FLoadedData& LoadedData, const FWwiseEventCookedData& InCookedData)
  1024. {
  1025. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadEventSwitchContainerResources"));
  1026. // Load required GroupValues
  1027. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Loading %d GroupValues for Event %s (%" PRIu32 ")"),
  1028. (int)InCookedData.RequiredGroupValueSet.Num(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1029. FWwiseLoadedGroupValueList& LoadedRequiredGroupValues = LoadedData.LoadedRequiredGroupValues;
  1030. bool& bLoadedSwitchContainerLeaves = LoadedData.bLoadedSwitchContainerLeaves;
  1031. FCompletionFutureArray FutureArray;
  1032. for (const auto& GroupValue : InCookedData.RequiredGroupValueSet)
  1033. {
  1034. FCompletionPromise GroupValuePromise;
  1035. FutureArray.Add(GroupValuePromise.GetFuture());
  1036. SwitchContainerExecutionQueue.Async([this, &LoadedRequiredGroupValues, &InCookedData, &GroupValue, GroupValuePromise = MoveTemp(GroupValuePromise)]() mutable
  1037. {
  1038. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Loading GroupValue %s for Event %s (%" PRIu32 ")"),
  1039. *GroupValue.GetDebugString(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1040. auto* LoadedNode = new FWwiseLoadedGroupValueListNode(FWwiseLoadedGroupValueInfo(GroupValue));
  1041. auto& GroupValueLoadedData = LoadedNode->GetValue().LoadedData;
  1042. FWwiseResourceLoadPromise GroupValueResourcePromise;
  1043. auto GroupValueResourceFuture = GroupValueResourcePromise.GetFuture();
  1044. LoadGroupValueResources(MoveTemp(GroupValueResourcePromise), GroupValueLoadedData, GroupValue);
  1045. GroupValueResourceFuture.Next([this, &LoadedRequiredGroupValues, &InCookedData, &GroupValue, GroupValuePromise = MoveTemp(GroupValuePromise), LoadedNode](bool bResult) mutable
  1046. {
  1047. const auto& GroupValueLoadedData = LoadedNode->GetValue().LoadedData;
  1048. if (UNLIKELY(!bResult || !GroupValueLoadedData.IsLoaded()))
  1049. {
  1050. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Could not load required GroupValue %s for Event %s (%" PRIu32 ")"),
  1051. *GroupValue.DebugName.ToString(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1052. delete LoadedNode;
  1053. GroupValuePromise.EmplaceValue();
  1054. }
  1055. else
  1056. {
  1057. SwitchContainerExecutionQueue.Async([this, &LoadedRequiredGroupValues, LoadedNode, GroupValuePromise = MoveTemp(GroupValuePromise)]() mutable
  1058. {
  1059. LoadedRequiredGroupValues.AddTail(LoadedNode);
  1060. GroupValuePromise.EmplaceValue();
  1061. });
  1062. }
  1063. });
  1064. });
  1065. }
  1066. // Load Switch Container Leaves
  1067. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Loading %d Leaves for Event %s (%" PRIu32 ")"),
  1068. (int)InCookedData.SwitchContainerLeaves.Num(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1069. for (const auto& SwitchContainerLeaf : InCookedData.SwitchContainerLeaves)
  1070. {
  1071. check(SwitchContainerLeaf.GroupValueSet.Num() > 0);
  1072. FWwiseSwitchContainerLeafGroupValueUsageCount* UsageCount = new FWwiseSwitchContainerLeafGroupValueUsageCount(SwitchContainerLeaf);
  1073. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Created %s Usage Count @ %p for Event %s (%" PRIu32 ")"),
  1074. *SwitchContainerLeaf.GetDebugString(), &UsageCount->LoadedData,
  1075. *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1076. for (const auto& GroupValue : SwitchContainerLeaf.GroupValueSet)
  1077. {
  1078. FCompletionPromise SwitchContainerLeafPromise;
  1079. FutureArray.Add(SwitchContainerLeafPromise.GetFuture());
  1080. SwitchContainerExecutionQueue.Async([this, &bLoadedSwitchContainerLeaves, &InCookedData, &GroupValue, UsageCount, SwitchContainerLeafPromise = MoveTemp(SwitchContainerLeafPromise)]() mutable
  1081. {
  1082. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Adding optional %s for %s in Event %s (%" PRIu32 ")"),
  1083. *GroupValue.GetDebugString(), *UsageCount->Key.GetDebugString(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1084. auto FoundInfoId = LoadedGroupValueInfo.FindId(FWwiseSwitchContainerLoadedGroupValueInfo(GroupValue));
  1085. auto InfoId = FoundInfoId.IsValidId() ? FoundInfoId : LoadedGroupValueInfo.Add(FWwiseSwitchContainerLoadedGroupValueInfo(GroupValue), nullptr);
  1086. FWwiseSwitchContainerLoadedGroupValueInfo& Info = LoadedGroupValueInfo[InfoId];
  1087. bool bIsAlreadyCreated = false;
  1088. auto UsageCountId = Info.Leaves.Add(UsageCount, &bIsAlreadyCreated);
  1089. if (UNLIKELY(bIsAlreadyCreated))
  1090. {
  1091. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Creating already created Switch Container Leaf Usage Count @ %p for key %s"),
  1092. &UsageCount->LoadedData, *UsageCount->Key.GetDebugString());
  1093. return SwitchContainerLeafPromise.EmplaceValue();
  1094. }
  1095. bLoadedSwitchContainerLeaves = true;
  1096. UE_CLOG(!Info.ShouldBeLoaded(), LogWwiseResourceLoader, VeryVerbose, TEXT("Don't have referencing GroupValues yet: %d for key %s"), Info.LoadCount, *UsageCount->Key.GetDebugString());
  1097. UE_CLOG(Info.ShouldBeLoaded(), LogWwiseResourceLoader, VeryVerbose, TEXT("Have referencing GroupValues: %d for key %s"), Info.LoadCount, *UsageCount->Key.GetDebugString());
  1098. if (Info.ShouldBeLoaded())
  1099. {
  1100. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Number of GroupValues required for this leaf: %d/%d @ %p for key %s (+1 in Event)"),
  1101. (int)UsageCount->LoadedGroupValues.Num() + 1, UsageCount->Key.GroupValueSet.Num(), &UsageCount->LoadedData, *UsageCount->Key.GetDebugString());
  1102. bIsAlreadyCreated = false;
  1103. UsageCount->LoadedGroupValues.Add(GroupValue, &bIsAlreadyCreated);
  1104. if (UNLIKELY(bIsAlreadyCreated))
  1105. {
  1106. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Loading already created Switch Container Leaf LoadedGoupValueCount %d @ %p for key %s"),
  1107. (int)UsageCount->LoadedGroupValues.Num(), &UsageCount->LoadedData, *UsageCount->Key.GetDebugString());
  1108. return SwitchContainerLeafPromise.EmplaceValue();
  1109. }
  1110. if (UsageCount->HaveAllKeys())
  1111. {
  1112. check(!UsageCount->LoadedData.IsLoaded());
  1113. FWwiseResourceLoadPromise LeafResourcesPromise;
  1114. auto LeafResourcesFuture = LeafResourcesPromise.GetFuture();
  1115. LoadSwitchContainerLeafResources(MoveTemp(LeafResourcesPromise), UsageCount->LoadedData, UsageCount->Key);
  1116. LeafResourcesFuture.Next([SwitchContainerLeafPromise = MoveTemp(SwitchContainerLeafPromise)](bool bResult) mutable
  1117. {
  1118. SwitchContainerLeafPromise.EmplaceValue();
  1119. });
  1120. }
  1121. else
  1122. {
  1123. SwitchContainerLeafPromise.EmplaceValue();
  1124. }
  1125. }
  1126. else
  1127. {
  1128. SwitchContainerLeafPromise.EmplaceValue();
  1129. }
  1130. });
  1131. }
  1132. }
  1133. WaitForFutures(MoveTemp(FutureArray), [Promise = MoveTemp(Promise)]() mutable
  1134. {
  1135. Promise.EmplaceValue(true);
  1136. });
  1137. }
  1138. void FWwiseResourceLoaderImpl::LoadExternalSourceResources(FWwiseResourceLoadPromise&& Promise, FWwiseLoadedExternalSourceInfo::FLoadedData& LoadedData, const FWwiseExternalSourceCookedData& InCookedData)
  1139. {
  1140. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadExternalSourceResources"));
  1141. LogLoadResources(InCookedData);
  1142. if (UNLIKELY(LoadedData.IsLoaded()))
  1143. {
  1144. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadExternalSourceResources: ExternalSource %s (%" PRIu32 ") is already loaded."),
  1145. *InCookedData.DebugName.ToString(), (uint32)InCookedData.Cookie);
  1146. return Promise.EmplaceValue(false);
  1147. }
  1148. LoadExternalSourceFile(InCookedData, [Promise = MoveTemp(Promise), &LoadedData, &InCookedData](bool bResult) mutable
  1149. {
  1150. LoadedData.bLoaded = bResult;
  1151. if (UNLIKELY(!bResult))
  1152. {
  1153. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadExternalSourceResources: Could not load ExternalSource %s (%" PRIu32 ")"),
  1154. *InCookedData.DebugName.ToString(), (uint32)InCookedData.Cookie);
  1155. }
  1156. Promise.EmplaceValue(bResult);
  1157. });
  1158. }
  1159. void FWwiseResourceLoaderImpl::LoadGroupValueResources(FWwiseResourceLoadPromise&& Promise, FWwiseLoadedGroupValueInfo::FLoadedData& LoadedData, const FWwiseGroupValueCookedData& InCookedData)
  1160. {
  1161. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadGroupValueResources"));
  1162. LogLoadResources(InCookedData);
  1163. SwitchContainerExecutionQueue.Async([this, &LoadedData, &InCookedData, Promise = MoveTemp(Promise)]() mutable
  1164. {
  1165. auto FoundInfoId = LoadedGroupValueInfo.FindId(FWwiseSwitchContainerLoadedGroupValueInfo(InCookedData));
  1166. auto InfoId = FoundInfoId.IsValidId() ? FoundInfoId : LoadedGroupValueInfo.Add(FWwiseSwitchContainerLoadedGroupValueInfo(InCookedData), nullptr);
  1167. FWwiseSwitchContainerLoadedGroupValueInfo& Info = LoadedGroupValueInfo[InfoId];
  1168. const bool bWasLoaded = Info.ShouldBeLoaded();
  1169. ++Info.LoadCount;
  1170. FCompletionFutureArray FutureArray;
  1171. if (!bWasLoaded && Info.ShouldBeLoaded())
  1172. {
  1173. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("First GroupValue %s (%s %" PRIu32 ":%" PRIu32 ") load. Loading %d leaves."),
  1174. *InCookedData.DebugName.ToString(), *InCookedData.GetTypeName(), (uint32)InCookedData.GroupId, (uint32)InCookedData.Id, (int)Info.Leaves.Num());
  1175. for (auto* UsageCount : Info.Leaves)
  1176. {
  1177. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Number of GroupValues required for a leaf: %d/%d @ %p for key %s (+1 in GroupValue)"),
  1178. (int)UsageCount->LoadedGroupValues.Num() + 1, UsageCount->Key.GroupValueSet.Num(), &UsageCount->LoadedData, *UsageCount->Key.GetDebugString());
  1179. bool bIsAlreadyCreated = false;
  1180. UsageCount->LoadedGroupValues.Add(InCookedData, &bIsAlreadyCreated);
  1181. if (UNLIKELY(bIsAlreadyCreated))
  1182. {
  1183. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Loading already created LoadedGroupValue @ %p for key %s"),
  1184. &UsageCount->LoadedData, *UsageCount->Key.GetDebugString());
  1185. continue;
  1186. }
  1187. if (UsageCount->HaveAllKeys())
  1188. {
  1189. FWwiseResourceLoadPromise LeafPromise;
  1190. auto LeafFuture = LeafPromise.GetFuture();
  1191. LoadSwitchContainerLeafResources(MoveTemp(LeafPromise), UsageCount->LoadedData, UsageCount->Key);
  1192. FCompletionPromise CompletionPromise;
  1193. FutureArray.Add(CompletionPromise.GetFuture());
  1194. LeafFuture.Next([CompletionPromise = MoveTemp(CompletionPromise)](int) mutable
  1195. {
  1196. CompletionPromise.EmplaceValue();
  1197. });
  1198. }
  1199. }
  1200. }
  1201. else
  1202. {
  1203. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("GroupValue %s (%s %" PRIu32 ":%" PRIu32 ") already loaded (Count: %d times)."),
  1204. *InCookedData.DebugName.ToString(), *InCookedData.GetTypeName(), (uint32)InCookedData.GroupId, (uint32)InCookedData.Id, (int)Info.LoadCount);
  1205. }
  1206. WaitForFutures(MoveTemp(FutureArray), [&LoadedData, Promise = MoveTemp(Promise)]() mutable
  1207. {
  1208. LoadedData.bLoaded = true;
  1209. // We always return success, as GroupValues are not complete deal-breaks and we cannot do anything if they fail.
  1210. return Promise.EmplaceValue(true);
  1211. });
  1212. });
  1213. }
  1214. void FWwiseResourceLoaderImpl::LoadInitBankResources(FWwiseResourceLoadPromise&& Promise, FWwiseLoadedInitBankInfo::FLoadedData& LoadedData, const FWwiseInitBankCookedData& InCookedData)
  1215. {
  1216. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadInitBankResources"));
  1217. LogLoadResources(InCookedData);
  1218. auto& LoadedMedia = LoadedData.LoadedMedia;
  1219. if (UNLIKELY(LoadedData.IsLoaded()))
  1220. {
  1221. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadInitBankResources: InitBank %s (%" PRIu32 ") is already loaded."),
  1222. *InCookedData.DebugName.ToString(), (uint32)InCookedData.SoundBankId);
  1223. return Promise.EmplaceValue(false);
  1224. }
  1225. FCompletionFutureArray FutureArray;
  1226. AddLoadMediaFutures(FutureArray, LoadedMedia, InCookedData.Media, TEXT("InitBank"), InCookedData.DebugName, InCookedData.SoundBankId);
  1227. WaitForFutures(MoveTemp(FutureArray), [this, Promise = MoveTemp(Promise), &LoadedData, &InCookedData]() mutable
  1228. {
  1229. TPromise<bool> SoundBankPromise;
  1230. auto Future = SoundBankPromise.GetFuture();
  1231. LoadSoundBankFile(InCookedData, [SoundBankPromise = MoveTemp(SoundBankPromise)](bool bInResult) mutable
  1232. {
  1233. SoundBankPromise.EmplaceValue(bInResult);
  1234. });
  1235. Future.Next([this, Promise = MoveTemp(Promise), &LoadedData, &InCookedData](bool bLoaded) mutable
  1236. {
  1237. LoadedData.bLoaded = bLoaded;
  1238. if (UNLIKELY(!bLoaded))
  1239. {
  1240. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadInitBankResources: Could not load InitBank %s (%" PRIu32 ")"),
  1241. *InCookedData.DebugName.ToString(), (uint32)InCookedData.SoundBankId);
  1242. }
  1243. return Promise.EmplaceValue(bLoaded);
  1244. });
  1245. });
  1246. }
  1247. void FWwiseResourceLoaderImpl::LoadMediaResources(FWwiseResourceLoadPromise&& Promise, FWwiseLoadedMediaInfo::FLoadedData& LoadedData, const FWwiseMediaCookedData& InCookedData)
  1248. {
  1249. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadMediaResources"));
  1250. LogLoadResources(InCookedData);
  1251. if (UNLIKELY(LoadedData.IsLoaded()))
  1252. {
  1253. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadMediaResources: Media %s (%" PRIu32 ") is already loaded."),
  1254. *InCookedData.DebugName.ToString(), (uint32)InCookedData.MediaId);
  1255. return Promise.EmplaceValue(false);
  1256. }
  1257. LoadMediaFile(InCookedData, [Promise = MoveTemp(Promise), &LoadedData, &InCookedData](bool bResult) mutable
  1258. {
  1259. LoadedData.bLoaded = bResult;
  1260. if (UNLIKELY(!bResult))
  1261. {
  1262. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadMediaResources: Could not load Media %s (%" PRIu32 ")"),
  1263. *InCookedData.DebugName.ToString(), (uint32)InCookedData.MediaId);
  1264. }
  1265. Promise.EmplaceValue(bResult);
  1266. });
  1267. }
  1268. void FWwiseResourceLoaderImpl::LoadShareSetResources(FWwiseResourceLoadPromise&& Promise, FWwiseLoadedShareSetInfo::FLoadedData& LoadedData, const FWwiseShareSetCookedData& InCookedData)
  1269. {
  1270. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadShareSetResources"));
  1271. LogLoadResources(InCookedData);
  1272. auto& LoadedSoundBanks = LoadedData.LoadedSoundBanks;
  1273. auto& LoadedMedia = LoadedData.LoadedMedia;
  1274. if (UNLIKELY(LoadedData.IsLoaded()))
  1275. {
  1276. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadShareSetResources: ShareSet %s (%" PRIu32 ") is already loaded."),
  1277. *InCookedData.DebugName.ToString(), (uint32)InCookedData.ShareSetId);
  1278. return Promise.EmplaceValue(false);
  1279. }
  1280. FCompletionFutureArray FutureArray;
  1281. AddLoadMediaFutures(FutureArray, LoadedMedia, InCookedData.Media, TEXT("ShareSet"), InCookedData.DebugName, InCookedData.ShareSetId);
  1282. AddLoadSoundBankFutures(FutureArray, LoadedSoundBanks, InCookedData.SoundBanks, TEXT("ShareSet"), InCookedData.DebugName, InCookedData.ShareSetId);
  1283. WaitForFutures(MoveTemp(FutureArray), [this, Promise = MoveTemp(Promise), &LoadedData, &LoadedSoundBanks, &InCookedData]() mutable
  1284. {
  1285. if (UNLIKELY(LoadedSoundBanks.Num() != InCookedData.SoundBanks.Num()))
  1286. {
  1287. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadShareSetResources: Could not load %d SoundBanks for ShareSet %s (%" PRIu32 "). Unloading and failing."),
  1288. InCookedData.SoundBanks.Num() - LoadedSoundBanks.Num(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.ShareSetId);
  1289. FWwiseResourceUnloadPromise UnloadPromise;
  1290. auto UnloadFuture = UnloadPromise.GetFuture();
  1291. UnloadShareSetResources(MoveTemp(UnloadPromise), LoadedData, InCookedData);
  1292. UnloadFuture.Next([Promise = MoveTemp(Promise)](int) mutable
  1293. {
  1294. return Promise.EmplaceValue(false);
  1295. });
  1296. }
  1297. else
  1298. {
  1299. return Promise.EmplaceValue(true);
  1300. }
  1301. });
  1302. }
  1303. void FWwiseResourceLoaderImpl::LoadSoundBankResources(FWwiseResourceLoadPromise&& Promise, FWwiseLoadedSoundBankInfo::FLoadedData& LoadedData, const FWwiseSoundBankCookedData& InCookedData)
  1304. {
  1305. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadSoundBankResources"));
  1306. LogLoadResources(InCookedData);
  1307. if (UNLIKELY(LoadedData.IsLoaded()))
  1308. {
  1309. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadSoundBankResources: SoundBank %s (%" PRIu32 ") is already loaded."),
  1310. *InCookedData.DebugName.ToString(), (uint32)InCookedData.SoundBankId);
  1311. return Promise.EmplaceValue(false);
  1312. }
  1313. LoadSoundBankFile(InCookedData, [Promise = MoveTemp(Promise), &LoadedData, &InCookedData](bool bResult) mutable
  1314. {
  1315. LoadedData.bLoaded = bResult;
  1316. if (UNLIKELY(!bResult))
  1317. {
  1318. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadSoundBankResources: Could not load SoundBank %s (%" PRIu32 ")"),
  1319. *InCookedData.DebugName.ToString(), (uint32)InCookedData.SoundBankId);
  1320. }
  1321. Promise.EmplaceValue(bResult);
  1322. });
  1323. }
  1324. void FWwiseResourceLoaderImpl::LoadSwitchContainerLeafResources(FWwiseResourceLoadPromise&& Promise, FWwiseSwitchContainerLeafGroupValueUsageCount::FLoadedData& LoadedData, const FWwiseSwitchContainerLeafCookedData& InCookedData)
  1325. {
  1326. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("LoadSwitchContainerLeafResources"));
  1327. LogLoadResources(InCookedData, &LoadedData);
  1328. auto& LoadedSoundBanks = LoadedData.LoadedSoundBanks;
  1329. auto& LoadedExternalSources = LoadedData.LoadedExternalSources;
  1330. auto& LoadedMedia = LoadedData.LoadedMedia;
  1331. if (UNLIKELY(LoadedData.IsLoaded()))
  1332. {
  1333. UE_LOG(LogWwiseResourceLoader, Error, TEXT("LoadSwitchContainerLeafResources: Leaf is already loaded."));
  1334. return Promise.EmplaceValue(true); // It's loaded, it exists, even if wrong.
  1335. }
  1336. FCompletionFutureArray FutureArray;
  1337. AddLoadExternalSourceFutures(FutureArray, LoadedExternalSources, InCookedData.ExternalSources, TEXT("Leaf"), {}, 0);
  1338. AddLoadMediaFutures(FutureArray, LoadedMedia, InCookedData.Media, TEXT("Leaf"), {}, 0);
  1339. AddLoadSoundBankFutures(FutureArray, LoadedSoundBanks, InCookedData.SoundBanks, TEXT("Leaf"), {}, 0);
  1340. WaitForFutures(MoveTemp(FutureArray), [Promise = MoveTemp(Promise)]() mutable
  1341. {
  1342. INC_DWORD_STAT(STAT_WwiseResourceLoaderSwitchContainerCombinations);
  1343. Promise.EmplaceValue(true);
  1344. });
  1345. }
  1346. void FWwiseResourceLoaderImpl::UnloadAuxBusResources(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedAuxBusInfo::FLoadedData& LoadedData, const FWwiseAuxBusCookedData& InCookedData)
  1347. {
  1348. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadAuxBusResources"));
  1349. LogUnloadResources(InCookedData);
  1350. auto& LoadedSoundBanks = LoadedData.LoadedSoundBanks;
  1351. auto& LoadedMedia = LoadedData.LoadedMedia;
  1352. FCompletionFutureArray FutureArray;
  1353. AddUnloadSoundBankFutures(FutureArray, LoadedSoundBanks);
  1354. WaitForFutures(MoveTemp(FutureArray), [this, Promise = MoveTemp(Promise), &LoadedMedia]() mutable
  1355. {
  1356. FCompletionFutureArray FutureArray;
  1357. AddUnloadMediaFutures(FutureArray, LoadedMedia);
  1358. WaitForFutures(MoveTemp(FutureArray), [Promise = MoveTemp(Promise)]() mutable
  1359. {
  1360. Promise.EmplaceValue();
  1361. });
  1362. });
  1363. }
  1364. void FWwiseResourceLoaderImpl::UnloadEventResources(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedEventInfo::FLoadedData& LoadedData, const FWwiseEventCookedData& InCookedData)
  1365. {
  1366. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadEventResources"));
  1367. LogUnloadResources(InCookedData);
  1368. auto& LoadedSoundBanks = LoadedData.LoadedSoundBanks;
  1369. FCompletionFutureArray FutureArray;
  1370. AddUnloadSoundBankFutures(FutureArray, LoadedSoundBanks);
  1371. WaitForFutures(MoveTemp(FutureArray), [this, Promise = MoveTemp(Promise), &LoadedData, &InCookedData]() mutable
  1372. {
  1373. auto& LoadedExternalSources = LoadedData.LoadedExternalSources;
  1374. auto& LoadedMedia = LoadedData.LoadedMedia;
  1375. FCompletionFutureArray FutureArray;
  1376. if (LoadedData.bLoadedSwitchContainerLeaves || LoadedData.LoadedRequiredGroupValues.Num() > 0)
  1377. {
  1378. FCompletionPromise SwitchContainerLeavesPromise;
  1379. FutureArray.Add(SwitchContainerLeavesPromise.GetFuture());
  1380. AsyncTask(TaskThread, [this, &LoadedData, &InCookedData, SwitchContainerLeavesPromise = MoveTemp(SwitchContainerLeavesPromise)]() mutable
  1381. {
  1382. UnloadEventSwitchContainerResources(MoveTemp(SwitchContainerLeavesPromise), LoadedData, InCookedData);
  1383. });
  1384. }
  1385. AddUnloadExternalSourceFutures(FutureArray, LoadedExternalSources);
  1386. AddUnloadMediaFutures(FutureArray, LoadedMedia);
  1387. WaitForFutures(MoveTemp(FutureArray), [Promise = MoveTemp(Promise)]() mutable
  1388. {
  1389. Promise.EmplaceValue();
  1390. });
  1391. });
  1392. }
  1393. void FWwiseResourceLoaderImpl::UnloadEventSwitchContainerResources(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedEventInfo::FLoadedData& LoadedData, const FWwiseEventCookedData& InCookedData)
  1394. {
  1395. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadEventSwitchContainerResources"));
  1396. // Unload required GroupValues
  1397. FWwiseLoadedGroupValueList& LoadedRequiredGroupValues = LoadedData.LoadedRequiredGroupValues;
  1398. bool& bLoadedSwitchContainerLeaves = LoadedData.bLoadedSwitchContainerLeaves;
  1399. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Unloading %d GroupValues for Event %s (%" PRIu32 ")"),
  1400. (int)LoadedRequiredGroupValues.Num(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1401. FCompletionFutureArray FutureArray;
  1402. for (auto& GroupValue : LoadedRequiredGroupValues)
  1403. {
  1404. FCompletionPromise GroupValuePromise;
  1405. FutureArray.Add(GroupValuePromise.GetFuture());
  1406. SwitchContainerExecutionQueue.Async([this, &InCookedData, &GroupValue, GroupValuePromise = MoveTemp(GroupValuePromise)]() mutable
  1407. {
  1408. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Unloading GroupValue %s for Event %s (%" PRIu32 ")"),
  1409. *GroupValue.GroupValueCookedData.DebugName.ToString(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1410. UnloadGroupValueResources(MoveTemp(GroupValuePromise), GroupValue.LoadedData, GroupValue.GroupValueCookedData);
  1411. });
  1412. }
  1413. // Unload Switch Container Leaves
  1414. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Unloading %d Leaves for Event %s (%" PRIu32 ")"),
  1415. (int)InCookedData.SwitchContainerLeaves.Num(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1416. if (bLoadedSwitchContainerLeaves) for (const auto& SwitchContainerLeaf : InCookedData.SwitchContainerLeaves)
  1417. {
  1418. FCompletionPromise SwitchContainerLeavesPromise;
  1419. FutureArray.Add(SwitchContainerLeavesPromise.GetFuture());
  1420. SwitchContainerExecutionQueue.Async([this, &SwitchContainerLeaf, &InCookedData, SwitchContainerLeavesPromise = MoveTemp(SwitchContainerLeavesPromise)]() mutable
  1421. {
  1422. FWwiseSwitchContainerLeafGroupValueUsageCount* UsageCount = nullptr;
  1423. for (const auto& GroupValue : SwitchContainerLeaf.GroupValueSet)
  1424. {
  1425. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Removing requested GroupValue %s for Leaf in Event %s (%" PRIu32 ")"),
  1426. *GroupValue.DebugName.ToString(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1427. FWwiseSwitchContainerLoadedGroupValueInfo* Info = LoadedGroupValueInfo.Find(FWwiseSwitchContainerLoadedGroupValueInfo(GroupValue));
  1428. if (UNLIKELY(!Info))
  1429. {
  1430. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Could not find requested GroupValue %s for Leaf in Event %s (%" PRIu32 ")"),
  1431. *GroupValue.DebugName.ToString(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1432. continue;
  1433. }
  1434. if (!UsageCount)
  1435. {
  1436. for (auto* Leaf : Info->Leaves)
  1437. {
  1438. if (&Leaf->Key == &SwitchContainerLeaf)
  1439. {
  1440. UsageCount = Leaf;
  1441. break;
  1442. }
  1443. }
  1444. if (UNLIKELY(!UsageCount))
  1445. {
  1446. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Could not find requested Leaf in GroupValue %s in Event %s (%" PRIu32 ")"),
  1447. *GroupValue.DebugName.ToString(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1448. continue;
  1449. }
  1450. }
  1451. Info->Leaves.Remove(UsageCount);
  1452. UE_CLOG(!Info->ShouldBeLoaded(), LogWwiseResourceLoader, VeryVerbose, TEXT("Don't have referencing GroupValues yet: %d for key %s"), Info->LoadCount, *UsageCount->Key.GetDebugString());
  1453. UE_CLOG(Info->ShouldBeLoaded(), LogWwiseResourceLoader, VeryVerbose, TEXT("Have referencing GroupValues: %d for key %s"), Info->LoadCount, *UsageCount->Key.GetDebugString());
  1454. if (Info->ShouldBeLoaded())
  1455. {
  1456. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Number of GroupValues required for this leaf: %d/%d @ %p for key %s (-1 in SwitchContainer)"),
  1457. (int)UsageCount->LoadedGroupValues.Num() - 1, UsageCount->Key.GroupValueSet.Num(), &UsageCount->LoadedData, *UsageCount->Key.GetDebugString());
  1458. UsageCount->LoadedGroupValues.Remove(GroupValue);
  1459. }
  1460. }
  1461. if (LIKELY(UsageCount))
  1462. {
  1463. if (UNLIKELY(UsageCount->LoadedGroupValues.Num() > 0))
  1464. {
  1465. UE_LOG(LogWwiseResourceLoader, Error, TEXT("There are still %d loaded elements for leaf in Event %s (%" PRIu32 ")"),
  1466. (int)UsageCount->LoadedGroupValues.Num(), *InCookedData.DebugName.ToString(), (uint32)InCookedData.EventId);
  1467. }
  1468. FWwiseResourceUnloadPromise UnloadPromise;
  1469. auto UnloadFuture = UnloadPromise.GetFuture();
  1470. UnloadSwitchContainerLeafResources(MoveTemp(UnloadPromise), UsageCount->LoadedData, UsageCount->Key);
  1471. UnloadFuture.Next([UsageCount, SwitchContainerLeavesPromise = MoveTemp(SwitchContainerLeavesPromise)](int) mutable
  1472. {
  1473. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Deleting Switch Container Leaf Usage Count @ %p"), &UsageCount->LoadedData);
  1474. delete UsageCount;
  1475. SwitchContainerLeavesPromise.EmplaceValue();
  1476. });
  1477. }
  1478. else
  1479. {
  1480. SwitchContainerLeavesPromise.EmplaceValue();
  1481. }
  1482. });
  1483. }
  1484. WaitForFutures(MoveTemp(FutureArray), [Promise = MoveTemp(Promise), &LoadedRequiredGroupValues, &bLoadedSwitchContainerLeaves]() mutable
  1485. {
  1486. LoadedRequiredGroupValues.Empty();
  1487. bLoadedSwitchContainerLeaves = false;
  1488. Promise.EmplaceValue();
  1489. });
  1490. }
  1491. void FWwiseResourceLoaderImpl::UnloadExternalSourceResources(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedExternalSourceInfo::FLoadedData& LoadedData, const FWwiseExternalSourceCookedData& InCookedData)
  1492. {
  1493. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadExternalSourceResources"));
  1494. LogUnloadResources(InCookedData);
  1495. if (LoadedData.IsLoaded())
  1496. {
  1497. UnloadExternalSourceFile(InCookedData, [ &LoadedData, Promise = MoveTemp(Promise)]() mutable
  1498. {
  1499. LoadedData.bLoaded = false;
  1500. Promise.EmplaceValue();
  1501. });
  1502. }
  1503. else
  1504. {
  1505. Promise.EmplaceValue();
  1506. }
  1507. }
  1508. void FWwiseResourceLoaderImpl::UnloadGroupValueResources(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedGroupValueInfo::FLoadedData& LoadedData, const FWwiseGroupValueCookedData& InCookedData)
  1509. {
  1510. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadGroupValueResources"));
  1511. LogUnloadResources(InCookedData);
  1512. SwitchContainerExecutionQueue.Async([this, &LoadedData, &InCookedData, Promise = MoveTemp(Promise)]() mutable
  1513. {
  1514. FWwiseSwitchContainerLoadedGroupValueInfo* Info = LoadedGroupValueInfo.Find(FWwiseSwitchContainerLoadedGroupValueInfo(InCookedData));
  1515. if (UNLIKELY(!Info))
  1516. {
  1517. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Could not find requested GroupValue %s (%s %" PRIu32 ":%" PRIu32 ")"),
  1518. *InCookedData.DebugName.ToString(), *InCookedData.GetTypeName(), (uint32)InCookedData.GroupId, (uint32)InCookedData.Id);
  1519. return Promise.EmplaceValue();
  1520. }
  1521. check(Info->ShouldBeLoaded());
  1522. --Info->LoadCount;
  1523. FCompletionFutureArray FutureArray;
  1524. if (!Info->ShouldBeLoaded())
  1525. {
  1526. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Last GroupValue %s (%s %" PRIu32 ":%" PRIu32 ") unload. Unloading %d leaves."),
  1527. *InCookedData.DebugName.ToString(), *InCookedData.GetTypeName(), (uint32)InCookedData.GroupId, (uint32)InCookedData.Id, (int)Info->Leaves.Num());
  1528. for (auto* UsageCount : Info->Leaves)
  1529. {
  1530. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Number of GroupValues required for a leaf: %d/%d @ %p for key %s (-1 in GroupValue)"),
  1531. (int)UsageCount->LoadedGroupValues.Num() - 1, UsageCount->Key.GroupValueSet.Num(), &UsageCount->LoadedData, *UsageCount->Key.GetDebugString());
  1532. check(UsageCount->LoadedGroupValues.Num() > 0);
  1533. check(UsageCount->LoadedData.IsLoaded() && UsageCount->HaveAllKeys() || !UsageCount->LoadedData.IsLoaded());
  1534. UsageCount->LoadedGroupValues.Remove(InCookedData);
  1535. FWwiseResourceUnloadPromise UnloadPromise;
  1536. FutureArray.Add(UnloadPromise.GetFuture());
  1537. UnloadSwitchContainerLeafResources(MoveTemp(UnloadPromise), UsageCount->LoadedData, UsageCount->Key);
  1538. }
  1539. }
  1540. else
  1541. {
  1542. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("GroupValue %s (%s %" PRIu32 ":%" PRIu32 ") still loaded (Count: %d times)."),
  1543. *InCookedData.DebugName.ToString(), *InCookedData.GetTypeName(), (uint32)InCookedData.GroupId, (uint32)InCookedData.Id, (int)Info->LoadCount);
  1544. }
  1545. WaitForFutures(MoveTemp(FutureArray), [Promise = MoveTemp(Promise)]() mutable
  1546. {
  1547. Promise.EmplaceValue();
  1548. });
  1549. });
  1550. }
  1551. void FWwiseResourceLoaderImpl::UnloadInitBankResources(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedInitBankInfo::FLoadedData& LoadedData, const FWwiseInitBankCookedData& InCookedData)
  1552. {
  1553. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadInitBankResources"));
  1554. LogUnloadResources(InCookedData);
  1555. auto& LoadedMedia = LoadedData.LoadedMedia;
  1556. FCompletionPromise SoundBankPromise;
  1557. auto Future = SoundBankPromise.GetFuture();
  1558. if (LoadedData.bLoaded)
  1559. {
  1560. UnloadSoundBankFile(InCookedData, [&LoadedData, SoundBankPromise = MoveTemp(SoundBankPromise)]() mutable
  1561. {
  1562. LoadedData.bLoaded = false;
  1563. SoundBankPromise.EmplaceValue();
  1564. });
  1565. }
  1566. else
  1567. {
  1568. SoundBankPromise.EmplaceValue();
  1569. }
  1570. Future.Next([this, Promise = MoveTemp(Promise), &LoadedMedia](int) mutable
  1571. {
  1572. FCompletionFutureArray FutureArray;
  1573. AddUnloadMediaFutures(FutureArray, LoadedMedia);
  1574. WaitForFutures(MoveTemp(FutureArray), [Promise = MoveTemp(Promise)]() mutable
  1575. {
  1576. Promise.EmplaceValue();
  1577. });
  1578. });
  1579. }
  1580. void FWwiseResourceLoaderImpl::UnloadMediaResources(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedMediaInfo::FLoadedData& LoadedData, const FWwiseMediaCookedData& InCookedData)
  1581. {
  1582. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadMediaResources"));
  1583. LogUnloadResources(InCookedData);
  1584. if (LoadedData.IsLoaded())
  1585. {
  1586. UnloadMediaFile(InCookedData, [Promise = MoveTemp(Promise), &LoadedData]() mutable
  1587. {
  1588. LoadedData.bLoaded = false;
  1589. Promise.EmplaceValue();
  1590. });
  1591. }
  1592. else
  1593. {
  1594. Promise.EmplaceValue();
  1595. }
  1596. }
  1597. void FWwiseResourceLoaderImpl::UnloadShareSetResources(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedShareSetInfo::FLoadedData& LoadedData, const FWwiseShareSetCookedData& InCookedData)
  1598. {
  1599. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadShareSetResources"));
  1600. LogUnloadResources(InCookedData);
  1601. auto& LoadedSoundBanks = LoadedData.LoadedSoundBanks;
  1602. auto& LoadedMedia = LoadedData.LoadedMedia;
  1603. FCompletionFutureArray FutureArray;
  1604. AddUnloadSoundBankFutures(FutureArray, LoadedSoundBanks);
  1605. WaitForFutures(MoveTemp(FutureArray), [this, Promise = MoveTemp(Promise), &LoadedMedia]() mutable
  1606. {
  1607. FCompletionFutureArray FutureArray;
  1608. AddUnloadMediaFutures(FutureArray, LoadedMedia);
  1609. WaitForFutures(MoveTemp(FutureArray), [Promise = MoveTemp(Promise)]() mutable
  1610. {
  1611. Promise.EmplaceValue();
  1612. });
  1613. });
  1614. }
  1615. void FWwiseResourceLoaderImpl::UnloadSoundBankResources(FWwiseResourceUnloadPromise&& Promise, FWwiseLoadedSoundBankInfo::FLoadedData& LoadedData, const FWwiseSoundBankCookedData& InCookedData)
  1616. {
  1617. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadSoundBankResources"));
  1618. LogUnloadResources(InCookedData);
  1619. if (LoadedData.IsLoaded())
  1620. {
  1621. UnloadSoundBankFile(InCookedData, [Promise = MoveTemp(Promise), &LoadedData]() mutable
  1622. {
  1623. LoadedData.bLoaded = false;
  1624. Promise.EmplaceValue();
  1625. });
  1626. }
  1627. else
  1628. {
  1629. Promise.EmplaceValue();
  1630. }
  1631. }
  1632. void FWwiseResourceLoaderImpl::UnloadSwitchContainerLeafResources(FWwiseResourceUnloadPromise&& Promise, FWwiseSwitchContainerLeafGroupValueUsageCount::FLoadedData& LoadedData, const FWwiseSwitchContainerLeafCookedData& InCookedData)
  1633. {
  1634. SCOPED_WWISERESOURCELOADER_EVENT_2(TEXT("UnloadSwitchContainerLeafResources"));
  1635. LogUnloadResources(InCookedData, &LoadedData);
  1636. auto& LoadedSoundBanks = LoadedData.LoadedSoundBanks;
  1637. auto& LoadedExternalSources = LoadedData.LoadedExternalSources;
  1638. auto& LoadedMedia = LoadedData.LoadedMedia;
  1639. FCompletionFutureArray FutureArray;
  1640. AddUnloadSoundBankFutures(FutureArray, LoadedSoundBanks);
  1641. WaitForFutures(MoveTemp(FutureArray), [this, Promise = MoveTemp(Promise), &LoadedExternalSources, &LoadedMedia, &LoadedData]() mutable
  1642. {
  1643. FCompletionFutureArray FutureArray;
  1644. AddUnloadExternalSourceFutures(FutureArray, LoadedExternalSources);
  1645. AddUnloadMediaFutures(FutureArray, LoadedMedia);
  1646. WaitForFutures(MoveTemp(FutureArray), [Promise = MoveTemp(Promise), &LoadedData]() mutable
  1647. {
  1648. DEC_DWORD_STAT(STAT_WwiseResourceLoaderSwitchContainerCombinations);
  1649. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("Done unloading Switch Container Leaf @ %p"), &LoadedData);
  1650. Promise.EmplaceValue();
  1651. });
  1652. });
  1653. }
  1654. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::AttachAuxBusNode(FWwiseLoadedAuxBus AuxBusListNode)
  1655. {
  1656. FCompletionPromise Promise;
  1657. auto Future = Promise.GetFuture();
  1658. LoadedListExecutionQueue.Async([this, AuxBusListNode = MoveTemp(AuxBusListNode), Promise = MoveTemp(Promise)]() mutable
  1659. {
  1660. LoadedAuxBusList.AddTail(AuxBusListNode);
  1661. INC_DWORD_STAT(STAT_WwiseResourceLoaderAuxBusses);
  1662. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1663. {
  1664. Promise.EmplaceValue();
  1665. });
  1666. });
  1667. return Future;
  1668. }
  1669. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::AttachEventNode(FWwiseLoadedEvent EventListNode)
  1670. {
  1671. FCompletionPromise Promise;
  1672. auto Future = Promise.GetFuture();
  1673. LoadedListExecutionQueue.Async([this, EventListNode = MoveTemp(EventListNode), Promise = MoveTemp(Promise)]() mutable
  1674. {
  1675. LoadedEventList.AddTail(EventListNode);
  1676. INC_DWORD_STAT(STAT_WwiseResourceLoaderEvents);
  1677. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1678. {
  1679. Promise.EmplaceValue();
  1680. });
  1681. });
  1682. return Future;
  1683. }
  1684. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::AttachExternalSourceNode(FWwiseLoadedExternalSource ExternalSourceListNode)
  1685. {
  1686. FCompletionPromise Promise;
  1687. auto Future = Promise.GetFuture();
  1688. LoadedListExecutionQueue.Async([this, ExternalSourceListNode = MoveTemp(ExternalSourceListNode), Promise = MoveTemp(Promise)]() mutable
  1689. {
  1690. LoadedExternalSourceList.AddTail(ExternalSourceListNode);
  1691. INC_DWORD_STAT(STAT_WwiseResourceLoaderExternalSources);
  1692. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1693. {
  1694. Promise.EmplaceValue();
  1695. });
  1696. });
  1697. return Future;
  1698. }
  1699. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::AttachGroupValueNode(FWwiseLoadedGroupValue GroupValueListNode)
  1700. {
  1701. FCompletionPromise Promise;
  1702. auto Future = Promise.GetFuture();
  1703. LoadedListExecutionQueue.Async([this, GroupValueListNode = MoveTemp(GroupValueListNode), Promise = MoveTemp(Promise)]() mutable
  1704. {
  1705. LoadedGroupValueList.AddTail(GroupValueListNode);
  1706. INC_DWORD_STAT(STAT_WwiseResourceLoaderGroupValues);
  1707. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1708. {
  1709. Promise.EmplaceValue();
  1710. });
  1711. });
  1712. return Future;
  1713. }
  1714. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::AttachInitBankNode(FWwiseLoadedInitBank InitBankListNode)
  1715. {
  1716. FCompletionPromise Promise;
  1717. auto Future = Promise.GetFuture();
  1718. LoadedListExecutionQueue.Async([this, InitBankListNode = MoveTemp(InitBankListNode), Promise = MoveTemp(Promise)]() mutable
  1719. {
  1720. LoadedInitBankList.AddTail(InitBankListNode);
  1721. INC_DWORD_STAT(STAT_WwiseResourceLoaderInitBanks);
  1722. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1723. {
  1724. Promise.EmplaceValue();
  1725. });
  1726. });
  1727. return Future;
  1728. }
  1729. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::AttachMediaNode(FWwiseLoadedMedia MediaListNode)
  1730. {
  1731. FCompletionPromise Promise;
  1732. auto Future = Promise.GetFuture();
  1733. LoadedListExecutionQueue.Async([this, MediaListNode = MoveTemp(MediaListNode), Promise = MoveTemp(Promise)]() mutable
  1734. {
  1735. LoadedMediaList.AddTail(MediaListNode);
  1736. INC_DWORD_STAT(STAT_WwiseResourceLoaderMedia);
  1737. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1738. {
  1739. Promise.EmplaceValue();
  1740. });
  1741. });
  1742. return Future;
  1743. }
  1744. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::AttachShareSetNode(FWwiseLoadedShareSet ShareSetListNode)
  1745. {
  1746. FCompletionPromise Promise;
  1747. auto Future = Promise.GetFuture();
  1748. LoadedListExecutionQueue.Async([this, ShareSetListNode = MoveTemp(ShareSetListNode), Promise = MoveTemp(Promise)]() mutable
  1749. {
  1750. LoadedShareSetList.AddTail(ShareSetListNode);
  1751. INC_DWORD_STAT(STAT_WwiseResourceLoaderShareSets);
  1752. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1753. {
  1754. Promise.EmplaceValue();
  1755. });
  1756. });
  1757. return Future;
  1758. }
  1759. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::AttachSoundBankNode(FWwiseLoadedSoundBank SoundBankListNode)
  1760. {
  1761. FCompletionPromise Promise;
  1762. auto Future = Promise.GetFuture();
  1763. LoadedListExecutionQueue.Async([this, SoundBankListNode = MoveTemp(SoundBankListNode), Promise = MoveTemp(Promise)]() mutable
  1764. {
  1765. LoadedSoundBankList.AddTail(SoundBankListNode);
  1766. INC_DWORD_STAT(STAT_WwiseResourceLoaderSoundBanks);
  1767. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1768. {
  1769. Promise.EmplaceValue();
  1770. });
  1771. });
  1772. return Future;
  1773. }
  1774. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::DetachAuxBusNode(FWwiseLoadedAuxBus AuxBusListNode)
  1775. {
  1776. FCompletionPromise Promise;
  1777. auto Future = Promise.GetFuture();
  1778. LoadedListExecutionQueue.Async([this, AuxBusListNode = MoveTemp(AuxBusListNode), Promise = MoveTemp(Promise)]() mutable
  1779. {
  1780. LoadedAuxBusList.RemoveNode(AuxBusListNode, false);
  1781. DEC_DWORD_STAT(STAT_WwiseResourceLoaderAuxBusses);
  1782. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1783. {
  1784. Promise.EmplaceValue();
  1785. });
  1786. });
  1787. return Future;
  1788. }
  1789. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::DetachEventNode(FWwiseLoadedEvent EventListNode)
  1790. {
  1791. FCompletionPromise Promise;
  1792. auto Future = Promise.GetFuture();
  1793. LoadedListExecutionQueue.Async([this, EventListNode = MoveTemp(EventListNode), Promise = MoveTemp(Promise)]() mutable
  1794. {
  1795. LoadedEventList.RemoveNode(EventListNode, false);
  1796. DEC_DWORD_STAT(STAT_WwiseResourceLoaderEvents);
  1797. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1798. {
  1799. Promise.EmplaceValue();
  1800. });
  1801. });
  1802. return Future;
  1803. }
  1804. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::DetachExternalSourceNode(FWwiseLoadedExternalSource ExternalSourceListNode)
  1805. {
  1806. FCompletionPromise Promise;
  1807. auto Future = Promise.GetFuture();
  1808. LoadedListExecutionQueue.Async([this, ExternalSourceListNode = MoveTemp(ExternalSourceListNode), Promise = MoveTemp(Promise)]() mutable
  1809. {
  1810. LoadedExternalSourceList.RemoveNode(ExternalSourceListNode, false);
  1811. DEC_DWORD_STAT(STAT_WwiseResourceLoaderExternalSources);
  1812. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1813. {
  1814. Promise.EmplaceValue();
  1815. });
  1816. });
  1817. return Future;
  1818. }
  1819. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::DetachGroupValueNode(FWwiseLoadedGroupValue GroupValueListNode)
  1820. {
  1821. FCompletionPromise Promise;
  1822. auto Future = Promise.GetFuture();
  1823. LoadedListExecutionQueue.Async([this, GroupValueListNode = MoveTemp(GroupValueListNode), Promise = MoveTemp(Promise)]() mutable
  1824. {
  1825. LoadedGroupValueList.RemoveNode(GroupValueListNode, false);
  1826. DEC_DWORD_STAT(STAT_WwiseResourceLoaderGroupValues);
  1827. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1828. {
  1829. Promise.EmplaceValue();
  1830. });
  1831. });
  1832. return Future;
  1833. }
  1834. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::DetachInitBankNode(FWwiseLoadedInitBank InitBankListNode)
  1835. {
  1836. FCompletionPromise Promise;
  1837. auto Future = Promise.GetFuture();
  1838. LoadedListExecutionQueue.Async([this, InitBankListNode = MoveTemp(InitBankListNode), Promise = MoveTemp(Promise)]() mutable
  1839. {
  1840. LoadedInitBankList.RemoveNode(InitBankListNode, false);
  1841. DEC_DWORD_STAT(STAT_WwiseResourceLoaderInitBanks);
  1842. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1843. {
  1844. Promise.EmplaceValue();
  1845. });
  1846. });
  1847. return Future;
  1848. }
  1849. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::DetachMediaNode(FWwiseLoadedMedia MediaListNode)
  1850. {
  1851. FCompletionPromise Promise;
  1852. auto Future = Promise.GetFuture();
  1853. LoadedListExecutionQueue.Async([this, MediaListNode = MoveTemp(MediaListNode), Promise = MoveTemp(Promise)]() mutable
  1854. {
  1855. LoadedMediaList.RemoveNode(MediaListNode, false);
  1856. DEC_DWORD_STAT(STAT_WwiseResourceLoaderMedia);
  1857. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1858. {
  1859. Promise.EmplaceValue();
  1860. });
  1861. });
  1862. return Future;
  1863. }
  1864. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::DetachShareSetNode(FWwiseLoadedShareSet ShareSetListNode)
  1865. {
  1866. FCompletionPromise Promise;
  1867. auto Future = Promise.GetFuture();
  1868. LoadedListExecutionQueue.Async([this, ShareSetListNode = MoveTemp(ShareSetListNode), Promise = MoveTemp(Promise)]() mutable
  1869. {
  1870. LoadedShareSetList.RemoveNode(ShareSetListNode, false);
  1871. DEC_DWORD_STAT(STAT_WwiseResourceLoaderShareSets);
  1872. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1873. {
  1874. Promise.EmplaceValue();
  1875. });
  1876. });
  1877. return Future;
  1878. }
  1879. FWwiseResourceLoaderImpl::FCompletionFuture FWwiseResourceLoaderImpl::DetachSoundBankNode(FWwiseLoadedSoundBank SoundBankListNode)
  1880. {
  1881. FCompletionPromise Promise;
  1882. auto Future = Promise.GetFuture();
  1883. LoadedListExecutionQueue.Async([this, SoundBankListNode = MoveTemp(SoundBankListNode), Promise = MoveTemp(Promise)]() mutable
  1884. {
  1885. LoadedSoundBankList.RemoveNode(SoundBankListNode, false);
  1886. DEC_DWORD_STAT(STAT_WwiseResourceLoaderSoundBanks);
  1887. FFunctionGraphTask::CreateAndDispatchWhenReady([Promise = MoveTemp(Promise)]() mutable
  1888. {
  1889. Promise.EmplaceValue();
  1890. });
  1891. });
  1892. return Future;
  1893. }
  1894. void FWwiseResourceLoaderImpl::AddLoadExternalSourceFutures(FCompletionFutureArray& FutureArray, TArray<const FWwiseExternalSourceCookedData*>& LoadedExternalSources,
  1895. const TArray<FWwiseExternalSourceCookedData>& InExternalSources, const TCHAR* InType, FName InDebugName, uint32 InShortId) const
  1896. {
  1897. for (const auto& ExternalSource : InExternalSources)
  1898. {
  1899. TWwisePromise<void> Promise;
  1900. FutureArray.Add(Promise.GetFuture());
  1901. LoadExternalSourceFile(ExternalSource, [this, &ExternalSource, &LoadedExternalSources, InType, InDebugName, InShortId, Promise = MoveTemp(Promise)](bool bInResult) mutable
  1902. {
  1903. if (UNLIKELY(!bInResult))
  1904. {
  1905. UE_CLOG(InDebugName.IsValid(), LogWwiseResourceLoader, Warning, TEXT("Load%sResources: Could not load External Source %s (%" PRIu32 ") for %s %s (%" PRIu32 ")"),
  1906. InType,
  1907. *ExternalSource.DebugName.ToString(), (uint32)ExternalSource.Cookie,
  1908. InType, *InDebugName.ToString(), (uint32)InShortId);
  1909. UE_CLOG(!InDebugName.IsValid(), LogWwiseResourceLoader, Warning, TEXT("Load%sResources: Could not load External Source %s (%" PRIu32 ") for %s"),
  1910. InType,
  1911. *ExternalSource.DebugName.ToString(), (uint32)ExternalSource.Cookie,
  1912. InType);
  1913. Promise.EmplaceValue();
  1914. }
  1915. else
  1916. {
  1917. FileExecutionQueue.Async([&ExternalSource, &LoadedExternalSources, Promise = MoveTemp(Promise)]() mutable
  1918. {
  1919. LoadedExternalSources.Add(&ExternalSource);
  1920. Promise.EmplaceValue();
  1921. });
  1922. }
  1923. });
  1924. }
  1925. }
  1926. void FWwiseResourceLoaderImpl::AddUnloadExternalSourceFutures(FCompletionFutureArray& FutureArray,
  1927. TArray<const FWwiseExternalSourceCookedData*>& LoadedExternalSources) const
  1928. {
  1929. for (const auto* ExternalSource : LoadedExternalSources)
  1930. {
  1931. TWwisePromise<void> Promise;
  1932. FutureArray.Add(Promise.GetFuture());
  1933. UnloadExternalSourceFile(*ExternalSource, [Promise = MoveTemp(Promise)]() mutable
  1934. {
  1935. Promise.EmplaceValue();
  1936. });
  1937. }
  1938. LoadedExternalSources.Empty();
  1939. }
  1940. void FWwiseResourceLoaderImpl::AddLoadMediaFutures(FCompletionFutureArray& FutureArray, TArray<const FWwiseMediaCookedData*>& LoadedMedia,
  1941. const TArray<FWwiseMediaCookedData>& InMedia, const TCHAR* InType, FName InDebugName, uint32 InShortId) const
  1942. {
  1943. for (const auto& Media : InMedia)
  1944. {
  1945. TWwisePromise<void> Promise;
  1946. FutureArray.Add(Promise.GetFuture());
  1947. LoadMediaFile(Media, [this, &Media, &LoadedMedia, InType, InDebugName, InShortId, Promise = MoveTemp(Promise)](bool bInResult) mutable
  1948. {
  1949. if (UNLIKELY(!bInResult))
  1950. {
  1951. UE_CLOG(InDebugName.IsValid(), LogWwiseResourceLoader, Warning, TEXT("Load%sResources: Could not load Media %s (%" PRIu32 ") for %s %s (%" PRIu32 ")"),
  1952. InType,
  1953. *Media.DebugName.ToString(), (uint32)Media.MediaId,
  1954. InType, *InDebugName.ToString(), (uint32)InShortId);
  1955. UE_CLOG(!InDebugName.IsValid(), LogWwiseResourceLoader, Warning, TEXT("Load%sResources: Could not load Media %s (%" PRIu32 ") for %s"),
  1956. InType,
  1957. *Media.DebugName.ToString(), (uint32)Media.MediaId,
  1958. InType);
  1959. Promise.EmplaceValue();
  1960. }
  1961. else
  1962. {
  1963. FileExecutionQueue.Async([&Media, &LoadedMedia, Promise = MoveTemp(Promise)]() mutable
  1964. {
  1965. LoadedMedia.Add(&Media);
  1966. Promise.EmplaceValue();
  1967. });
  1968. }
  1969. });
  1970. }
  1971. }
  1972. void FWwiseResourceLoaderImpl::AddUnloadMediaFutures(FCompletionFutureArray& FutureArray,
  1973. TArray<const FWwiseMediaCookedData*>& LoadedMedia) const
  1974. {
  1975. for (const auto* Media : LoadedMedia)
  1976. {
  1977. TWwisePromise<void> Promise;
  1978. FutureArray.Add(Promise.GetFuture());
  1979. UnloadMediaFile(*Media, [Promise = MoveTemp(Promise)]() mutable
  1980. {
  1981. Promise.EmplaceValue();
  1982. });
  1983. }
  1984. LoadedMedia.Empty();
  1985. }
  1986. void FWwiseResourceLoaderImpl::AddLoadSoundBankFutures(FCompletionFutureArray& FutureArray, TArray<const FWwiseSoundBankCookedData*>& LoadedSoundBanks,
  1987. const TArray<FWwiseSoundBankCookedData>& InSoundBank, const TCHAR* InType, FName InDebugName, uint32 InShortId) const
  1988. {
  1989. for (const auto& SoundBank : InSoundBank)
  1990. {
  1991. TWwisePromise<void> Promise;
  1992. FutureArray.Add(Promise.GetFuture());
  1993. LoadSoundBankFile(SoundBank, [this, &SoundBank, &LoadedSoundBanks, InType, InDebugName, InShortId, Promise = MoveTemp(Promise)](bool bInResult) mutable
  1994. {
  1995. if (UNLIKELY(!bInResult))
  1996. {
  1997. UE_CLOG(InDebugName.IsValid(), LogWwiseResourceLoader, Warning, TEXT("Load%sResources: Could not load SoundBank %s (%" PRIu32 ") for %s %s (%" PRIu32 ")"),
  1998. InType,
  1999. *SoundBank.DebugName.ToString(), (uint32)SoundBank.SoundBankId,
  2000. InType, *InDebugName.ToString(), (uint32)InShortId);
  2001. UE_CLOG(!InDebugName.IsValid(), LogWwiseResourceLoader, Warning, TEXT("Load%sResources: Could not load SoundBank %s (%" PRIu32 ") for %s"),
  2002. InType,
  2003. *SoundBank.DebugName.ToString(), (uint32)SoundBank.SoundBankId,
  2004. InType);
  2005. Promise.EmplaceValue();
  2006. }
  2007. else
  2008. {
  2009. FileExecutionQueue.Async([&SoundBank, &LoadedSoundBanks, Promise = MoveTemp(Promise)]() mutable
  2010. {
  2011. LoadedSoundBanks.Add(&SoundBank);
  2012. Promise.EmplaceValue();
  2013. });
  2014. }
  2015. });
  2016. }
  2017. }
  2018. void FWwiseResourceLoaderImpl::AddUnloadSoundBankFutures(FCompletionFutureArray& FutureArray,
  2019. TArray<const FWwiseSoundBankCookedData*>& LoadedSoundBanks) const
  2020. {
  2021. for (const auto* SoundBank : LoadedSoundBanks)
  2022. {
  2023. TWwisePromise<void> Promise;
  2024. FutureArray.Add(Promise.GetFuture());
  2025. UnloadSoundBankFile(*SoundBank, [Promise = MoveTemp(Promise)]() mutable
  2026. {
  2027. Promise.EmplaceValue();
  2028. });
  2029. }
  2030. LoadedSoundBanks.Empty();
  2031. }
  2032. void FWwiseResourceLoaderImpl::WaitForFutures(FCompletionFutureArray&& FutureArray, FCompletionCallback&& Callback, int NextId) const
  2033. {
  2034. {
  2035. SCOPED_WWISERESOURCELOADER_EVENT_4(TEXT("WaitForFutures"));
  2036. while (FutureArray.Num() > NextId)
  2037. {
  2038. auto Future = MoveTemp(FutureArray[NextId]);
  2039. if (Future.IsReady())
  2040. {
  2041. ++NextId;
  2042. }
  2043. else
  2044. {
  2045. Future.Next([this, FutureArray = MoveTemp(FutureArray), Callback = MoveTemp(Callback), NextId = NextId + 1](int) mutable
  2046. {
  2047. WaitForFutures(MoveTemp(FutureArray), MoveTemp(Callback), NextId);
  2048. });
  2049. return;
  2050. }
  2051. }
  2052. }
  2053. return Callback();
  2054. }
  2055. void FWwiseResourceLoaderImpl::LoadSoundBankFile(const FWwiseSoundBankCookedData& InSoundBank, FLoadFileCallback&& InCallback) const
  2056. {
  2057. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[LoadSoundBankAsync: %" PRIu32 "] %s at %s"),
  2058. (uint32)InSoundBank.SoundBankId, *InSoundBank.DebugName.ToString(), *InSoundBank.SoundBankPathName.ToString());
  2059. auto* SoundBankManager = IWwiseSoundBankManager::Get();
  2060. if (UNLIKELY(!SoundBankManager))
  2061. {
  2062. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Failed to retrieve SoundBank Manager"));
  2063. InCallback(false);
  2064. return;
  2065. }
  2066. SoundBankManager->LoadSoundBank(InSoundBank, GetUnrealPath(), [&InSoundBank, InCallback = MoveTemp(InCallback)](bool bInResult)
  2067. {
  2068. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[LoadSoundBankAsync: %" PRIu32 "] %s: Done."),
  2069. (uint32)InSoundBank.SoundBankId, *InSoundBank.DebugName.ToString());
  2070. InCallback(bInResult);
  2071. });
  2072. }
  2073. void FWwiseResourceLoaderImpl::UnloadSoundBankFile(const FWwiseSoundBankCookedData& InSoundBank, FUnloadFileCallback&& InCallback) const
  2074. {
  2075. auto Path = GetUnrealPath(InSoundBank.SoundBankPathName);
  2076. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[UnloadSoundBankAsync: %" PRIu32 "] %s at %s"),
  2077. (uint32)InSoundBank.SoundBankId, *InSoundBank.DebugName.ToString(), *InSoundBank.SoundBankPathName.ToString());
  2078. auto* SoundBankManager = IWwiseSoundBankManager::Get();
  2079. if (UNLIKELY(!SoundBankManager))
  2080. {
  2081. UE_CLOG(!IsEngineExitRequested(), LogWwiseResourceLoader, Error, TEXT("Failed to retrieve SoundBank Manager"));
  2082. InCallback();
  2083. return;
  2084. }
  2085. SoundBankManager->UnloadSoundBank(InSoundBank, GetUnrealPath(), [&InSoundBank, InCallback = MoveTemp(InCallback)]()
  2086. {
  2087. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[UnloadSoundBankAsync: %" PRIu32 "] %s: Done."),
  2088. (uint32)InSoundBank.SoundBankId, *InSoundBank.DebugName.ToString());
  2089. InCallback();
  2090. });
  2091. }
  2092. void FWwiseResourceLoaderImpl::LoadMediaFile(const FWwiseMediaCookedData& InMedia, FLoadFileCallback&& InCallback) const
  2093. {
  2094. auto Path = GetUnrealPath(InMedia.MediaPathName);
  2095. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[LoadMediaAsync: %" PRIu32 "] %s at %s"),
  2096. (uint32)InMedia.MediaId, *InMedia.DebugName.ToString(), *InMedia.MediaPathName.ToString());
  2097. auto* MediaManager = IWwiseMediaManager::Get();
  2098. if (UNLIKELY(!MediaManager))
  2099. {
  2100. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Failed to retrieve Media Manager"));
  2101. InCallback(false);
  2102. return;
  2103. }
  2104. MediaManager->LoadMedia(InMedia, GetUnrealPath(), [&InMedia, InCallback = MoveTemp(InCallback)](bool bInResult)
  2105. {
  2106. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[LoadMediaAsync: %" PRIu32 "] %s: Done."),
  2107. (uint32)InMedia.MediaId, *InMedia.DebugName.ToString());
  2108. InCallback(bInResult);
  2109. });
  2110. }
  2111. void FWwiseResourceLoaderImpl::UnloadMediaFile(const FWwiseMediaCookedData& InMedia, FUnloadFileCallback&& InCallback) const
  2112. {
  2113. auto Path = GetUnrealPath(InMedia.MediaPathName);
  2114. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[UnloadMediaAsync: %" PRIu32 "] %s at %s"),
  2115. (uint32)InMedia.MediaId, *InMedia.DebugName.ToString(), *InMedia.MediaPathName.ToString());
  2116. auto* MediaManager = IWwiseMediaManager::Get();
  2117. if (UNLIKELY(!MediaManager))
  2118. {
  2119. UE_CLOG(!IsEngineExitRequested(), LogWwiseResourceLoader, Error, TEXT("Failed to retrieve Media Manager"));
  2120. InCallback();
  2121. return;
  2122. }
  2123. MediaManager->UnloadMedia(InMedia, GetUnrealPath(), [&InMedia, InCallback = MoveTemp(InCallback)]()
  2124. {
  2125. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[UnloadMediaAsync: %" PRIu32 "] %s: Done."),
  2126. (uint32)InMedia.MediaId, *InMedia.DebugName.ToString());
  2127. InCallback();
  2128. });
  2129. }
  2130. void FWwiseResourceLoaderImpl::LoadExternalSourceFile(const FWwiseExternalSourceCookedData& InExternalSource, FLoadFileCallback&& InCallback) const
  2131. {
  2132. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[LoadExternalSourceAsync: %" PRIu32 "] %s"),
  2133. (uint32)InExternalSource.Cookie, *InExternalSource.DebugName.ToString());
  2134. auto* ExternalSourceManager = IWwiseExternalSourceManager::Get();
  2135. if (UNLIKELY(!ExternalSourceManager))
  2136. {
  2137. UE_LOG(LogWwiseResourceLoader, Error, TEXT("Failed to retrieve External Source Manager"));
  2138. InCallback(false);
  2139. return;
  2140. }
  2141. ExternalSourceManager->LoadExternalSource(InExternalSource, GetUnrealExternalSourcePath(), CurrentLanguage, [&InExternalSource, InCallback = MoveTemp(InCallback)](bool bInResult)
  2142. {
  2143. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[LoadExternalSourceAsync: %" PRIu32 "] %s: Done."),
  2144. (uint32)InExternalSource.Cookie, *InExternalSource.DebugName.ToString());
  2145. InCallback(bInResult);
  2146. });
  2147. }
  2148. void FWwiseResourceLoaderImpl::UnloadExternalSourceFile(const FWwiseExternalSourceCookedData& InExternalSource, FUnloadFileCallback&& InCallback) const
  2149. {
  2150. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[UnloadExternalSourceAsync: %" PRIu32 "] %s"),
  2151. (uint32)InExternalSource.Cookie, *InExternalSource.DebugName.ToString());
  2152. auto* ExternalSourceManager = IWwiseExternalSourceManager::Get();
  2153. if (UNLIKELY(!ExternalSourceManager))
  2154. {
  2155. UE_CLOG(!IsEngineExitRequested(), LogWwiseResourceLoader, Error, TEXT("Failed to retrieve External Source Manager"));
  2156. InCallback();
  2157. return;
  2158. }
  2159. ExternalSourceManager->UnloadExternalSource(InExternalSource, GetUnrealExternalSourcePath(), CurrentLanguage, [&InExternalSource, InCallback = MoveTemp(InCallback)]()
  2160. {
  2161. UE_LOG(LogWwiseResourceLoader, VeryVerbose, TEXT("[UnloadExternalSourceAsync: %" PRIu32 "] %s: Done."),
  2162. (uint32)InExternalSource.Cookie, *InExternalSource.DebugName.ToString());
  2163. InCallback();
  2164. });
  2165. }