#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" #include "Engine/SkeletalMesh.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/SkeletalMeshes"), USkeletalMesh::StaticClass(), TEXT("SKM_")); 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); } void UlxAssetLookup::ReportFailedLoad(const FString &ClassName, const FString &Name, const FString &Reason) { static TSet Reported; FString Key = ClassName + TEXT(":") + Name + TEXT(":") + Reason; if (Reported.Contains(Key)) return; Reported.Add(Key); UE_LOG(LogLuprexIntegration, Display, TEXT("Loading %s %s: %s"), *ClassName, *Name, *Reason); } UObject *UlxAssetLookup::LoadAsset(const UObject *Context, UClass *Class, UClass *ChildOf, const FString &Name) { const UlxAssetLookup *Lookup = ALuprexGameModeBase::FromContext(Context)->GetAssetLookup(); const FString *Path = Lookup->AssetPaths.Find(MakeTuple(Class->GetName(), FName(Name))); if (Path == nullptr) { ReportFailedLoad(Class->GetName(), Name, TEXT("asset not found")); 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) { ReportFailedLoad(Class->GetName(), Name, TEXT("unknown load failure")); return nullptr; } if (ChildOf != nullptr) { UClass *ResClass = (UClass *)Result; if (!ResClass->IsChildOf(ChildOf)) { ReportFailedLoad(Class->GetName(), Name, FString::Printf(TEXT("blueprint not a child of %s"), *ChildOf->GetName())); return nullptr; } } return Result; } ElxValidOrNotValid UlxAssetLookup::LoadStaticMeshAsset( UStaticMesh *&Result, const UObject *Context, const FString &Name) { Result = (UStaticMesh *)LoadAsset(Context, UStaticMesh::StaticClass(), nullptr, Name); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadSkeletalMeshAsset( USkeletalMesh *&Result, const UObject *Context, const FString &Name) { Result = (USkeletalMesh *)LoadAsset(Context, USkeletalMesh::StaticClass(), nullptr, Name); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadAnimSequenceAsset( UAnimSequence *&Result, const UObject *Context, const FString &Name) { Result = (UAnimSequence *)LoadAsset(Context, UAnimSequence::StaticClass(), nullptr, Name); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadTangibleBlueprintAsset( TSubclassOf &Result, const UObject *Context, const FString &Name) { Result = (UClass*)LoadAsset(Context, UBlueprint::StaticClass(), AActor::StaticClass(), Name); if (Result == nullptr) return NotValid; UFunction *aqchanged = Result->FindFunctionByName(FName(TEXT("Animation Queue Changed"))); if ((aqchanged == nullptr)||(aqchanged->ParmsSize != 0)) { ReportFailedLoad(TEXT("Blueprint"), Name, TEXT("tangible does not have 'Animation Queue Changed' function")); Result = nullptr; return NotValid; } return Valid; } ElxValidOrNotValid UlxAssetLookup::LoadUserWidgetAsset( TSubclassOf &Result, const UObject *Context, const FString &Name) { Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UUserWidget::StaticClass(), Name); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadLuaWidgetAsset( TSubclassOf &Result, const UObject *Context, const FString &Name) { Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UlxLuaWidget::StaticClass(), Name); return Result ? Valid : NotValid; }