#include "AssetLookup.h" #include "AssetRegistry/IAssetRegistry.h" #include "AssetRegistry/AssetData.h" #include "AssetRegistry/AssetRegistryState.h" #include "LuprexGameModeBase.h" #include "Components/Widget.h" #include "WidgetBlueprint.h" #include "Blueprint/UserWidget.h" #include "Animation/AnimSequence.h" #include "Engine/StaticMesh.h" const ElxValidOrNotValid NotValid = ElxValidOrNotValid::NotValid; const ElxValidOrNotValid Valid = ElxValidOrNotValid::Valid; void UlxAssetLookup::RebuildIndex() { IAssetRegistry::GetChecked().WaitForCompletion(); AssetPaths.Empty(); AddAssets(TEXT("/Game/StaticMeshes"), UStaticMesh::StaticClass(), TEXT("SM_")); AddAssets(TEXT("/Game/AnimSequences"), UAnimSequence::StaticClass(), TEXT("SEQ_")); AddAssets(TEXT("/Game/Tangibles"), UBlueprint::StaticClass(), TEXT("TAN_")); AddAssets(TEXT("/Game/Widgets"), UWidgetBlueprint::StaticClass(), TEXT("WB_")); } void UlxAssetLookup::AddAssets(const TCHAR *Path, UClass *Class, const TCHAR *NamePrefix) { TArray FoundData; TMap Result; FARFilter AssetFilter; AssetFilter.PackagePaths.Add(FName(Path)); AssetFilter.ClassPaths.Add(Class->GetClassPathName()); AssetFilter.bIncludeOnlyOnDiskAssets = true; AssetFilter.bRecursivePaths = true; IAssetRegistry::GetChecked().GetAssets(AssetFilter, FoundData); FString FSNamePrefix(NamePrefix); for (const FAssetData &Data : FoundData) { FString AssetName = Data.AssetName.ToString(); if (AssetName.StartsWith(FSNamePrefix)) { FName ShortName(AssetName.RightChop(FSNamePrefix.Len())); AssetPaths.Add(MakeTuple(Class->GetName(), ShortName), Data.GetObjectPathString()); } } UE_LOG(LogLuprexIntegration, Display, TEXT("Found %d assets of type %s in %s"), FoundData.Num(), *Class->GetName(), Path); } UObject *UlxAssetLookup::LoadAsset(const UObject *Context, UClass *Class, UClass *ChildOf, const FString &Name, bool ErrorIfNotFound) { const UlxAssetLookup *Lookup = ALuprexGameModeBase::FromContext(Context)->GetAssetLookup(); const FString *Path = Lookup->AssetPaths.Find(MakeTuple(Class->GetName(), FName(Name))); if (Path == nullptr) { if (ErrorIfNotFound) { UE_LOG(LogLuprexIntegration, Error, TEXT("Loading %s %s: asset not found"), *Class->GetName(), *Name); } return nullptr; } UObject *Result; if (ChildOf == nullptr) { Result = StaticLoadObject(Class, nullptr, **Path); } else { Result = StaticLoadObject(UClass::StaticClass(), nullptr, *((*Path) + FString(TEXT("_C")))); } if (Result == nullptr) { UE_LOG(LogLuprexIntegration, Error, TEXT("Loading %s %s: unknown load failure"), *Class->GetName(), *Name); return nullptr; } if (ChildOf != nullptr) { UClass *ResClass = (UClass *)Result; if (!ResClass->IsChildOf(ChildOf)) { UE_LOG(LogLuprexIntegration, Error, TEXT("Loading %s %s: blueprint not a child of %s"), *Class->GetName(), *Name, *ChildOf->GetName()); return nullptr; } } return Result; } ElxValidOrNotValid UlxAssetLookup::LoadStaticMeshAsset( UStaticMesh *&Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { Result = (UStaticMesh *)LoadAsset(Context, UStaticMesh::StaticClass(), nullptr, Name, ErrorIfNotFound); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadAnimSequenceAsset( UAnimSequence *&Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { Result = (UAnimSequence *)LoadAsset(Context, UAnimSequence::StaticClass(), nullptr, Name, ErrorIfNotFound); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadTangibleBlueprintAsset( TSubclassOf &Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { Result = (UClass*)LoadAsset(Context, UBlueprint::StaticClass(), AActor::StaticClass(), Name, ErrorIfNotFound); if (Result == nullptr) return NotValid; UFunction *aqchanged = Result->FindFunctionByName(FName(TEXT("Animation Queue Changed"))); if ((aqchanged == nullptr)||(aqchanged->ParmsSize != 0)) { UE_LOG(LogLuprexIntegration, Error, TEXT("Loading Blueprint %s: Tangible does not have 'Animation Queue Changed' function"), *Name); Result = nullptr; return NotValid; } return Valid; } ElxValidOrNotValid UlxAssetLookup::LoadUserWidgetAsset( TSubclassOf &Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UUserWidget::StaticClass(), Name, ErrorIfNotFound); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadLuaWidgetAsset( TSubclassOf &Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UlxLuaWidget::StaticClass(), Name, ErrorIfNotFound); return Result ? Valid : NotValid; }