RapyutaSimulationPlugins
RRAssetUtils.h
Go to the documentation of this file.
1 
13 #pragma once
14 
15 
16 
17 // UE
18 
19 #include "AssetRegistry/AssetRegistryModule.h"
20 
21 #include "Engine/ObjectLibrary.h"
22 
23 #include "Engine/StaticMesh.h"
24 
25 #include "Kismet/BlueprintFunctionLibrary.h"
26 
27 #include "Materials/Material.h"
28 
29 #include "PhysicalMaterials/PhysicalMaterial.h"
30 
31 #include "UObject/Package.h"
32 
33 #include "UObject/SavePackage.h"
34 
35 
36 
37 #if WITH_EDITOR
38 
39 #include "AssetToolsModule.h"
40 
41 #include "IAssetTools.h"
42 
43 #include "UObject/ConstructorHelpers.h"
44 
45 #endif
46 
47 
48 
49 // RapyutaSim
50 
51 #include "Core/RRObjectCommon.h"
52 
54 
55 #include "logUtilities.h"
56 
57 
58 
59 #include "RRAssetUtils.generated.h"
60 
61 
62 
82 class RAPYUTASIMULATIONPLUGINS_API URRAssetUtils : public UBlueprintFunctionLibrary
83 
84 {
85 
86 
87 
88 public:
89 
90  static IAssetRegistry& GetAssetRegistry()
91 
92  {
93 
94  static FAssetRegistryModule& assetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
95 
96  return assetRegistryModule.Get();
97 
98  }
99 
100 
101 
102 #if WITH_EDITOR
103 
104  static IAssetTools& GetAssetToolsModule()
105 
106  {
107 
108  // FModuleManager::LoadModuleChecked are used internally
109 
110  static FAssetToolsModule& assetToolsModule = FAssetToolsModule::GetModule();
111 
112  return assetToolsModule.Get();
113 
114  }
115 
116 #endif
117 
118 
119 
132  static bool GetAssetFilePathOnDisk(const FString& InAssetPath, FString& OutAssetFilePath)
133 
134  {
135 
136  return FPackageName::TryConvertLongPackageNameToFilename(
137 
138  InAssetPath, OutAssetFilePath, FPackageName::GetAssetPackageExtension());
139 
140  }
141 
142 
143 
144  static bool IsAssetPackageValid(const FAssetData& InAssetData, bool bIsLogged = false)
145 
146  {
147 
148  // Package's availability
149 
150  UPackage* assetPackage = InAssetData.GetPackage();
151 
152  if (nullptr == assetPackage)
153 
154  {
155 
156  if (bIsLogged)
157 
158  {
159 
160  UE_LOG_WITH_INFO(
161 
162  LogRapyutaCore, Error, TEXT("[%s] asset's package is not available!"), *InAssetData.AssetName.ToString());
163 
164  }
165 
166  return false;
167 
168  }
169 
170 
171 
172  // Package's validity
173 
174  FString packageFileName;
175 
176  if (false == FPackageName::DoesPackageExist(assetPackage->GetName(),
177 
178 #if ENGINE_MAJOR_VERSION < 5
179 
180  nullptr,
181 
182 #endif
183 
184  &packageFileName))
185 
186  {
187 
188  if (bIsLogged)
189 
190  {
191 
192  UE_LOG_WITH_INFO(LogRapyutaCore,
193 
194  Error,
195 
196  TEXT("[%s] asset's package [%s] does not exist!"),
197 
198  *InAssetData.AssetName.ToString(),
199 
200  *packageFileName);
201 
202  }
203 
204  return false;
205 
206  }
207 
208 
209 
210  // Package's compatibility with this UE version
211 
212  // If a package has never been loaded, a file reader is necessary to find the package file summary for its saved engine
213 
214  // version.
215 
216  TUniquePtr<FArchive> packageReader = TUniquePtr<FArchive>(IFileManager::Get().CreateFileReader(*packageFileName));
217 
218  if (nullptr == packageReader)
219 
220  {
221 
222  UE_LOG_WITH_INFO(LogRapyutaCore, Error, TEXT("Failed creating Package reader for package [%s]!"), *packageFileName);
223 
224  return false;
225 
226  }
227 
228 
229 
230  FPackageFileSummary packageSummary;
231 
232  *packageReader << packageSummary;
233 
234 
235 
236  // Package file UE version
237 
238 #if ENGINE_MAJOR_VERSION < 5
239 
240  const int32 packageFileVersionUE = packageSummary.GetFileVersionUE4();
241 
242 #else
243 
244  const int32 packageFileVersionUE = packageSummary.GetFileVersionUE().ToValue();
245 
246 #endif
247 
248 
249 
250  // Check TOO OLD
251 
252  if (packageFileVersionUE < static_cast<int32>(VER_UE4_OLDEST_LOADABLE_PACKAGE))
253 
254  {
255 
256  if (bIsLogged)
257 
258  {
259 
260  UE_LOG_WITH_INFO(
261 
262  LogRapyutaCore,
263 
264  Error,
265 
266  TEXT("[%s] asset was saved by a previous UE version which is not backward compatible with this one."
267 
268  "Min Required version: [%d] vs Package version: [%d]"),
269 
270  *InAssetData.AssetName.ToString(),
271 
272  static_cast<int32>(VER_UE4_OLDEST_LOADABLE_PACKAGE),
273 
274  packageFileVersionUE);
275 
276  }
277 
278  return false;
279 
280  }
281 
282 
283 
284  // Check TOO NEW
285 
286 #if ENGINE_MAJOR_VERSION < 5
287 
288  const int32 packageFileVersionUEGlobal = GPackageFileUE4Version;
289 
290 #else
291 
292  const int32 packageFileVersionUEGlobal = GPackageFileUEVersion.ToValue();
293 
294 #endif
295 
296 
297 
298  if (packageFileVersionUE > packageFileVersionUEGlobal)
299 
300  {
301 
302  if (bIsLogged)
303 
304  {
305 
306  UE_LOG_WITH_INFO(LogRapyutaCore,
307 
308  Error,
309 
310  TEXT("[%s] asset was saved by a newer UE version [%d], which is not forward compatible "
311 
312  "with the current one[%d]"),
313 
314  *InAssetData.AssetName.ToString(),
315 
316  packageFileVersionUE,
317 
318  packageFileVersionUEGlobal);
319 
320  }
321 
322  return false;
323 
324  }
325 
326 
327 
328  // Check Incompatibility
329 
330  if (false == FEngineVersion::Current().IsCompatibleWith(packageSummary.CompatibleWithEngineVersion))
331 
332  {
333 
334  if (bIsLogged)
335 
336  {
337 
338  UE_LOG_WITH_INFO(LogRapyutaCore,
339 
340  Error,
341 
342  TEXT("[%s] asset's package's version [%s] is incompatible with the current UE version[%s]!"),
343 
344  *InAssetData.AssetName.ToString(),
345 
346  *packageSummary.CompatibleWithEngineVersion.ToString(),
347 
348  *FEngineVersion::Current().ToString());
349 
350  }
351 
352  return false;
353 
354  }
355 
356  return true;
357 
358  }
359 
360 
361 
362  static bool IsAssetDataListValid(const TArray<FAssetData>& InAssetDataList, bool bLoadedCheck, bool bIsLogged = false)
363 
364  {
365 
366  bool bIsAssetValid = true;
367 
368  for (const auto& assetData : InAssetDataList)
369 
370  {
371 
372  // Check [assetData]'s validity
373 
374  if (false == assetData.IsValid())
375 
376  {
377 
378  bIsAssetValid = false;
379 
380  if (bIsLogged)
381 
382  {
383 
384  UE_LOG_WITH_INFO(
385 
386  LogRapyutaCore, Error, TEXT("[%s] asset data info is invalid!"), *assetData.AssetName.ToString());
387 
388  }
389 
390  }
391 
392  else if (false == IsAssetPackageValid(assetData, bIsLogged))
393 
394  {
395 
396  bIsAssetValid = false;
397 
398  }
399 
400  else if (bLoadedCheck && (false == assetData.IsAssetLoaded()))
401 
402  {
403 
404  bIsAssetValid = false;
405 
406  if (bIsLogged)
407 
408  {
409 
410  UE_LOG_WITH_INFO(
411 
412  LogRapyutaCore, Error, TEXT("[%s] asset failed to be loaded!"), *assetData.AssetName.ToString());
413 
414  }
415 
416  }
417 
418 
419 
420  // Print [assetData] if invalid
421 
422  if (false == bIsAssetValid)
423 
424  {
425 
426  if (bIsLogged)
427 
428  {
429 
430  assetData.PrintAssetData();
431 
432  }
433 
434  return false;
435 
436  }
437 
438  }
439 
440  return true;
441 
442  }
443 
444 
445 
468  template<typename T>
469 
470  static void LoadAssetDataList(const FString& InAssetsPath,
471 
472  TArray<FAssetData>& OutAssetDataList,
473 
474  bool bHasBPAsset = false,
475 
476  bool bIsFullLoad = false)
477 
478  {
479 
480  // NOTE: [objectLibrary] is only needed to fill [OutAssetDataList], loaded objects (if [bIsFullLoad]) should be stored explicitly by callers
481 
482  UObjectLibrary* objectLibrary = UObjectLibrary::CreateLibrary(T::StaticClass(), bHasBPAsset, GIsEditor);
483 
484  if (GIsEditor)
485 
486  {
487 
488  objectLibrary->bIncludeOnlyOnDiskAssets = false;
489 
490  }
491 
492 
493 
494  objectLibrary->bRecursivePaths = true;
495 
496  objectLibrary->LoadAssetDataFromPath(InAssetsPath);
497 
498  if (bIsFullLoad)
499 
500  {
501 
502  objectLibrary->LoadAssetsFromAssetData();
503 
504  }
505 
506 
507 
508  objectLibrary->GetAssetDataList(OutAssetDataList);
509 
510  ensure(IsAssetDataListValid(OutAssetDataList, bIsFullLoad, true));
511 
512  }
513 
514 
515 
538  template<typename T>
539 
540  FORCEINLINE static T* LoadObjFromAssetPath(UObject* Outer, const FString& InAssetPath)
541 
542  {
543 
544  if (InAssetPath.IsEmpty())
545 
546  {
547 
548  UE_LOG_WITH_INFO(LogTemp, Error, TEXT("[EMPTY PATH!"))
549 
550  return nullptr;
551 
552  }
553 
554  // This invokes [StaticLoadObject()]
555 
556  return LoadObject<T>(Outer, *InAssetPath);
557 
558  }
559 
560 
561 
574  template<typename T>
575 
576  FORCEINLINE static T* FetchObjectFromAsset(const TCHAR* InAssetPath)
577 
578  {
579 
580  return ConstructorHelpers::FObjectFinderOptional<T>(InAssetPath).Get();
581 
582  }
583 
584 
585 
598  template<typename T>
599 
600  FORCEINLINE static TSubclassOf<T> FetchClassFromAsset(const TCHAR* InClassAssetPath)
601 
602  {
603 
604  // NOTE: For class asset, "_C" is required at the end of class path
605 
606  ConstructorHelpers::FClassFinder<T> classFinder(InClassAssetPath);
607 
608  return classFinder.Class;
609 
610  }
611 
612 
613 
626  static bool DoesAssetExist(const FString& InAssetPath, bool bOnDiskAssetOnly = false)
627 
628  {
629 
630  const auto& assetPackageName = FName(*InAssetPath);
631 
632  return bOnDiskAssetOnly ? GetAssetRegistry().GetAssetPackageDataCopy(assetPackageName).IsSet()
633 
634  : GetAssetRegistry().HasAssets(assetPackageName);
635 
636  }
637 
638 
639 
652  static UPackage* CreatePackageForSavingToAsset(const TCHAR* InPackageName,
653 
654  const EPackageFlags InPackageFlags = (PKG_NewlyCreated | PKG_RuntimeGenerated));
655 
656 
657 
682  static UObject* SaveObjectToAssetInModule(UObject* InObject,
683 
684  const ERRResourceDataType InAssetDataType,
685 
686  const FString& InAssetUniqueName,
687 
688  const TCHAR* InModuleName,
689 
690  bool bSaveDuplicatedObject = false,
691 
692  bool bInStripEditorOnlyContent = false,
693 
694  bool bInAsyncSave = true,
695 
696  bool bInAlwaysOverwrite = false);
697 
724  static UObject* SaveObjectToAsset(UObject* InObject,
725 
726  const FString& InAssetPath,
727 
728  bool bSaveDuplicatedObject = false,
729 
730  bool bInStripEditorOnlyContent = false,
731 
732  bool bInAsyncSave = true,
733 
734  bool bInAlwaysOverwrite = false);
735 
736 
737 
752  static bool SavePackageToAsset(UPackage* InPackage,
753 
754  UObject* InObject,
755 
756  bool bInAsyncSave = true,
757 
758  bool bInAlwaysOverwrite = false);
759 
760 
761 
778  static UClass* FindBlueprintClass(const FString& InBlueprintClassName);
779 
780 
781 
782  /* @brief Find UClass from its asset path name
783 
784  * @param InClassPathName, eg: '/Script/RapyutaSimulationPlugins.TurtlebotBurger'
785 
786  */
787 
788  static UClass* FindClassFromPathName(const FString& InClassPathName)
789 
790  {
791 
792  const FTopLevelAssetPath classAssetPath(InClassPathName);
793 
794  if (UClass* foundClass = FindObject<UClass>(classAssetPath))
795 
796  {
797 
798  return foundClass;
799 
800  }
801 
802  else
803 
804  {
805 
806  TArray<FAssetData> outAssets;
807 
808  GetAssetRegistry().GetAssetsByClass(classAssetPath, outAssets);
809 
810  return (outAssets.Num() > 0) ? outAssets[0].GetClass() : nullptr;
811 
812  }
813 
814  }
815 
816 
817 
840  static UClass* CreateBlueprintClass(UClass* InParentClass,
841 
842  const FString& InBlueprintClassName,
843 
844  const TFunction<void(UObject* InCDO)>& InCDOFunc = nullptr,
845 
846  const bool bInSaveBP = false,
847 
848  const FString& InBPBasePath = TEXT(""));
849 
868  static UBlueprint* CreateBlueprintFromActor(AActor* InActor,
869 
870  const FString& InBlueprintClassName,
871 
872  const bool bInSaveBP,
873 
874  const TFunction<void(UObject* InCDO)>& InCDOFunc = nullptr);
875 
876 };
877 
URRAssetUtils::FetchClassFromAsset
static FORCEINLINE TSubclassOf< T > FetchClassFromAsset(const TCHAR *InClassAssetPath)
Fetch UClass from asset, called in Constructor only.
Definition: RRAssetUtils.h:600
RapyutaSimulationPlugins.h
Unreal Engine Mudule class.
URRAssetUtils::LoadObjFromAssetPath
static FORCEINLINE T * LoadObjFromAssetPath(UObject *Outer, const FString &InAssetPath)
This must not be invoked at Sim initialization since it would flush Async loaders away!
Definition: RRAssetUtils.h:540
URRAssetUtils::FetchObjectFromAsset
static FORCEINLINE T * FetchObjectFromAsset(const TCHAR *InAssetPath)
Fetch UObject from asset, called in Constructor only.
Definition: RRAssetUtils.h:576
URRAssetUtils::GetAssetRegistry
static IAssetRegistry & GetAssetRegistry()
Definition: RRAssetUtils.h:90
URRAssetUtils::IsAssetDataListValid
static bool IsAssetDataListValid(const TArray< FAssetData > &InAssetDataList, bool bLoadedCheck, bool bIsLogged=false)
Definition: RRAssetUtils.h:362
URRAssetUtils::LoadAssetDataList
static void LoadAssetDataList(const FString &InAssetsPath, TArray< FAssetData > &OutAssetDataList, bool bHasBPAsset=false, bool bIsFullLoad=false)
Load asset with UObjectLibrary.
Definition: RRAssetUtils.h:470
URRAssetUtils::IsAssetPackageValid
static bool IsAssetPackageValid(const FAssetData &InAssetData, bool bIsLogged=false)
Definition: RRAssetUtils.h:144
URRAssetUtils::GetAssetFilePathOnDisk
static bool GetAssetFilePathOnDisk(const FString &InAssetPath, FString &OutAssetFilePath)
Get full asset file path on disk of an UE asset.
Definition: RRAssetUtils.h:132
ERRResourceDataType
ERRResourceDataType
Sim resource(Uassets) data types.
Definition: RRObjectCommon.h:174
URRAssetUtils
Asset utils.
Definition: RRAssetUtils.h:82
RRObjectCommon.h
Common objects.
URRAssetUtils::FindClassFromPathName
static UClass * FindClassFromPathName(const FString &InClassPathName)
Definition: RRAssetUtils.h:788
URRAssetUtils::DoesAssetExist
static bool DoesAssetExist(const FString &InAssetPath, bool bOnDiskAssetOnly=false)
Check whether an asset has been created at a path.
Definition: RRAssetUtils.h:626