ExtAssetData.h 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734
  1. // Copyright 2017-2021 marynate. All Rights Reserved.
  2. #pragma once
  3. #include "ExtContentBrowser.h"
  4. #include "ExtContentBrowserTypes.h"
  5. #include "CoreMinimal.h"
  6. #include "UObject/ObjectMacros.h"
  7. #include "UObject/LinkerLoad.h"
  8. #include "AssetRegistry/AssetData.h"
  9. #include "AssetRegistry/AssetDataTagMap.h"
  10. #include "EditorFramework/AssetImportData.h"
  11. #include "Misc/AssetRegistryInterface.h"
  12. #include "HAL/Runnable.h"
  13. #include "ExtFeedbackContextEditor.h"
  14. #include "HAL/FeedbackContextAnsi.h"
  15. #include "Serialization/BufferArchive.h"
  16. #include "ExtAssetData.generated.h"
  17. struct FExtAssetIdentifier;
  18. struct FARFilter;
  19. struct FExtAssetDependencyNode;
  20. struct FExtAssetDependencyWalker;
  21. /**
  22. *
  23. */
  24. struct FExtAssetRegistryVersion
  25. {
  26. enum Type
  27. {
  28. // Before any version changes were made
  29. BeforeCustomVersionWasAdded = 0,
  30. SaveLoadNameBatch, // 4.27+
  31. // -----<new versions can be added above this line>-------------------------------------------------
  32. VersionPlusOne,
  33. LatestVersion = VersionPlusOne - 1
  34. };
  35. // The GUID for this custom version number
  36. const static FGuid GUID;
  37. /** Read/write the custom version to the archive, should call at the very beginning */
  38. static bool SerializeVersion(FArchive& Ar, FExtAssetRegistryVersion::Type& Version);
  39. private:
  40. FExtAssetRegistryVersion() {}
  41. };
  42. /**
  43. * Holds info of supported asset type/extensions
  44. */
  45. struct FExtAssetSupport
  46. {
  47. static FString AssetPackageExtension;
  48. static FString MapPackageExtension;
  49. static FString TextAssetPackageExtension;
  50. static FString TextMapPackageExtension;
  51. static FORCEINLINE bool IsSupportedPackageFilename(const FString& Filename)
  52. {
  53. const bool bShouldSupportMapPackage = true;
  54. const bool bIsAssetPackage = Filename.EndsWith(FExtAssetSupport::AssetPackageExtension);
  55. const bool bIsMapMapPackage = Filename.EndsWith(FExtAssetSupport::MapPackageExtension);
  56. return bShouldSupportMapPackage ? (bIsAssetPackage || bIsMapMapPackage) : bIsAssetPackage;
  57. }
  58. };
  59. /**
  60. * Holds Constants used in ExtAsstData
  61. */
  62. namespace FExtAssetContants
  63. {
  64. const FString ExtTempPackagePath(TEXT("/Temp/UAssetBrowser"));
  65. const FString ExtSandboxPackagePath(TEXT("/UAssetBrowser/Sandbox"));
  66. const FName DefaultImportedUAssetCollectionName(TEXT("ImportedUAssets"));
  67. };
  68. #if ECB_WIP_ASSETREGISTRY_SERIALIZATION
  69. /** Version used for serializing ext asset registry caches */
  70. struct ASSETREGISTRY_API FExtAssetRegistryVersion
  71. {
  72. enum Type
  73. {
  74. PreVersioning = 0, // From before file versioning was implemented
  75. // -----<new versions can be added above this line>-------------------------------------------------
  76. VersionPlusOne,
  77. LatestVersion = VersionPlusOne - 1
  78. };
  79. /** The GUID for this custom version number */
  80. const static FGuid GUID;
  81. /** Read/write the custom version to the archive, should call at the very beginning */
  82. static bool SerializeVersion(FArchive& Ar, FAssetRegistryVersion::Type& Version);
  83. private:
  84. FExtAssetRegistryVersion() {}
  85. };
  86. #endif
  87. /**
  88. * A struct to hold external asset information
  89. */
  90. USTRUCT(BlueprintType)
  91. struct FExtAssetData
  92. {
  93. GENERATED_BODY()
  94. public:
  95. enum class EInvalidReason :uint8
  96. {
  97. NotParsed,
  98. Valid,
  99. // File Path
  100. FileNotFound,
  101. FilePathEmptyOrInvalid,
  102. FilePathContainsInvalidCharacter,
  103. // From LinkerLoad
  104. FailedToLoadPackage,
  105. // From Package Reader
  106. PackageFileVersionEmptyOrTooOld,
  107. PackageFileOrCustomVersionTooNew,
  108. PackageFileMalformed,
  109. PackageFileCustomVersionMissing,
  110. PackageFileFailedToLoad,
  111. // Basic info
  112. NoAssetData,
  113. AssetNameEmpty,
  114. ClassNameEmpty,
  115. // Not Supported Type
  116. GenericAssetTypeNotSupported,
  117. RedirectorNotSupported,
  118. ClassAssetNotSupported,
  119. TextForamtNotSupported,
  120. CookedPackageNotSupported,
  121. NotCompatiableWithCurrentEngineVersion,
  122. Unknown
  123. };
  124. enum class EContentType :uint8
  125. {
  126. Plugin,
  127. Project,
  128. VaultCache,
  129. Orphan,
  130. PartialProject,
  131. Unknown
  132. };
  133. public:
  134. /** Full file path to package disk file */
  135. UPROPERTY(BlueprintReadOnly, Category = AssetData, transient)
  136. FName PackageFilePath;
  137. /** The name of the package in which the asset is found, this is the full long package name such as /Game/Path/Package */
  138. UPROPERTY(BlueprintReadOnly, Category = AssetData, transient)
  139. FName PackageName;
  140. /** The path to the package in which the asset is found, this is /Game/Path with the Package stripped off */
  141. UPROPERTY(BlueprintReadOnly, Category = AssetData, transient)
  142. FName PackagePath;
  143. /** The object path for the asset in the form PackageName.AssetName. e.g. /Game/Path/Package.AssetName */
  144. UPROPERTY(BlueprintReadOnly, Category = AssetData, transient)
  145. FName ObjectPath;
  146. /** The name of the asset without the package */
  147. UPROPERTY(BlueprintReadOnly, Category = AssetData, transient)
  148. FName AssetName;
  149. /** The name of the asset's class */
  150. UPROPERTY(BlueprintReadOnly, Category = AssetData, transient)
  151. FName AssetClass;
  152. /** Asset data to satisfy FAssetData based interface. */
  153. UPROPERTY(BlueprintReadOnly, Category = AssetData, transient)
  154. FAssetData AssetData;
  155. // Content root of current asset
  156. FName AssetContentRoot = NAME_None;
  157. // Content root folder name, can get from AssetContentRootDir but cache here for performance
  158. //FName AssetContentRootDirName = NAME_None;
  159. // Relative path to asset content root
  160. FName AssetRelativePath = NAME_None;
  161. // Asset content type: plugin/project/vaultcahce/orphan
  162. EContentType AssetContentType;
  163. /** Asset registry tags */
  164. FAssetDataTagMapSharedView TagsAndValues;
  165. /** Hard Dependencies */
  166. TSet<FName> HardDependentPackages;
  167. /** Soft References */
  168. TSet<FName> SoftReferencesList;
  169. /** UE4 file version */
  170. int32 FileVersionUE4 = 0;
  171. /** Engine version this package was saved with.*/
  172. FEngineVersion SavedByEngineVersion;
  173. /** Engine version this package is compatible with. See SavedByEngineVersion. */
  174. FEngineVersion CompatibleWithEngineVersion;
  175. /** Gathered invalid reason */
  176. EInvalidReason InvalidReason;
  177. #if 1 //ECB_DEBUG
  178. int32 AssetCount = 0;
  179. int32 ThumbCount = 0;
  180. int64 FileSize = 0;
  181. #endif
  182. public:
  183. /** Default Constructor. */
  184. FExtAssetData();
  185. /** Constructor taking a package file path. */
  186. FExtAssetData(const FString& InPackageFilePath, bool bDelayParse = false);
  187. /** Constructor taking a UObject. By default trying to create one for a blueprint class will create one for the UBlueprint instead, but this can be overridden */
  188. FExtAssetData(const UObject* InAsset, bool bAllowBlueprintClass = false);
  189. /** Constructor taking a package name. For support wrapping an internal package */
  190. FExtAssetData(const FName& InPackageName);
  191. /** Parse .uasset file to gather asset data, assume package file path has been assigned in constructor */
  192. bool Parse();
  193. bool ReParse();
  194. /** Check if has thumbnail data. */
  195. bool HasThumbnail() const;
  196. void SetHasThumbnail(bool bInHasThumbnail)
  197. {
  198. bHasThumbnail = bInHasThumbnail;
  199. }
  200. /** Check if asset has valid content root (project or vault cache data folder) */
  201. bool HasContentRoot() const;
  202. /** Load and check if has valid thumbnail data. */
  203. bool HasValidThumbnail() const;
  204. /** Check if can import this asset in fastest way */
  205. bool CanImportFast() const;
  206. /** Load thumbnail from package. */
  207. bool LoadThumbnail(FObjectThumbnail& OutThumbnail) const;
  208. #if ECB_LEGACY
  209. /** Load soft package references from package. */
  210. void LoadSoftReferences(TArray<FName>& OutSoftReferences) const;
  211. #endif
  212. /** Get saved engine version string */
  213. FString GetSavedEngineVersionForDisplay() const;
  214. const FString& GetAssetContentTypeForDisplay() const;
  215. /** Checks compatibility with current engine version. */
  216. bool IsCompatibleWithCurrentEngineVersion() const;
  217. FString GetInvalidReason() const;
  218. public: // AssetData compatible interface
  219. /** Prints the details of the asset to the log */
  220. void PrintAssetData() const;
  221. /** Check if is parsed and has valid asset name */
  222. bool IsValid() const
  223. {
  224. return bParsed && bValid;//&& AssetName != NAME_None;
  225. }
  226. bool IsUAsset() const;
  227. /**
  228. * Returns true iff the Asset is a TopLevelAsset (not a subobject, its outer is a UPackage).
  229. * Only TopLevelAssets can be PrimaryAssets in the AssetManager.
  230. * A TopLevelAsset is not necessarily the main asset in a package; see IsUAsset.
  231. * Note that this is distinct from UObject::IsAsset because IsAsset can be overloaded (see e.g. AActor::IsAsset)
  232. */
  233. bool IsTopLevelAsset() const;
  234. bool IsUMap() const;
  235. /** Check if is parsed and has valid asset name */
  236. bool IsParsed() const
  237. {
  238. return bParsed;
  239. }
  240. /** Returns true if the asset is loaded */
  241. bool IsAssetLoaded() const
  242. {
  243. return IsValid() && FindObjectSafe<UObject>(NULL, *ObjectPath.ToString()) != NULL;
  244. }
  245. /** Try and get the value associated with the given tag as a type converted value */
  246. template <typename ValueType>
  247. bool GetTagValue(const FName InTagName, ValueType& OutTagValue) const;
  248. UClass* GetIconClass(bool* bOutIsClassType) const;
  249. /** Returns the asset UObject if it is loaded or loads the asset if it is unloaded then returns the result */
  250. UObject* GetAsset() const
  251. {
  252. if (!IsValid())
  253. {
  254. // Dont even try to find the object if the objectpath isn't set
  255. return NULL;
  256. }
  257. UObject* Asset = FindObject<UObject>(NULL, *ObjectPath.ToString());
  258. if (Asset == NULL)
  259. {
  260. Asset = LoadObject<UObject>(NULL, *ObjectPath.ToString());
  261. }
  262. return Asset;
  263. }
  264. /** Returns the full name for the asset in the form: Class ObjectPath */
  265. FString GetFullName() const
  266. {
  267. FString FullName;
  268. GetFullName(FullName);
  269. return FullName;
  270. }
  271. /** Convert to a SoftObjectPath. PackageName.AssetName for ToplevelAssets. OptionalOuterName and AssetName joined by : or . for sub-object assets */
  272. FSoftObjectPath GetSoftObjectPath() const;
  273. /** Returns the folder path of the asset package file */
  274. FString GetFolderPath() const;
  275. /** Populates OutFullName with the full name for the asset in the form: Class ObjectPath */
  276. void GetFullName(FString& OutFullName) const
  277. {
  278. OutFullName.Reset();
  279. AssetClass.AppendString(OutFullName);
  280. OutFullName.AppendChar(' ');
  281. ObjectPath.AppendString(OutFullName);
  282. }
  283. /** Returns the class UClass if it is loaded. It is not possible to load the class if it is unloaded since we only have the short name. */
  284. UClass* GetClass() const
  285. {
  286. if (!IsValid())
  287. {
  288. // Dont even try to find the class if the objectpath isn't set
  289. return NULL;
  290. }
  291. UClass* FoundClass = FindObject<UClass>(nullptr, *AssetClass.ToString());
  292. if (!FoundClass)
  293. {
  294. // Look for class redirectors
  295. FName NewPath = FLinkerLoad::FindNewNameForClass(AssetClass, false);
  296. if (NewPath != NAME_None)
  297. {
  298. FoundClass = FindObject<UClass>(nullptr, *NewPath.ToString());
  299. }
  300. }
  301. return FoundClass;
  302. }
  303. bool operator==(const FExtAssetData& Other) const
  304. {
  305. return ObjectPath == Other.ObjectPath;
  306. }
  307. bool operator!=(const FExtAssetData& Other) const
  308. {
  309. return ObjectPath != Other.ObjectPath;
  310. }
  311. #if ECB_WIP_CACHEDB
  312. template<class Archive>
  313. void SerializeForCache(Archive&& Ar);
  314. #endif
  315. static FString ConvertFilePathToTempPackageName(const FString& InFilePath);
  316. static FString& GetSandboxPackagePath();
  317. static FString& GetSandboxPackagePathWithSlash();
  318. static FString& GetSandboxDir();
  319. static FString& GetUAssetBrowserTempDir();
  320. static FString& GetImportSessionTempDir();
  321. static FString GetZipExportSessionTempDir();
  322. public:
  323. private:
  324. /** Parse .uasset file to gather asset data */
  325. bool PreParse();
  326. /** Parse .uasset file to gather asset data */
  327. bool DoParse();
  328. void AppendObjectPath(FString& String) const
  329. {
  330. TStringBuilder<FName::StringBufferSize> Builder;
  331. AppendObjectPath(Builder);
  332. String.Append(FString(Builder));
  333. }
  334. /** Append the object path to the given string builder. */
  335. void AppendObjectPath(FStringBuilderBase& Builder) const
  336. {
  337. if (!IsValid())
  338. {
  339. return;
  340. }
  341. #if WITH_EDITORONLY_DATA
  342. if (!OptionalOuterPath.IsNone())
  343. {
  344. UE::AssetRegistry::Private::ConcatenateOuterPathAndObjectName(Builder, OptionalOuterPath, AssetName);
  345. }
  346. else
  347. #endif
  348. {
  349. Builder << PackageName << '.' << AssetName;
  350. }
  351. }
  352. void CheckIfCompatibleWithCurrentEngineVersion();
  353. private:
  354. /** If the package has been parsed */
  355. bool bParsed;
  356. /** If the package is valid */
  357. bool bValid;
  358. /** If has thumbnail data */
  359. bool bHasThumbnail;
  360. /** If the package is compatible with current engine version */
  361. bool bCompatible;
  362. #if WITH_EDITORONLY_DATA
  363. /**
  364. * If this object is not a top level asset, this contains the path of the outer of this object.
  365. * Non top-level assets may only be used in the editor.
  366. * For some assets (such as external actors) this may not start with PackageName.
  367. * e.g. PackageName = /Game/__EXTERNAL_ACTORS__/Maps/MyMap/ABCDE12345
  368. OptionalOuterPath = /Game/Maps/MyMap.MyMap:PersistentLevel
  369. AssetName = SomeExternalActor
  370. */
  371. FName OptionalOuterPath;
  372. #endif
  373. };
  374. FORCEINLINE uint32 GetTypeHash(const FExtAssetData& AssetData)
  375. {
  376. return GetTypeHash(AssetData.PackageFilePath);
  377. }
  378. struct FExtAssetDataUtil
  379. {
  380. #if 0
  381. static bool RemapPackagesToFullFilePath(const FString& InPackageName, const TArray<FString>& InRootPackageNamesToReplace, const FString& InAssetContentDir, FString& OutFullFilePath);
  382. #endif
  383. static FString GetPluginNameFromAssetContentRoot(const FString& InAssetContentDir);
  384. static FString GetPackageRootFromFullPackagePath(const FString& InFullPackagePath);
  385. static bool RemapGamePackageToFullFilePath(const FString& InGameRoot, const FString& InPackageName, const FString& InAssetContentDir, FString& OutFullFilePath, bool bPackageIsFolder = false);
  386. static bool SyncToContentBrowser(const FExtAssetData& InAssetData);
  387. };
  388. namespace FExtAssetCoreUtil
  389. {
  390. class FExtAssetFeedbackContext : public FExtFeedbackContextEditor
  391. {
  392. public:
  393. /**
  394. * cache the cancel result as FExtFeedbackContextEditor::ReceivedUserCancel seems clears the result right away
  395. */
  396. virtual bool ReceivedUserCancel() override;
  397. private:
  398. bool bTaskWasCancelledCache = false;
  399. };
  400. class IExtAssetProgressReporter
  401. {
  402. public:
  403. virtual ~IExtAssetProgressReporter() = default;
  404. virtual void BeginWork(const FText& InDescription, float InAmountOfWork, bool bInterruptible = true) = 0;
  405. virtual void EndWork() = 0;
  406. virtual void ReportProgress(float IncrementOfWork, const FText& InMessage) = 0;
  407. virtual bool IsWorkCancelled() = 0;
  408. virtual FFeedbackContext* GetFeedbackContext() const = 0;
  409. };
  410. class FExtAssetWorkReporter
  411. {
  412. public:
  413. FExtAssetWorkReporter(const TSharedPtr<IExtAssetProgressReporter>& InReporter, const FText& InDescription, float InAmountOfWork, float InIncrementOfWork, bool bInterruptible);
  414. ~FExtAssetWorkReporter();
  415. void ReportNextStep(const FText& InMessage, float InIncrementOfWork);
  416. void ReportNextStep(const FText& InMessage);
  417. bool IsWorkCancelled() const;
  418. private:
  419. TSharedPtr<IExtAssetProgressReporter> Reporter;
  420. float DefaultIncrementOfWork;
  421. };
  422. class FExtAssetProgressUIReporter : public IExtAssetProgressReporter
  423. {
  424. public:
  425. FExtAssetProgressUIReporter()
  426. : bIsCancelled(false)
  427. {
  428. }
  429. FExtAssetProgressUIReporter(TSharedRef<FFeedbackContext> InFeedbackContext)
  430. : FeedbackContext(InFeedbackContext)
  431. , bIsCancelled(false)
  432. {
  433. }
  434. virtual ~FExtAssetProgressUIReporter()
  435. {
  436. }
  437. /* begin IExtAssetProgressReporter interface */
  438. virtual void BeginWork(const FText& InTitle, float InAmountOfWork, bool bInterruptible = true) override;
  439. virtual void EndWork() override;
  440. virtual void ReportProgress(float Progress, const FText& InMessage) override;
  441. virtual bool IsWorkCancelled() override;
  442. FFeedbackContext* GetFeedbackContext() const override;
  443. /* end IExtAssetProgressReporter interface */
  444. private:
  445. TArray< TSharedPtr< FScopedSlowTask > > ProgressTasks;
  446. TSharedPtr< FFeedbackContext > FeedbackContext;
  447. bool bIsCancelled;
  448. };
  449. class FExtAssetProgressTextReporter : public IExtAssetProgressReporter
  450. {
  451. public:
  452. FExtAssetProgressTextReporter()
  453. : TaskDepth(0)
  454. , FeedbackContext(new FFeedbackContextAnsi)
  455. {
  456. }
  457. virtual ~FExtAssetProgressTextReporter()
  458. {
  459. }
  460. // Begin IDataprepProgressReporter interface
  461. virtual void BeginWork(const FText& InTitle, float InAmountOfWork, bool bInterruptible = true) override;
  462. virtual void EndWork() override;
  463. virtual void ReportProgress(float Progress, const FText& InMessage) override;
  464. virtual bool IsWorkCancelled() override;
  465. virtual FFeedbackContext* GetFeedbackContext() const override;
  466. private:
  467. int32 TaskDepth;
  468. TUniquePtr<FFeedbackContextAnsi> FeedbackContext;
  469. };
  470. }
  471. /**
  472. * Collection Util
  473. */
  474. struct FExtCollectionUtil
  475. {
  476. static FName GetOrCreateCollection(FName CollectionName, bool bUniqueCollection);
  477. static bool AddAssetsToCollection(const TArray<FAssetData>& InAssets, FName InCollectionName, bool bUniqueCollection);
  478. };
  479. /**
  480. * FAssetData Util
  481. */
  482. struct FAssetDataUtil
  483. {
  484. static void PlaceToCurrentLevelViewport(const TArray<FAssetData>& InAssets);
  485. static void ExportAssetsWithDialog(const TArray<FAssetData>& InAssets);
  486. };
  487. /**
  488. *A structure defining a thing that can be reference by something else in the asset registry. Represents either a package of a primary asset id
  489. */
  490. struct FExtAssetIdentifier
  491. {
  492. /** The name of the package that is depended on, this is always set unless PrimaryAssetType is */
  493. FName PackageName;
  494. /** The primary asset type, if valid the ObjectName is the PrimaryAssetName */
  495. FPrimaryAssetType PrimaryAssetType;
  496. /** Specific object within a package. If empty, assumed to be the default asset */
  497. FName ObjectName;
  498. /** Name of specific value being referenced, if ObjectName specifies a type such as a UStruct */
  499. FName ValueName;
  500. /** Can be implicitly constructed from just the package name */
  501. FExtAssetIdentifier(FName InPackageName, FName InObjectName = NAME_None, FName InValueName = NAME_None)
  502. : PackageName(InPackageName), PrimaryAssetType(NAME_None), ObjectName(InObjectName), ValueName(InValueName)
  503. {}
  504. /** Construct from a primary asset id */
  505. FExtAssetIdentifier(const FPrimaryAssetId& PrimaryAssetId, FName InValueName = NAME_None)
  506. : PackageName(NAME_None), PrimaryAssetType(PrimaryAssetId.PrimaryAssetType), ObjectName(PrimaryAssetId.PrimaryAssetName), ValueName(InValueName)
  507. {}
  508. FExtAssetIdentifier(UObject* SourceObject, FName InValueName)
  509. {
  510. if (SourceObject)
  511. {
  512. UPackage* Package = SourceObject->GetOutermost();
  513. PackageName = Package->GetFName();
  514. ObjectName = SourceObject->GetFName();
  515. ValueName = InValueName;
  516. }
  517. }
  518. FExtAssetIdentifier()
  519. : PackageName(NAME_None), PrimaryAssetType(NAME_None), ObjectName(NAME_None), ValueName(NAME_None)
  520. {}
  521. /** Returns primary asset id for this identifier, if valid */
  522. FPrimaryAssetId GetPrimaryAssetId() const
  523. {
  524. if (PrimaryAssetType != NAME_None)
  525. {
  526. return FPrimaryAssetId(PrimaryAssetType, ObjectName);
  527. }
  528. return FPrimaryAssetId();
  529. }
  530. /** Returns true if this represents a package */
  531. bool IsPackage() const
  532. {
  533. return PackageName != NAME_None && !IsObject() && !IsValue();
  534. }
  535. /** Returns true if this represents an object, true for both package objects and PrimaryAssetId objects */
  536. bool IsObject() const
  537. {
  538. return ObjectName != NAME_None && !IsValue();
  539. }
  540. /** Returns true if this represents a specific value */
  541. bool IsValue() const
  542. {
  543. return ValueName != NAME_None;
  544. }
  545. /** Returns true if this is a valid non-null identifier */
  546. bool IsValid() const
  547. {
  548. return PackageName != NAME_None || GetPrimaryAssetId().IsValid();
  549. }
  550. /** Returns string version of this identifier in Package.Object::Name format */
  551. FString ToString() const
  552. {
  553. FString Result;
  554. if (PrimaryAssetType != NAME_None)
  555. {
  556. Result = GetPrimaryAssetId().ToString();
  557. }
  558. else
  559. {
  560. Result = PackageName.ToString();
  561. if (ObjectName != NAME_None)
  562. {
  563. Result += TEXT(".");
  564. Result += ObjectName.ToString();
  565. }
  566. }
  567. if (ValueName != NAME_None)
  568. {
  569. Result += TEXT("::");
  570. Result += ValueName.ToString();
  571. }
  572. return Result;
  573. }
  574. /** Converts from Package.Object::Name format */
  575. static FExtAssetIdentifier FromString(const FString& String)
  576. {
  577. // To right of :: is value
  578. FString PackageString;
  579. FString ObjectString;
  580. FString ValueString;
  581. // Try to split value out
  582. if (!String.Split(TEXT("::"), &PackageString, &ValueString))
  583. {
  584. PackageString = String;
  585. }
  586. // Check if it's a valid primary asset id
  587. FPrimaryAssetId PrimaryId = FPrimaryAssetId::FromString(PackageString);
  588. if (PrimaryId.IsValid())
  589. {
  590. return FExtAssetIdentifier(PrimaryId, *ValueString);
  591. }
  592. // Try to split on first . , if it fails PackageString will stay the same
  593. FString(PackageString).Split(TEXT("."), &PackageString, &ObjectString);
  594. return FExtAssetIdentifier(*PackageString, *ObjectString, *ValueString);
  595. }
  596. friend inline bool operator==(const FExtAssetIdentifier& A, const FExtAssetIdentifier& B)
  597. {
  598. return A.PackageName == B.PackageName && A.ObjectName == B.ObjectName && A.ValueName == B.ValueName;
  599. }
  600. friend inline uint32 GetTypeHash(const FExtAssetIdentifier& Key)
  601. {
  602. uint32 Hash = 0;
  603. // Most of the time only packagename is set
  604. if (Key.ObjectName.IsNone() && Key.ValueName.IsNone())
  605. {
  606. return GetTypeHash(Key.PackageName);
  607. }
  608. Hash = HashCombine(Hash, GetTypeHash(Key.PackageName));
  609. Hash = HashCombine(Hash, GetTypeHash(Key.PrimaryAssetType));
  610. Hash = HashCombine(Hash, GetTypeHash(Key.ObjectName));
  611. Hash = HashCombine(Hash, GetTypeHash(Key.ValueName));
  612. return Hash;
  613. }
  614. /** Identifiers may be serialized as part of the registry cache, or in other contexts. If you make changes here you must also change FAssetRegistryVersion */
  615. friend FArchive& operator<<(FArchive& Ar, FExtAssetIdentifier& AssetIdentifier)
  616. {
  617. // Serialize bitfield of which elements to serialize, in general many are empty
  618. uint8 FieldBits = 0;
  619. if (Ar.IsSaving())
  620. {
  621. FieldBits |= (AssetIdentifier.PackageName != NAME_None) << 0;
  622. FieldBits |= (AssetIdentifier.PrimaryAssetType != NAME_None) << 1;
  623. FieldBits |= (AssetIdentifier.ObjectName != NAME_None) << 2;
  624. FieldBits |= (AssetIdentifier.ValueName != NAME_None) << 3;
  625. }
  626. Ar << FieldBits;
  627. if (FieldBits & (1 << 0))
  628. {
  629. Ar << AssetIdentifier.PackageName;
  630. }
  631. if (FieldBits & (1 << 1))
  632. {
  633. FName TypeName = AssetIdentifier.PrimaryAssetType.GetName();
  634. Ar << TypeName;
  635. if (Ar.IsLoading())
  636. {
  637. AssetIdentifier.PrimaryAssetType = TypeName;
  638. }
  639. }
  640. if (FieldBits & (1 << 2))
  641. {
  642. Ar << AssetIdentifier.ObjectName;
  643. }
  644. if (FieldBits & (1 << 3))
  645. {
  646. Ar << AssetIdentifier.ValueName;
  647. }
  648. return Ar;
  649. }
  650. };
  651. enum class EDependencyNodePackageType : uint8
  652. {
  653. File,
  654. Script,
  655. Engine,
  656. Other,
  657. };
  658. enum class EDependencyNodeReferenceType : uint8
  659. {
  660. Hard,
  661. Soft
  662. };
  663. enum class EDependencyNodeStatus : uint8
  664. {
  665. Unknown,
  666. AbortGathering,
  667. Missing,
  668. Invalid,
  669. Valid,
  670. ValidWithSoftReferenceIssue
  671. };
  672. /**
  673. * Dependency info gathered for asset data
  674. */
  675. struct FExtAssetDependencyInfo
  676. {
  677. // ---------------- Source -----------------
  678. TArray<FString> ValidDependentFiles;
  679. TArray<FString> InvalidDependentFiles;
  680. TArray<FString> MissingDependentFiles;
  681. TArray<FString> SkippedPackageNames;
  682. TArray<FString> MissingPackageNames;
  683. TMap<FName, EDependencyNodeStatus> AllDepdencyPackages; // PakcaegName - DependencyStatus map, dependencies only (not include main asset)
  684. TMap<FName, TArray<FExtAssetDependencyNode>> AssetDepdencies; // Asset File Path - DependencyNode map
  685. EDependencyNodeStatus AssetStatus = EDependencyNodeStatus::Unknown;
  686. bool IsValid(bool bIgnoreSoftIssue = true);
  687. void Print();
  688. #if ECB_WIP_CACHEDB
  689. friend FArchive& operator<<(FArchive& Ar, FExtAssetDependencyInfo& InDependencyInfo);
  690. #endif
  691. };
  692. struct FExtAssetDependencyNode
  693. {
  694. FExtAssetDependencyNode(const FName& InPackageName, EDependencyNodeStatus InNodeStatus, bool bSoftReference)
  695. : PackageName(InPackageName)
  696. , NodeStatus(InNodeStatus)
  697. {
  698. ReferenceType = bSoftReference ? EDependencyNodeReferenceType::Soft : EDependencyNodeReferenceType::Hard;
  699. }
  700. FExtAssetDependencyNode() {}
  701. FName PackageName = NAME_None;
  702. EDependencyNodeReferenceType ReferenceType = EDependencyNodeReferenceType::Hard;
  703. EDependencyNodeStatus NodeStatus = EDependencyNodeStatus::Valid;
  704. static FString GetStatusString(EDependencyNodeStatus InStatus);
  705. FString ToString() const;
  706. #if ECB_WIP_CACHEDB
  707. friend FArchive& operator<<(FArchive& Ar, FExtAssetDependencyNode& InDependencyNode);
  708. #endif
  709. };
  710. struct FExtAssetDependencyWalker
  711. {
  712. static EDependencyNodeStatus GatherDependencies(const FExtAssetData& InAssetData, const FString& InAssetContentDir, const FExtAssetData::EContentType& InAssetContentType, FExtAssetDependencyInfo& InOuDependencyInfo, bool bShowProgess = false);
  713. private:
  714. static EDependencyNodeStatus GatherDependencies(const FExtAssetData& InAssetData, const FString& InAssetContentDir, const FExtAssetData::EContentType& InAssetContentType, FExtAssetDependencyInfo& InOuDependencyInfo, int32 Level, FScopedSlowTask* SlowTaskPtr = nullptr);
  715. static EDependencyNodeStatus GatherPackageDependencies(const FName& DependPackageName, FExtAssetDependencyInfo& InOuDependencyInfo
  716. , const FString& InAssetContentDir, const FExtAssetData::EContentType& InAssetContentType
  717. , int32& Level, bool bSoftReference, FScopedSlowTask* SlowTaskPtr = nullptr);
  718. };
  719. struct FRootContentPathInfo
  720. {
  721. FExtAssetData::EContentType ContentType;
  722. FString AssetContentRoot;
  723. FText DisplayName;
  724. #if ECB_WIP_CACHEDB
  725. friend FArchive& operator<<(FArchive& Ar, FRootContentPathInfo& InDependencyInfo);
  726. #endif
  727. };
  728. /**
  729. * Cache asset registry state in memory or disk, currently only in memory cache
  730. */
  731. class FExtAssetRegistryStateCache
  732. {
  733. public:
  734. void Reset();
  735. void ClearThumbnailCache();
  736. void CacheNewAsset(FExtAssetData* InAssetToCache);
  737. void ReCacheParsedAsset(FExtAssetData* InAssetToCache);
  738. void UpdateCacheByRemovedFolders(const TArray<FString>& InRemovedFolders);
  739. bool PurgeAssets(bool bSilent = true);
  740. void PrintStatus() const;
  741. /** Returns memory size of entire registry, optionally logging sizes */
  742. //uint32 GetAllocatedSize(bool bLogDetailed = false) const;
  743. #if ECB_WIP_CACHEDB
  744. template<class Archive>
  745. bool SerializeForCache(Archive&& Ar);
  746. int32 NumFoldersInCache = 0;
  747. int32 NumAssetsInCache = 0;
  748. #endif
  749. private:
  750. #if ECB_WIP_CACHEDB
  751. bool Save(FArchive& Ar);
  752. bool Load(FArchive& Ar);
  753. template<class Archive>
  754. void Load(Archive&& Ar, FExtAssetRegistryVersion::Type Version);
  755. void SetAssetDatas(TArrayView<FExtAssetData> AssetDatas);
  756. void SerializeDependencyInfos(FArchive& Ar);
  757. void SerializeMisc(FArchive& Ar);
  758. TArray<FExtAssetData*> PreallocatedAssetDataBuffers;
  759. #endif
  760. public:
  761. /** Mirrored Root Content Paths Info Copied from ExtAssetRegistry */
  762. TArray<FString> CachedRootContentPaths;
  763. /** A one-to-many mapping between a parent path and its child paths*/
  764. TMap<FName, TSet<FName>> CachedSubPaths;
  765. /** The array of empty folders which contains no package recursively */
  766. TMap<FName, bool> CachedEmptyFoldersStatus;
  767. /** The set of folders have uasset been fully parsed */
  768. TSet<FName> CachedFullyParsedFolders;
  769. /** The map of long package folder path to asset data */
  770. TMap<FName, TArray<FExtAssetData*> > CachedAssetsByFolder;
  771. /** A one-to-many mapping between a folder to packages' file path in the folder */
  772. TMap<FName, TArray<FName>> CachedFilePathsByFolder;
  773. /** The map of asset file path to asset data */
  774. TMap<FName, FExtAssetData*> CachedAssetsByFilePath;
  775. /** Assets been cached but not yet parsed, subset of CachedAssetsByFilePath */
  776. TMap<FName, FExtAssetData*> CachedUnParsedAssets;
  777. /** The map of asset file path to asset data */
  778. TMap<FName, FExtAssetDependencyInfo> CachedDependencyInfoByFilePath;
  779. /** Cached Asset Thumbnail data, could grows very fast when viewing large amount of assets */
  780. TMap<FName, FObjectThumbnail> CachedThumbnails; // todo: FIFO queue?
  781. /** The map of class name to asset data for assets saved to disk */
  782. TMap<FName, TArray<FExtAssetData*> > CachedAssetsByClass;
  783. /** The map of asset tag to asset data for assets saved to disk */
  784. TMap<FName, TArray<FExtAssetData*> > CachedAssetsByTag;
  785. /** The map of asset package name to file path */
  786. TMap<FName, FName> CachedPackageNameToFilePathMap;
  787. /** The array of asset content root dirs, sorted from longest to shortest */
  788. TArray<FName> CachedAssetContentRoots;
  789. TMap<FName, FExtAssetData::EContentType> CachedAssetContentType; // ContentRoot - ContentType
  790. TMap<FName, FName> CachedAssetContentRootHosts; // Host - ContentRoot
  791. TMap<FName, FName> CachedAssetContentRootConfigDirs; // ContentRoot - ConfigDir
  792. TMap<FName, TArray<FName>> CachedFolderColorIndices; // ContentRoot - Folders
  793. TMap<FName, FLinearColor> CachedFolderColors; // Folder - Color
  794. private:
  795. void CacheValidAssetInfo(FExtAssetData* InAssetToCache);
  796. };
  797. struct FExtFolderGatherResult
  798. {
  799. FExtFolderGatherResult(const FName& InRootPath, const FName& InParentPath, const TArray<FName>& InSubPaths, const TMap<FName, TArray<FName>>& InRecurseSubPaths, const TMap<FName, TArray<FName>>& InFolderPackages)
  800. : RootPath(InRootPath)
  801. , ParentPath(InParentPath)
  802. , SubPaths(InSubPaths)
  803. , RecurseSubPaths(InRecurseSubPaths)
  804. , FolderPakages(InFolderPackages)
  805. {}
  806. FName RootPath;
  807. FName ParentPath;
  808. TArray<FName> SubPaths;
  809. TMap<FName, TArray<FName>> RecurseSubPaths;
  810. TMap<FName, TArray<FName>> FolderPakages;
  811. };
  812. struct FExtAssetContentRootGatherResult
  813. {
  814. FExtAssetContentRootGatherResult(const FName& InAssetContentRootDir, const FName& InAssetContentRootHostDir, const FName& InAssetContentRootConfigDir, FExtAssetData::EContentType InAssetContentType)
  815. : AssetContentRoot(InAssetContentRootDir)
  816. , AssetContentRootHost(InAssetContentRootHostDir)
  817. , AssetContentRootConfigDir(InAssetContentRootConfigDir)
  818. , AssetContentType(InAssetContentType)
  819. {}
  820. FName AssetContentRoot;
  821. FName AssetContentRootHost;
  822. FName AssetContentRootConfigDir;
  823. FExtAssetData::EContentType AssetContentType;
  824. };
  825. struct FExtAssetGatherResult
  826. {
  827. FExtAssetGatherResult()
  828. {}
  829. TMap<FName, FExtAssetData> ParsedAssets;
  830. void AddReuslt(const FName& InFilePath, const FExtAssetData& InParsedAsset);
  831. bool HasResult() const;
  832. void Reset();
  833. const TMap<FName, FExtAssetData>& GetParsedAssets() const { return ParsedAssets; };
  834. };
  835. /**
  836. * Gather and cache information about uasset files and paths
  837. */
  838. class FExtAssetRegistry
  839. {
  840. public:
  841. ///////////////////////////////////////////////
  842. // Events
  843. //
  844. DECLARE_EVENT_OneParam(FExtAssetRegistry, FPathAddedEvent, const FString& /*Path*/);
  845. FPathAddedEvent& OnRootPathAdded() { return RootPathAddedEvent; }
  846. DECLARE_EVENT_OneParam(FExtAssetRegistry, FPathRemovedEvent, const FString& /*Path*/);
  847. FPathRemovedEvent& OnRootPathRemoved() { return RootPathRemovedEvent; }
  848. DECLARE_EVENT(FExtAssetRegistry, FPathUpdatedEvent);
  849. FPathUpdatedEvent& OnRootPathUpdated() { return RootPathUpdatedEvent; }
  850. DECLARE_EVENT_OneParam(FExtAssetRegistry, FFolderStartGatheringEvent, const TArray<FString>& /*Paths*/);
  851. FFolderStartGatheringEvent& OnFolderStartGathering() { return FolderStartGatheringEvent; }
  852. DECLARE_EVENT_TwoParams(FExtAssetRegistry, FFolderFinishGatheringEvent, const FString& /*GatheredPath*/, const FString& /*RootGatheredPath*/);
  853. FFolderFinishGatheringEvent& OnFolderFinishGathering() { return FolderFinishGatheringEvent; }
  854. DECLARE_EVENT_TwoParams(FExtAssetRegistry, FAssetGatheredEvent, const FExtAssetData& /*GatheredAsset*/, int32 /*Left*/);
  855. FAssetGatheredEvent& OnAssetGathered() { return AssetGatheredEvent; }
  856. DECLARE_EVENT_OneParam(FExtAssetRegistry, FAssetUpdatedEvent, const FExtAssetData& /*UpdatedAssets*/);
  857. FAssetUpdatedEvent& OnAssetUpdated() { return AssetUpdatedEvent; }
  858. void BroadcastAssetUpdatedEvent(const FExtAssetData& /*UpdatedAssets*/);
  859. ///////////////////////////////////////////////
  860. // Async Folder Gather
  861. //
  862. bool GetAndTrimFolderGatherResult();
  863. bool IsFolderBackgroundGathering(const FString& InFolder) const;
  864. FName GetCurrentGatheringFolder() const { return BackgroundGatheringSubFolder; }
  865. ///////////////////////////////////////////////
  866. // Async Asset Gather
  867. //
  868. bool GetAndTrimAssetGatherResult();
  869. //bool IsFolderBackgroundGathering(const FString& InFolder) const;
  870. //FName GetCurrentGatheringFolder() const { return BackgroundGatheringSubFolder; }
  871. private:
  872. /** The delegate to execute when an root content path is added to the registry */
  873. FPathAddedEvent RootPathAddedEvent;
  874. /** The delegate to execute when an root content path is removed from the registry */
  875. FPathRemovedEvent RootPathRemovedEvent;
  876. /** The delegate to execute when an root content path is removed from the registry */
  877. FPathUpdatedEvent RootPathUpdatedEvent;
  878. /** The delegate to execute when a folder path is start gathering from the registry */
  879. FFolderStartGatheringEvent FolderStartGatheringEvent;
  880. /** The delegate to execute when a folder path is finishing gathering from the registry */
  881. FFolderFinishGatheringEvent FolderFinishGatheringEvent;
  882. /** The delegate to execute when an asset is finishing gathering from the registry */
  883. FAssetGatheredEvent AssetGatheredEvent;
  884. FAssetUpdatedEvent AssetUpdatedEvent;
  885. public:
  886. FExtAssetRegistry();
  887. virtual ~FExtAssetRegistry();
  888. public:
  889. ///////////////////////////////////////////////
  890. // IAssetRegistry compatible interface
  891. //
  892. /** Gets asset data for all assets that match the filter. Alias of GetOrCacheExtAssets */
  893. bool GetAssets(const struct FARFilter& InFilter, TArray<FExtAssetData>& OutAssetData);
  894. /** Trims items out of the asset data list that do not pass the supplied filter */
  895. void RunAssetsThroughFilter(TArray<FExtAssetData>& AssetDataList, const FARFilter& Filter) const;
  896. /**
  897. * Gets a list of AssetIdentifiers or FAssetDependencies that reference the supplied AssetIdentifier. (On disk references ONLY)
  898. *
  899. * @param AssetIdentifier the name of the package/name for which to gather referencers (eg, /Game/MyFolder/MyAsset)
  900. * @param OutReferencers a list of things that reference AssetIdentifier.
  901. * @param Category which category(ies) of referencers to include in the output list. Referencers that have a dependency matching ANY of the OR'd categories will be returned.
  902. * @param Flags which flags are required present or not present on the referencer's dependency. Referencers that have a dependency matching ALL required and NONE excluded bits will be returned. For each potentially returned dependency, flags not applicable to their category are ignored.
  903. */
  904. bool GetReferencers(const FExtAssetIdentifier& AssetIdentifier, TArray<FExtAssetIdentifier>& OutReferencers, UE::AssetRegistry::EDependencyCategory Category = UE::AssetRegistry::EDependencyCategory::All, const UE::AssetRegistry::FDependencyQuery& Flags = UE::AssetRegistry::FDependencyQuery()) const { return false; }
  905. /**
  906. * Gets a list of PackageNames that reference the supplied package. (On disk references ONLY)
  907. *
  908. * @param PackageName the name of the package for which to gather dependencies (eg, /Game/MyFolder/MyAsset)
  909. * @param OutReferencers a list of packages that reference the package whose path is PackageName
  910. * @param Category which category(ies) of referencers to include in the output list. Referencers that have a dependency matching ANY of the OR'd categories will be returned.
  911. * @param Flags which flags are required present or not present on the referencer's dependency. Referencers that have a dependency matching ALL required and NONE excluded bits will be returned. For each potentially returned dependency, flags not applicable to their category are ignored.
  912. */
  913. bool GetReferencers(FName PackageName, TArray<FName>& OutReferencers, UE::AssetRegistry::EDependencyCategory Category = UE::AssetRegistry::EDependencyCategory::Package, const UE::AssetRegistry::FDependencyQuery& Flags = UE::AssetRegistry::FDependencyQuery()) const { return false; }
  914. /**
  915. * Gets a list of AssetIdentifiers or FAssetDependencies that are referenced by the supplied AssetIdentifier. (On disk references ONLY)
  916. *
  917. * @param AssetIdentifier the name of the package/name for which to gather dependencies.
  918. * @param OutDependencies a list of things that are referenced by AssetIdentifier.
  919. * @param Category which category(ies) of dependencies to include in the output list. Dependencies matching ANY of the OR'd categories will be returned.
  920. * @param Flags which flags are required present or not present on the dependencies. Dependencies matching ALL required and NONE excluded bits will be returned. For each potentially returned dependency, flags not applicable to their category are ignored.
  921. */
  922. bool GetDependencies(const FExtAssetIdentifier& AssetIdentifier, TArray<FExtAssetIdentifier>& OutDependencies, UE::AssetRegistry::EDependencyCategory Category = UE::AssetRegistry::EDependencyCategory::All, const UE::AssetRegistry::FDependencyQuery& Flags = UE::AssetRegistry::FDependencyQuery());
  923. /**
  924. * Gets a list of PackageNames that are referenced by the supplied package. (On disk references ONLY)
  925. *
  926. * @param PackageName the name of the package for which to gather dependencies (eg, /Game/MyFolder/MyAsset)
  927. * @param OutDependencies a list of packages that are referenced by the package whose path is PackageName
  928. * @param Category which category(ies) of dependencies to include in the output list. Dependencies matching ANY of the OR'd categories will be returned.
  929. * @param Flags which flags are required present or not present on the dependencies. Dependencies matching ALL required and NONE excluded bits will be returned. For each potentially returned dependency, flags not applicable to their category are ignored.
  930. */
  931. bool GetDependencies(FName PackageName, TArray<FName>& OutDependencies, UE::AssetRegistry::EDependencyCategory Category = UE::AssetRegistry::EDependencyCategory::Package, const UE::AssetRegistry::FDependencyQuery& Flags = UE::AssetRegistry::FDependencyQuery());
  932. ////////////////////////////////
  933. // Asset gather progress update
  934. /** Payload data for a file progress update */
  935. struct FAssetGatherProgressUpdateData
  936. {
  937. FAssetGatherProgressUpdateData(int32 InNumTotalAssets, int32 InNumAssetsProcessedByAssetRegistry, int32 InNumAssetsPendingDataLoad, bool InIsDiscoveringAssetFiles)
  938. : NumTotalAssets(InNumTotalAssets)
  939. , NumAssetsProcessedByAssetRegistry(InNumAssetsProcessedByAssetRegistry)
  940. , NumAssetsPendingDataLoad(InNumAssetsPendingDataLoad)
  941. , bIsDiscoveringAssetFiles(InIsDiscoveringAssetFiles)
  942. {
  943. }
  944. int32 NumTotalAssets;
  945. int32 NumAssetsProcessedByAssetRegistry;
  946. int32 NumAssetsPendingDataLoad;
  947. bool bIsDiscoveringAssetFiles;
  948. };
  949. /** Event to update the progress of the background file load */
  950. DECLARE_EVENT_OneParam(FExtAssetRegistry, FAssetGatherProgressUpdatedEvent, const FAssetGatherProgressUpdateData& /*ProgressUpdateData*/);
  951. FAssetGatherProgressUpdatedEvent& OnAssetGatherProgressUpdated()
  952. {
  953. return AssetGatherProgressUpdatedEvent;
  954. }
  955. /** Returns true if the asset registry is currently gathering uasset files */
  956. bool IsGatheringAssets() const;
  957. private:
  958. /** The delegate to execute while loading files to update progress */
  959. FAssetGatherProgressUpdatedEvent AssetGatherProgressUpdatedEvent;
  960. bool bIsGatheringAssets = false;
  961. int32 NumFilteredAssets = 0;
  962. int32 NumToGatherAssets = 0;
  963. public:
  964. ///////////////////////////////////////////////
  965. // AssetIdentifier interface
  966. //
  967. /** Returns valid PrimaryAssetId if this is a fake AssetData for a primary asset */
  968. static FPrimaryAssetId ExtractPrimaryAssetIdFromFakeAssetData(const FExtAssetData& InAssetData);
  969. static void ExtractAssetIdentifiersFromAssetDataList(const TArray<FExtAssetData>& AssetDataList, TArray<FExtAssetIdentifier>& OutAssetIdentifiers);
  970. public:
  971. void Shutdown();
  972. /** Load and cache root content folders from config */
  973. void LoadRootContentPaths();
  974. /** Merge input paths to current root content folders */
  975. void MergeRootContentPathsWith(const TArray<FString>& InPathsToMerge, bool bReplaceCurrent);
  976. /** Replace current content folders with input */
  977. void ReplaceRootContentPathsWith(const TArray<FString>& InPaths);
  978. /** Save root content folders to config file */
  979. void SaveRootContentPaths();
  980. /** Get root content folders */
  981. void QueryRootContentPaths(TArray<FString>& OutRootContentPaths) const;
  982. /** Get root content folder from file path */
  983. bool QueryRootContentPathFromFilePath(const FString& InFilePath, FString& OutRootContentPath);
  984. /** Get root content folders */
  985. bool QueryRootContentPathInfo(const FString& InRootContentPath, FText* OutDisplayName = nullptr, FExtAssetData::EContentType* OutContentType = nullptr, FString* OutAssetContentRoot = nullptr) const;
  986. /** Get relative path to any root path, return false if not match any */
  987. bool ParseAssetContentRoot(const FString& InFilePath, FString& OutRelativePath, FString& OutRootPath, FExtAssetData::EContentType& OutAssetContentType, TSet<FName>* InAllDependencies = nullptr);
  988. /** Cache found asset content dir */
  989. void AddAssetContentRoot(const FString& InAssetContentRootDir, const FString& InAssetContentRootHostDir, const FString& ConfigDir, FExtAssetData::EContentType InContentType);
  990. /** Get cached asset content dir, return false if not found */
  991. bool GetAssetContentRoot(const FString& InFilePath, FString& OutFoundAssetContentDir) const;
  992. FExtAssetData::EContentType GetAssetContentRootContentType(const FString& InAssetContentRoot) const;
  993. /** Get cached folder color*/
  994. bool GetFolderColor(const FString& InFolderPath, FLinearColor& OutFolderColor) const;
  995. bool IsAsetContentRootHasFolderColor(const FString& InAssetContentRoot) const;
  996. void GetAssetContentRootColoredFolders(const FString& InAssetContentRoot, TArray<FName>& OutColoredFolders) const;
  997. void GetAssetContentRootFolderColors(const FString& InAssetContentRoot, TMap<FName, FLinearColor>& OutFoldersColor) const;
  998. /** If input path is root content path */
  999. bool IsRootFolder(const FString& InPath) const;
  1000. /** If input path is root content path */
  1001. bool IsRootFolders(const TArray<FString>& InPaths) const;
  1002. /** Add root content folder */
  1003. bool AddRootFolder(const FString& InPath, TArray<FString>* OutAdded = nullptr, TArray<FString>* OutCombined = nullptr);
  1004. /** Reload root content folders */
  1005. bool ReloadRootFolders(const TArray<FString>& InPaths, TArray<FString>* OutReloaded = nullptr);
  1006. /** Remove root content folders */
  1007. bool RemoveRootFolders(const TArray<FString>& InPaths, TArray<FString>* OutRemovd = nullptr);
  1008. /** Rescan root content folders */
  1009. void ReGatheringFolders(const TArray<FString>& InPaths);
  1010. /** Cache asset data for all assets that match the filter. */
  1011. void CacheAssets(const struct FARFilter& InFilter);
  1012. /** Kick off aysnc cache asset data for all assets that match the filter. */
  1013. void CacheAssetsAsync(const struct FARFilter& InFilter);
  1014. /** Gets a list of all paths that are currently cached below the passed-in base path. */
  1015. void GetOrCacheSubPaths(const FName& InBasePath, TSet<FName>& OutPathList, bool bInRecurse);
  1016. /** Gets a list of all paths that are currently cached below the passed-in base path. */
  1017. void GetCachedSubPaths(const FName& InBasePath, TSet<FName>& OutPathList, bool bInRecurse);
  1018. /** Get or cache asset dependency info. */
  1019. FExtAssetDependencyInfo GetOrCacheAssetDependencyInfo(const FExtAssetData& InAssetData, bool bShowProgess = false);
  1020. /** Get cached asset dependency info. */
  1021. const FExtAssetDependencyInfo* GetCachedAssetDependencyInfo(const FExtAssetData& InAssetData) const;
  1022. bool RemoveCachedAssetDependencyInfo(const FExtAssetData& InAssetData);
  1023. bool IsCachedDependencyInfoInValid(const FExtAssetData& InAssetData, bool bTreatSoftErrorAsInvalid = false) const;
  1024. /** Get or cache an assets by file path. */
  1025. FExtAssetData* GetOrCacheAssetByFilePath(const FName& InFilePath, bool bDelayParse = false);
  1026. /** Gets assets by directory, cache them if not already. */
  1027. TMap<FName, TArray<FExtAssetData*>>& GetOrCacheAssetsByFolder(const FName& InDirectory, bool bDelayParse = false);
  1028. /** Gets assets by asset class, cache them if not already. */
  1029. TMap<FName, TArray<FExtAssetData*>>& GetOrCacheAssetsByClass(const TSet<FName>& InPaths, bool bRecursively);
  1030. /** Get cached asset by file path. */
  1031. FExtAssetData* GetCachedAssetByFilePath(const FName& InFilePath);
  1032. /** Get cached asset by package name. */
  1033. FExtAssetData* GetCachedAssetByPackageName(const FName& InPackageName);
  1034. /** Gets cached assets by directory. */
  1035. TArray<FExtAssetData*> GetCachedAssetsByFolder(const FName& InDirectory);
  1036. /** Gets cached assets by asset class. */
  1037. TArray<FExtAssetData*> GetCachedAssetsByClass(const FName& InClass);
  1038. const TMap<FName, FName>& GetCachedAssetContentRootConfigDirs() const;
  1039. const TMap<FName, FName>& GetCachedAssetContentRootHostDirs() const;
  1040. #if ECB_WIP_THUMB_CACHE
  1041. /** Searches for an object's thumbnail in memory and returns it if found */
  1042. const FObjectThumbnail* FindCachedThumbnail(const FName& InFilePath);
  1043. #endif
  1044. /** If input folder has any packages. */
  1045. bool IsEmptyFolder(const FString& FolderPath);
  1046. /** If assets in the input folder been fully parsed. */
  1047. bool IsFolderAssetsFullyParsed(const FString& FolderPath) const;
  1048. /** Checks a filter to make sure there are no illegal entries */
  1049. bool IsFilterValid(const FARFilter& Filter, bool bAllowRecursion);
  1050. /** Modifies passed in filter to make it safe for use on FAssetRegistryState. This expands recursive paths and classes */
  1051. void ExpandRecursiveFilter(const FARFilter& InFilter, FARFilter& ExpandedFilter);
  1052. /** Helper functions to extract asset import information from asset registry tags */
  1053. TOptional<FAssetImportInfo> ExtractAssetImportInfo(const FExtAssetData& AssetData) const;
  1054. void PrintCacheStatus();
  1055. /** Clear cached assets and paths */
  1056. void ClearCache();
  1057. void UpdateCacheByRemovedFolders(const TArray<FString>& InRemovedFolders);
  1058. void StartFolderGathering(const FString& InParentFolder);
  1059. void StartOrCancelAssetGathering(const TArray<FName>& InAssetPaths, int32 TotoalFiltered);
  1060. public:
  1061. #if ECB_WIP_CACHEDB
  1062. bool LoadCacheDBWithFilePicker();
  1063. bool LoadCacheDB(bool bSilent = true);
  1064. bool SaveCacheDB(bool bSilent = true);
  1065. bool PurgeCacheDB(bool bSilent = true);
  1066. void SwitchCacheMode();
  1067. int32 GetNumFoldersInCache() const { return State.NumFoldersInCache; }
  1068. int32 GetNumAssetsInCache() const { return State.NumAssetsInCache; }
  1069. int32 GetNumFoldersInMem() const { return State.CachedSubPaths.Num(); }
  1070. int32 GetNumAssetsInMem() const { return State.CachedAssetsByFilePath.Num(); }
  1071. #endif
  1072. private:
  1073. bool CombineRootContentPaths();
  1074. void CacheRootContentPathInfo();
  1075. void CacheFolderColor(const FName& InAssetContentRootDir);
  1076. /** Returns the names of all subclasses of the class whose name is ClassName */
  1077. void GetSubClasses(const TArray<FTopLevelAssetPath>& InClassPaths, const TSet<FTopLevelAssetPath>& ExcludedClassNames, TSet<FTopLevelAssetPath>& SubClassNames) const;
  1078. void GetSubClasses_Recursive(const FTopLevelAssetPath& InClassName, TSet<FTopLevelAssetPath>& SubClassNames, TSet<FTopLevelAssetPath>& ProcessedClassNames, const TMap<FTopLevelAssetPath, TSet<FTopLevelAssetPath>>& ReverseInheritanceMap, const TSet<FTopLevelAssetPath>& ExcludedClassNames) const;
  1079. void StopAllBackgroundGathering();
  1080. private:
  1081. /** The array of root content folders */
  1082. TArray<FString> RootContentPaths;
  1083. TMap<FString, FRootContentPathInfo> RootContentPathsInfo;
  1084. /** Asset data and folder caches */
  1085. FExtAssetRegistryStateCache State;
  1086. /** Folder Gathering */
  1087. TSharedPtr<class FExtFolderGatherer> BackgroundFolderGatherer;
  1088. TSet<FName> BackgroundGatheringFolders;
  1089. FName BackgroundGatheringSubFolder = NAME_None;
  1090. /** Asset Gathering */
  1091. TSharedPtr<class FExtAssetGatherer> BackgroundAssetGatherer;
  1092. };
  1093. /**
  1094. * Helpers to export root content paths
  1095. */
  1096. struct FRootContentPathsExporter
  1097. {
  1098. //static void ImportAssets(const TArray<FExtAssetData>& InAssetDatas, const FExtAssetImportSetting& ImportSetting);
  1099. };
  1100. /**
  1101. * Helpers to import uasset files into current project
  1102. */
  1103. struct FExtAssetImporter
  1104. {
  1105. static void ImportAssets(const TArray<FExtAssetData>& InAssetDatas, const FUAssetImportSetting& ImportSetting);
  1106. static void ImportAssetsByFilePaths(const TArray<FString>& InAssetFilePaths, const FUAssetImportSetting& ImportSetting);
  1107. static void ImportAssetsToFolderPackagePath(const TArray<FExtAssetData>& InAssetDatas, const FUAssetImportSetting& ImportSetting, const FString& InDestPackagePath);
  1108. static void ImportAssetsWithPathPicker(const TArray<FExtAssetData>& InAssetDatas, const FUAssetImportSetting& ImportSetting);
  1109. static void ImportProjectFolderColors(const FString& InRootOrHost);
  1110. static void ExportAssets(const TArray<FExtAssetData>& InAssetDatas);
  1111. static void ZipUpSourceAssets(const TArray<FExtAssetData>& InAssetDatas);
  1112. static bool IsValidImportToPluginName(const FName& InPluginName, FString* OutInValidReason = nullptr, FString* OutValidPluginContentDir = nullptr);
  1113. private:
  1114. static void DoImportAssets(const TArray<FExtAssetData>& InAssetDatas, const FUAssetImportSetting& ImportSetting);
  1115. static bool ValidateImportSetting(const FUAssetImportSetting& ImportSetting);
  1116. };
  1117. /**
  1118. * Helpers to validate a uasset file
  1119. */
  1120. struct FExtAssetValidator
  1121. {
  1122. static bool ValidateDependency(const TArray<FExtAssetData*>& InAssetDatas, FString* OutValidateResultPtr = nullptr, bool bShowProgess = false, EDependencyNodeStatus* OutAssetStatus = nullptr);
  1123. static bool ValidateDependency(const TArray<FExtAssetData>& InAssetDatas, FString* OutValidateResultPtr = nullptr, bool bShowProgess = false, EDependencyNodeStatus* OutAssetStatus = nullptr);
  1124. static void InValidateDependency(const TArray<FExtAssetData>& InAssetDatas);
  1125. };
  1126. /**
  1127. * Helpers count asset data
  1128. */
  1129. struct FExtAssetCountInfo
  1130. {
  1131. int32 TotalAssetsIncludeUMap;
  1132. int32 TotalUAsset;
  1133. int32 TotalUMap;
  1134. int32 TotalInvalid;
  1135. int32 TotalFileSizes;
  1136. };
  1137. struct FExtAssetCounter
  1138. {
  1139. static int32 CountAssetsByFolder(const FString& InFolder, FExtAssetCountInfo& OutCountInfo);
  1140. };
  1141. /**
  1142. * Folder gathering policy
  1143. */
  1144. struct FExtFolderGatherPolicy
  1145. {
  1146. struct FFolderVisitor : public IPlatformFile::FDirectoryVisitor
  1147. {
  1148. virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) override
  1149. {
  1150. if (bIsDirectory)
  1151. {
  1152. bool bShouldIgnore = false;
  1153. if (bIgnoreFoldersStartWithDot || IgnoreFolders.Num() > 0)
  1154. {
  1155. FString PathLeft = FPaths::GetPathLeaf(FilenameOrDirectory);
  1156. if (bIgnoreFoldersStartWithDot && PathLeft.StartsWith(TEXT(".")))
  1157. {
  1158. bShouldIgnore = true;
  1159. }
  1160. if (!bShouldIgnore && IgnoreFolders.Num() > 0)
  1161. {
  1162. for (const FString& IgnoreFolder : IgnoreFolders)
  1163. {
  1164. if (IgnoreFolder.Equals(PathLeft, ESearchCase::IgnoreCase))
  1165. {
  1166. bShouldIgnore = true;
  1167. break;
  1168. }
  1169. }
  1170. }
  1171. }
  1172. if (!bShouldIgnore)
  1173. {
  1174. Directories.Add(FilenameOrDirectory);
  1175. }
  1176. }
  1177. else if (FExtAssetSupport::IsSupportedPackageFilename(FilenameOrDirectory))
  1178. {
  1179. PackageFiles.Add(FilenameOrDirectory);
  1180. }
  1181. #if ECB_WIP // Gather Content Dir
  1182. else
  1183. {
  1184. }
  1185. #endif
  1186. return true;
  1187. }
  1188. void Reset()
  1189. {
  1190. Directories.Reset();
  1191. PackageFiles.Reset();
  1192. }
  1193. FFolderVisitor()
  1194. {
  1195. }
  1196. FFolderVisitor(bool bInIgnoreFoldersStartWithDot, const TArray<FString>& InIgnoreFolders)
  1197. : bIgnoreFoldersStartWithDot(bInIgnoreFoldersStartWithDot)
  1198. , IgnoreFolders(InIgnoreFolders)
  1199. {
  1200. }
  1201. TArray<FName> Directories;
  1202. TArray<FName> PackageFiles;
  1203. bool bIgnoreFoldersStartWithDot = false;
  1204. TArray<FString> IgnoreFolders;
  1205. };
  1206. FFolderVisitor& GetResetedFolderVisitor()
  1207. {
  1208. FolderVisitor.Reset();
  1209. return FolderVisitor;
  1210. }
  1211. void UpdateWith(const FExtFolderGatherPolicy& InNewPolicy)
  1212. {
  1213. FolderVisitor.bIgnoreFoldersStartWithDot = InNewPolicy.IsIgnoreFoldersStartWithDot();
  1214. FolderVisitor.IgnoreFolders = InNewPolicy.GetIgnoreFolders();
  1215. }
  1216. bool IsIgnoreFoldersStartWithDot() const
  1217. {
  1218. return FolderVisitor.bIgnoreFoldersStartWithDot;
  1219. }
  1220. const TArray<FString>& GetIgnoreFolders() const
  1221. {
  1222. return FolderVisitor.IgnoreFolders;
  1223. }
  1224. FExtFolderGatherPolicy(bool bInIgnoreFoldersStartWithDot, const TArray<FString>& InIgnoreFolders)
  1225. : FolderVisitor(bInIgnoreFoldersStartWithDot, InIgnoreFolders)
  1226. {
  1227. }
  1228. FExtFolderGatherPolicy() {}
  1229. private:
  1230. FFolderVisitor FolderVisitor;
  1231. };
  1232. /**
  1233. * Gather folders recursively
  1234. */
  1235. class FExtFolderGatherer : public FRunnable
  1236. {
  1237. public:
  1238. FExtFolderGatherer(const FString& InGatheringFolder);
  1239. FExtFolderGatherer(const FString& InGatheringFolder, const FExtFolderGatherPolicy& InGatherPolicy);
  1240. virtual ~FExtFolderGatherer();
  1241. // FRunnable implementation
  1242. virtual bool Init() override;
  1243. virtual uint32 Run() override;
  1244. virtual void Stop() override;
  1245. virtual void Exit() override;
  1246. void EnsureCompletion();
  1247. void AddSearchFolder(const FString& InFolderToSearch, const FExtFolderGatherPolicy* InUpdatedGatherPolicy);
  1248. void StopSearchFolder(const FString& InFolderToStopSearch);
  1249. bool GetAndTrimGatherResult(TArray<FExtFolderGatherResult>& OutGatherResults, double& OutGatherTime, TArray<FExtFolderGatherResult>& OutSubDirGatherResults, TArray<FExtAssetContentRootGatherResult>& OutAssetContentRootDirGatherResults);
  1250. private:
  1251. FExtFolderGatherPolicy GatherPolicy;
  1252. private:
  1253. struct FPathTree
  1254. {
  1255. FPathTree(const FName& InParent, const FName& InFolder, bool bInEmpty)
  1256. : Parent(InParent)
  1257. , Folder(InFolder)
  1258. , bEmptyFolder(bInEmpty)
  1259. {}
  1260. FName Parent;
  1261. FName Folder;
  1262. bool bEmptyFolder;
  1263. void MarkPathTreeNotEmpty(TMap<FName, FPathTree>& PathTrees)
  1264. {
  1265. bEmptyFolder = false;
  1266. for (FPathTree* ParentTreePtr = PathTrees.Find(Parent); ParentTreePtr; ParentTreePtr = PathTrees.Find(ParentTreePtr->Parent))
  1267. {
  1268. ParentTreePtr->bEmptyFolder = false;
  1269. }
  1270. }
  1271. };
  1272. /** Get all child directories of input base directory */
  1273. void GetDirectoriesAndPackages(const FName& InBaseDirectory, TArray<FName>& OutDirList, TArray<FName>& OutFilePaths);
  1274. /** Get all child directories and packages of input base directory, return false if skipped */
  1275. bool GetAllDirectoriesAndPackagesRecursively(const FName& InBaseDirectory, TArray<FName>& OutSubPaths, TMap<FName, TArray<FName>>& OutRecusriveSubPaths, TMap<FName, TArray<FName>>& OutFilePaths);
  1276. void GetChildDirectoriesAndPackages(const FName& InRoot, const FName& InParent, const TArray<FName>& InBaseDirs, TArray<FName>& OutSubPaths, TMap<FName, TArray<FName>>& OutRecusriveSubPaths, TMap<FName, TArray<FName>>& OutputFilePaths, TMap<FName, FPathTree>& OutputPathTrees, bool bFoundAssetContentRoot = false);
  1277. private:
  1278. TArray<FString> DirectoriesToSearch;
  1279. TArray<FExtFolderGatherResult> RootDirGatherResults;
  1280. TArray<FExtFolderGatherResult> SubDirGatherResults;
  1281. TArray<FExtAssetContentRootGatherResult> AssetContentRootGatherResults;
  1282. /** How many seconds spent on last gathering */
  1283. double GatherTime;
  1284. /** A critical section to protect data transfer to other threads */
  1285. FCriticalSection WorkerThreadCriticalSection;
  1286. /** Thread to run the cleanup FRunnable on */
  1287. FRunnableThread* Thread;
  1288. /** Signal to stop */
  1289. bool bRequestToStop;
  1290. /** Signal to skip current search folder */
  1291. bool bRequestToSkipCurrentSearchFolder;
  1292. /** Current searching folder */
  1293. FString CurrentSearchFolder;
  1294. };
  1295. /**
  1296. * Gather folders recursively
  1297. */
  1298. class FExtAssetGatherer : public FRunnable
  1299. {
  1300. public:
  1301. FExtAssetGatherer();
  1302. virtual ~FExtAssetGatherer();
  1303. // FRunnable implementation
  1304. virtual bool Init() override;
  1305. virtual uint32 Run() override;
  1306. virtual void Stop() override;
  1307. virtual void Exit() override;
  1308. void EnsureCompletion();
  1309. void AddBatchToGather(const TArray<FName>& InBatch);
  1310. void CancelGather();
  1311. bool GetAndTrimGatherResult(FExtAssetGatherResult& OutGatherResults, double& OutGatherTime, int32& OutLeft);
  1312. private:
  1313. bool DoGatherAssetByFilePath(const FName& InFilePath, FExtAssetData& OutExtAssetData) const;
  1314. private:
  1315. TArray<FName> GatherBatch;
  1316. FExtAssetGatherResult GatherResult;
  1317. /** How many seconds spent on last gathering */
  1318. double GatherStartTime;
  1319. double GatherTime;
  1320. /** A critical section to protect data transfer to other threads */
  1321. FCriticalSection WorkerThreadCriticalSection;
  1322. /** Thread to run the cleanup FRunnable on */
  1323. FRunnableThread* Thread;
  1324. /** Signal to stop */
  1325. bool bRequestToStop;
  1326. };
  1327. ////////////////////////////////////////////////
  1328. // FExtContentDirFinder
  1329. //
  1330. struct FExtContentDirFinder
  1331. {
  1332. static bool FindWithFile(const FString& InUAssetFilePath, const FString& InFileToFind, bool bExtension, const FString& InContentFolderPattern, FString& OutContentRootPath, FString& OutRelativePath);
  1333. static bool FindFolder(const FString& InUAssetFilePath, const FString& InContentFolderPattern, FString& OutContentRootPath, FString& OutRelativePath);
  1334. static bool FindWithFolder(const FString& InFolderPath, const FString& InFileToFind, bool bExtension);
  1335. };