WwiseDirectoryVisitor.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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/WwiseDirectoryVisitor.h"
  16. #include "WwiseUnrealHelper.h"
  17. #include "Wwise/Metadata/WwiseMetadataRootFile.h"
  18. #include "Wwise/Metadata/WwiseMetadataProjectInfo.h"
  19. #include "Wwise/Metadata/WwiseMetadataPlatform.h"
  20. #include "Wwise/Metadata/WwiseMetadataLanguage.h"
  21. #include "Wwise/Stats/ProjectDatabase.h"
  22. #include "Async/Async.h"
  23. #include "Misc/Paths.h"
  24. //
  25. // FPlatformRootDirectoryVisitor
  26. //
  27. class FWwiseDirectoryVisitor::FPlatformRootDirectoryVisitor : public IPlatformFile::FDirectoryVisitor, public FWwiseDirectoryVisitor::IGettableVisitor
  28. {
  29. public:
  30. FPlatformRootDirectoryVisitor(
  31. const FWwiseSharedPlatformId& InPlatform,
  32. IPlatformFile& InFileInterface) :
  33. Platform(InPlatform),
  34. FileInterface(InFileInterface)
  35. {}
  36. bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) override;
  37. bool StartJobIfValid();
  38. FWwiseGeneratedFiles::FPlatformFiles& Get() override;
  39. const FWwiseSharedPlatformId Platform;
  40. IPlatformFile& FileInterface;
  41. FWwiseGeneratedFiles::FPlatformFiles PlatformFiles;
  42. TArray<TFuture<FWwiseDirectoryVisitor::IGettableVisitor*>> Futures;
  43. };
  44. //
  45. // FSoundBankVisitor
  46. //
  47. class FWwiseDirectoryVisitor::FSoundBankVisitor : public IPlatformFile::FDirectoryVisitor, public FWwiseDirectoryVisitor::IGettableVisitor
  48. {
  49. public:
  50. FSoundBankVisitor(IPlatformFile& InFileInterface) :
  51. FileInterface(InFileInterface)
  52. {}
  53. virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory);
  54. FWwiseGeneratedFiles::FPlatformFiles& Get() override;
  55. IPlatformFile& FileInterface;
  56. FWwiseGeneratedFiles::FPlatformFiles Result;
  57. };
  58. //
  59. // FMediaVisitor
  60. //
  61. class FWwiseDirectoryVisitor::FMediaVisitor : public IPlatformFile::FDirectoryVisitor, public FWwiseDirectoryVisitor::IGettableVisitor
  62. {
  63. public:
  64. FMediaVisitor(IPlatformFile& InFileInterface) :
  65. FileInterface(InFileInterface)
  66. {}
  67. virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory);
  68. FWwiseGeneratedFiles::FPlatformFiles& Get() override;
  69. IPlatformFile& FileInterface;
  70. FWwiseGeneratedFiles::FPlatformFiles Result;
  71. };
  72. //
  73. // FWwiseDirectoryVisitor
  74. //
  75. bool FWwiseDirectoryVisitor::Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory)
  76. {
  77. SCOPED_WWISEPROJECTDATABASE_EVENT_2(TEXT("FWwiseDirectoryVisitor::Visit"));
  78. // make sure all paths are "standardized" so the other end can match up with it's own standardized paths
  79. FString RelativeFilename = FilenameOrDirectory;
  80. FPaths::MakeStandardFilename(RelativeFilename);
  81. const auto Filename = FPaths::GetCleanFilename(RelativeFilename);
  82. if (Filename.StartsWith(TEXT(".")))
  83. {
  84. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("[WwiseDirectoryVisitor] Skipping: %s"), *RelativeFilename);
  85. return true;
  86. }
  87. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("[WwiseDirectoryVisitor] Visiting %s"), *RelativeFilename);
  88. if (bIsDirectory)
  89. {
  90. // Skip directories, they are to be processed by ProjectInfo.json's Path
  91. return true;
  92. }
  93. FWwiseGeneratedFiles::FileTuple FileToAdd(RelativeFilename, FileInterface.GetTimeStamp(FilenameOrDirectory));
  94. const auto Extension = FPaths::GetExtension(RelativeFilename);
  95. if (Filename.Equals(TEXT("ProjectInfo.json"), ESearchCase::IgnoreCase))
  96. {
  97. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Found ProjectInfo: %s"), *RelativeFilename);
  98. // We need to retrieve the Path from ProjectInfo. Parse this file immediately
  99. // (will be parsed twice. Now once, and officially later - since the file is small, it's not a big worry)
  100. auto Root = FWwiseMetadataRootFile::LoadFile(RelativeFilename);
  101. if (!Root || !Root->ProjectInfo)
  102. {
  103. UE_LOG(LogWwiseProjectDatabase, Error, TEXT("Could not read ProjectInfo to retrieve paths."), *RelativeFilename);
  104. return true;
  105. }
  106. GeneratedDirectory.ProjectInfo = Root;
  107. const auto Path = FPaths::GetPath(FilenameOrDirectory);
  108. auto& Platforms = Root->ProjectInfo->Platforms;
  109. bool bFoundPlatform = false;
  110. if (!PlatformName)
  111. {
  112. UE_LOG(LogWwiseProjectDatabase, Log, TEXT("Skipping loading all platforms"));
  113. }
  114. else
  115. {
  116. for (auto& Platform : Platforms)
  117. {
  118. if (PlatformName->ToString().Equals(Platform.Name.ToString(), ESearchCase::IgnoreCase))
  119. {
  120. bFoundPlatform = true;
  121. break;
  122. }
  123. }
  124. UE_CLOG(UNLIKELY(!bFoundPlatform), LogWwiseProjectDatabase, Log, TEXT("Requested platform not found: %s"), *PlatformName->ToString());
  125. }
  126. if (bFoundPlatform)
  127. {
  128. for (auto& Platform : Platforms)
  129. {
  130. const auto PlatformPath = Path / Platform.Path.ToString();
  131. if (!PlatformName->ToString().Equals(Platform.Name.ToString(), ESearchCase::IgnoreCase))
  132. {
  133. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Skipping platform %s"), *Platform.Name.ToString());
  134. continue;
  135. }
  136. if (PlatformGuid && *PlatformGuid != Platform.BasePlatformGUID)
  137. {
  138. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Skipping platform %s (Base %s)"), *Platform.Name.ToString(), *Platform.BasePlatform.ToString());
  139. continue;
  140. }
  141. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Visiting platform %s at: %s"), *Platform.Name.ToString(), *Platform.Path.ToString());
  142. FWwisePlatformId CurrentPlatform;
  143. CurrentPlatform.PlatformGuid = Platform.GUID;
  144. CurrentPlatform.PlatformName = Platform.Name;
  145. FString RelativePlatformPath(PlatformPath);
  146. FPaths::MakePathRelativeTo(RelativePlatformPath, *WwiseUnrealHelper::GetSoundBankDirectory());
  147. CurrentPlatform.PathRelativeToGeneratedSoundBanks = FName(RelativePlatformPath);
  148. FWwiseSharedPlatformId PlatformRef;
  149. PlatformRef.Platform = MakeShared<FWwisePlatformId, ESPMode::ThreadSafe>(CurrentPlatform);
  150. Futures.Add(Async(EAsyncExecution::TaskGraph, [this, PlatformRef, PlatformPath] {
  151. auto* RootVisitor = new FPlatformRootDirectoryVisitor(PlatformRef, FileInterface);
  152. if (!FileInterface.IterateDirectory(*PlatformPath, *RootVisitor) ||
  153. !RootVisitor->StartJobIfValid())
  154. {
  155. UE_LOG(LogWwiseProjectDatabase, Warning, TEXT("Could not find generated platform %s at: %s"), *PlatformRef.GetPlatformName().ToString(), *PlatformRef.Platform->PathRelativeToGeneratedSoundBanks.ToString());
  156. delete RootVisitor;
  157. RootVisitor = nullptr;
  158. }
  159. return RootVisitor;
  160. }));
  161. }
  162. }
  163. GeneratedDirectory.GeneratedRootFiles.ProjectInfoFile = MoveTemp(FileToAdd);
  164. }
  165. else if (Filename.Equals(TEXT("Wwise_IDs.h"), ESearchCase::IgnoreCase))
  166. {
  167. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Found Wwise IDs: %s"), *RelativeFilename);
  168. GeneratedDirectory.GeneratedRootFiles.WwiseIDsFile = MoveTemp(FileToAdd);
  169. }
  170. else if (Filename.Equals(TEXT("SoundBanksGeneration.log"), ESearchCase::IgnoreCase)
  171. || Extension.Equals(TEXT("xml"), ESearchCase::IgnoreCase))
  172. {
  173. // Nothing to do
  174. }
  175. else
  176. {
  177. UE_LOG(LogWwiseProjectDatabase, Log, TEXT("Unknown file. Not in a platform. Will be ignored: %s"), *RelativeFilename);
  178. }
  179. return true;
  180. }
  181. FWwiseGeneratedFiles& FWwiseDirectoryVisitor::Get()
  182. {
  183. SCOPED_WWISEPROJECTDATABASE_EVENT_4(TEXT("FWwiseDirectoryVisitor::Get"));
  184. for (const auto& Future : Futures)
  185. {
  186. auto* Result = Future.Get();
  187. if (Result)
  188. {
  189. auto& PlatformFiles = Result->Get();
  190. if (PlatformFiles.IsValid())
  191. {
  192. GeneratedDirectory.Platforms.Add(Result->Platform, PlatformFiles);
  193. }
  194. delete Result;
  195. }
  196. }
  197. Futures.Empty();
  198. return GeneratedDirectory;
  199. }
  200. //
  201. // FPlatformRootDirectoryVisitor
  202. //
  203. bool FWwiseDirectoryVisitor::FPlatformRootDirectoryVisitor::Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory)
  204. {
  205. SCOPED_WWISEPROJECTDATABASE_EVENT_2(TEXT("FPlatformRootDirectoryVisitor::Visit"));
  206. // make sure all paths are "standardized" so the other end can match up with it's own standardized paths
  207. FString RelativeFilename = FilenameOrDirectory;
  208. FPaths::MakeStandardFilename(RelativeFilename);
  209. const auto Filename = FPaths::GetCleanFilename(RelativeFilename);
  210. if (Filename.StartsWith(TEXT(".")))
  211. {
  212. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("[RootFilesVisitor] Skipping: %s"), *RelativeFilename);
  213. return true;
  214. }
  215. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("[RootFilesVisitor] Visiting %s"), *RelativeFilename);
  216. if (bIsDirectory)
  217. {
  218. PlatformFiles.DirectoriesToWatch.Add(RelativeFilename);
  219. if (Filename.Equals(TEXT("Media"), ESearchCase::IgnoreCase))
  220. {
  221. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Found media directory: %s"), *RelativeFilename);
  222. PlatformFiles.MediaDirectory = FilenameOrDirectory;
  223. }
  224. else if (Filename.Equals(TEXT("Bus"), ESearchCase::IgnoreCase)
  225. || Filename.Equals(TEXT("Event"), ESearchCase::IgnoreCase))
  226. {
  227. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Found auto SoundBank directory: %s"), *RelativeFilename);
  228. PlatformFiles.AutoSoundBankDirectories.Add(FilenameOrDirectory);
  229. }
  230. else {
  231. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Found language directory: %s"), *RelativeFilename);
  232. PlatformFiles.LanguageDirectories.Add(FilenameOrDirectory);
  233. }
  234. return true;
  235. }
  236. FWwiseGeneratedFiles::FileTuple FileToAdd(RelativeFilename, FileInterface.GetTimeStamp(FilenameOrDirectory));
  237. const auto Extension = FPaths::GetExtension(RelativeFilename);
  238. if (!Extension.Equals(TEXT("json"), ESearchCase::IgnoreCase)
  239. && !Extension.Equals(TEXT("txt"), ESearchCase::IgnoreCase)
  240. && !Extension.Equals(TEXT("bnk"), ESearchCase::IgnoreCase)
  241. && !Extension.Equals(TEXT("xml"), ESearchCase::IgnoreCase))
  242. {
  243. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Adding extra file: %s"), *RelativeFilename);
  244. PlatformFiles.ExtraFiles.Add(MoveTemp(FileToAdd));
  245. return true;
  246. }
  247. if (Extension.Equals(TEXT("bnk"), ESearchCase::IgnoreCase))
  248. {
  249. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Adding SoundBank file: %s"), *RelativeFilename);
  250. PlatformFiles.SoundBankFiles.Add(MoveTemp(FileToAdd));
  251. return true;
  252. }
  253. else if (Extension.Equals(TEXT("xml"), ESearchCase::IgnoreCase)
  254. || Extension.Equals(TEXT("txt"), ESearchCase::IgnoreCase))
  255. {
  256. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Skipping file: %s"), *RelativeFilename);
  257. return true;
  258. }
  259. else if (Filename.Equals(TEXT("SoundbanksInfo.json"), ESearchCase::IgnoreCase))
  260. {
  261. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Found monolithic SoundBank info: %s"), *RelativeFilename);
  262. PlatformFiles.SoundbanksInfoFile = MoveTemp(FileToAdd);
  263. }
  264. else if (Filename.Equals(TEXT("PlatformInfo.json"), ESearchCase::IgnoreCase))
  265. {
  266. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Found platform info: %s"), *RelativeFilename);
  267. PlatformFiles.PlatformInfoFile = MoveTemp(FileToAdd);
  268. }
  269. else if (Filename.Equals(TEXT("PluginInfo.json"), ESearchCase::IgnoreCase))
  270. {
  271. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Found plugin info: %s"), *RelativeFilename);
  272. PlatformFiles.PluginInfoFile = MoveTemp(FileToAdd);
  273. }
  274. else
  275. {
  276. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Adding metadata file: %s"), *RelativeFilename);
  277. PlatformFiles.MetadataFiles.Add(MoveTemp(FileToAdd));
  278. }
  279. return true;
  280. }
  281. bool FWwiseDirectoryVisitor::FPlatformRootDirectoryVisitor::StartJobIfValid()
  282. {
  283. if (!PlatformFiles.IsValid())
  284. {
  285. return false;
  286. }
  287. if (!PlatformFiles.MediaDirectory.IsEmpty())
  288. {
  289. const auto& Elem = PlatformFiles.MediaDirectory;
  290. Futures.Add(Async(EAsyncExecution::TaskGraph, [this, Elem] {
  291. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Visiting media directory: %s"), *Elem);
  292. auto* MediaVisitor = new FMediaVisitor(FileInterface);
  293. FileInterface.IterateDirectory(*Elem, *MediaVisitor);
  294. return static_cast<FWwiseDirectoryVisitor::IGettableVisitor*>(MediaVisitor);
  295. }));
  296. }
  297. for (const auto& Elem : PlatformFiles.AutoSoundBankDirectories)
  298. {
  299. Futures.Add(Async(EAsyncExecution::TaskGraph, [this, Elem] {
  300. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Visiting auto SoundBank directory: %s"), *Elem);
  301. auto* SoundBankVisitor = new FSoundBankVisitor(FileInterface);
  302. FileInterface.IterateDirectory(*Elem, *SoundBankVisitor);
  303. return static_cast<FWwiseDirectoryVisitor::IGettableVisitor*>(SoundBankVisitor);
  304. }));
  305. }
  306. for (const auto& Elem : PlatformFiles.LanguageDirectories)
  307. {
  308. Futures.Add(Async(EAsyncExecution::TaskGraph, [this, Elem] {
  309. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("Visiting language directory: %s"), *Elem);
  310. auto* SoundBankVisitor = new FSoundBankVisitor(FileInterface);
  311. FileInterface.IterateDirectory(*Elem, *SoundBankVisitor);
  312. return static_cast<FWwiseDirectoryVisitor::IGettableVisitor*>(SoundBankVisitor);
  313. }));
  314. }
  315. return true;
  316. }
  317. FWwiseGeneratedFiles::FPlatformFiles& FWwiseDirectoryVisitor::FPlatformRootDirectoryVisitor::Get()
  318. {
  319. SCOPED_WWISEPROJECTDATABASE_EVENT_4(TEXT("FPlatformRootDirectoryVisitor::Get"));
  320. for (const auto& Future : Futures)
  321. {
  322. auto* Result = Future.Get();
  323. if (Result)
  324. {
  325. PlatformFiles.Append(MoveTemp(Result->Get()));
  326. delete Result;
  327. }
  328. }
  329. Futures.Empty();
  330. return PlatformFiles;
  331. }
  332. //
  333. // FSoundBankVisitor
  334. //
  335. bool FWwiseDirectoryVisitor::FSoundBankVisitor::Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory)
  336. {
  337. // make sure all paths are "standardized" so the other end can match up with it's own standardized paths
  338. FString RelativeFilename = FilenameOrDirectory;
  339. FPaths::MakeStandardFilename(RelativeFilename);
  340. const auto Filename = FPaths::GetCleanFilename(RelativeFilename);
  341. const auto Extension = FPaths::GetExtension(RelativeFilename);
  342. if (Filename.StartsWith(TEXT(".")))
  343. {
  344. UE_LOG(LogWwiseProjectDatabase, Verbose, TEXT("[SoundBankVisitor] Skipping: %s"), *RelativeFilename);
  345. return true;
  346. }
  347. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("[SoundBankVisitor] Visiting %s"), *RelativeFilename);
  348. if (bIsDirectory)
  349. {
  350. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Iterating folder: %s"), *RelativeFilename);
  351. Result.DirectoriesToWatch.Add(RelativeFilename);
  352. FileInterface.IterateDirectory(FilenameOrDirectory, *this);
  353. return true;
  354. }
  355. FWwiseGeneratedFiles::FileTuple FileToAdd(RelativeFilename, FileInterface.GetTimeStamp(FilenameOrDirectory));
  356. if (Extension.Equals(TEXT("json"), ESearchCase::IgnoreCase))
  357. {
  358. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Adding metadata file: %s"), *RelativeFilename);
  359. Result.MetadataFiles.Add(MoveTemp(FileToAdd));
  360. return true;
  361. }
  362. else if (Extension.Equals(TEXT("bnk"), ESearchCase::IgnoreCase))
  363. {
  364. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Adding SoundBank file: %s"), *RelativeFilename);
  365. Result.SoundBankFiles.Add(MoveTemp(FileToAdd));
  366. return true;
  367. }
  368. else if (Extension.Equals(TEXT("xml"), ESearchCase::IgnoreCase)
  369. || Extension.Equals(TEXT("txt"), ESearchCase::IgnoreCase))
  370. {
  371. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Skipping file: %s"), *RelativeFilename);
  372. return true;
  373. }
  374. else
  375. {
  376. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Adding extra file: %s"), *RelativeFilename);
  377. Result.ExtraFiles.Add(MoveTemp(FileToAdd));
  378. return true;
  379. }
  380. }
  381. FWwiseGeneratedFiles::FPlatformFiles& FWwiseDirectoryVisitor::FSoundBankVisitor::Get()
  382. {
  383. return Result;
  384. }
  385. //
  386. // FMediaVisitor
  387. //
  388. bool FWwiseDirectoryVisitor::FMediaVisitor::Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory)
  389. {
  390. // make sure all paths are "standardized" so the other end can match up with it's own standardized paths
  391. FString RelativeFilename = FilenameOrDirectory;
  392. FPaths::MakeStandardFilename(RelativeFilename);
  393. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("[MediaVisitor] Visiting %s"), *RelativeFilename);
  394. if (bIsDirectory)
  395. {
  396. Result.DirectoriesToWatch.Add(RelativeFilename);
  397. FileInterface.IterateDirectory(FilenameOrDirectory, *this);
  398. }
  399. else
  400. {
  401. FWwiseGeneratedFiles::FileTuple FileToAdd(RelativeFilename, FileInterface.GetTimeStamp(FilenameOrDirectory));
  402. const auto Extension = FPaths::GetExtension(RelativeFilename);
  403. if (Extension.Equals(TEXT("wem"), ESearchCase::IgnoreCase))
  404. {
  405. UE_LOG(LogWwiseProjectDatabase, VeryVerbose, TEXT("Adding media file: %s"), *RelativeFilename);
  406. Result.MediaFiles.Add(MoveTemp(FileToAdd));
  407. }
  408. else
  409. {
  410. UE_LOG(LogWwiseProjectDatabase, Log, TEXT("Adding unexpected extra file: %s"), *RelativeFilename);
  411. Result.ExtraFiles.Add(MoveTemp(FileToAdd));
  412. }
  413. }
  414. return true;
  415. }
  416. FWwiseGeneratedFiles::FPlatformFiles& FWwiseDirectoryVisitor::FMediaVisitor::Get()
  417. {
  418. return Result;
  419. }