#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" void UlxAssetLookup::LogMaybeError(bool Error, const TCHAR *Message, const TCHAR *Path) { if (Error) { UE_LOG(LogLuprexIntegration, Error, TEXT("%s: %s"), Message, Path); } else { UE_LOG(LogLuprexIntegration, Display, TEXT("%s: %s"), Message, Path); } } 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, const 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); } FString UlxAssetLookup::GetAssetPath(const UObject *Context, const UClass *Class, const FString &Name) { const UlxAssetLookup *Lookup = ALuprexGameModeBase::FromContext(Context)->GetAssetLookup(); const FString *Path = Lookup->AssetPaths.Find(MakeTuple(Class->GetName(), FName(Name))); if (Path == nullptr) { return FString(); } return *Path; } ElxValidOrNotValid UlxAssetLookup::LoadStaticMeshAsset( UStaticMesh *&Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { Result = nullptr; FString Path = GetAssetPath(Context, UStaticMesh::StaticClass(), Name); if (Path.IsEmpty()) { LogMaybeError(ErrorIfNotFound, TEXT("Static Mesh not found"), *Name); Result = nullptr; return NotValid; } Result = LoadObject(nullptr, *Path); if (Result == nullptr) { LogMaybeError(ErrorIfNotFound, TEXT("Cannot load Static Mesh"), *Path); Result = nullptr; return NotValid; } return Valid; } ElxValidOrNotValid UlxAssetLookup::LoadAnimSequenceAsset( UAnimSequence *&Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { Result = nullptr; FString Path = GetAssetPath(Context, UAnimSequence::StaticClass(), Name); if (Path.IsEmpty()) { LogMaybeError(ErrorIfNotFound, TEXT("Anim Sequence not found"), *Name); Result = nullptr; return NotValid; } Result = LoadObject(nullptr, *Path); if (Result == nullptr) { LogMaybeError(ErrorIfNotFound, TEXT("Cannot load Anim Sequence"), *Path); Result = nullptr; return NotValid; } return Valid; } ElxValidOrNotValid UlxAssetLookup::LoadTangibleBlueprintAsset( TSubclassOf &Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { FString Path = GetAssetPath(Context, UBlueprint::StaticClass(), Name); if (Path.IsEmpty()) { LogMaybeError(ErrorIfNotFound, TEXT("Tangible not found"), *Name); Result = nullptr; return NotValid; } Result = LoadClass(nullptr, *UnderscoreC(Path)); if (Result == nullptr) { LogMaybeError(ErrorIfNotFound, TEXT("Tangible load failed, not an actor blueprint"), *Path); Result = nullptr; return NotValid; } UFunction *aqchanged = Result->FindFunctionByName(FName(TEXT("Animation Queue Changed"))); if ((aqchanged == nullptr)||(aqchanged->ParmsSize != 0)) { LogMaybeError(ErrorIfNotFound, TEXT("Tangible does not have 'Animation Queue Changed' function"), *Path); Result = nullptr; return NotValid; } return Valid; } ElxValidOrNotValid UlxAssetLookup::LoadUserWidgetAsset( TSubclassOf &Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { Result = nullptr; FString Path = GetAssetPath(Context, UWidgetBlueprint::StaticClass(), Name); if (Path.IsEmpty()) { LogMaybeError(ErrorIfNotFound, TEXT("Widget not Found"), *Name); Result = nullptr; return NotValid; } Result = LoadClass(nullptr, *UnderscoreC(Path)); if (Result == nullptr) { LogMaybeError(ErrorIfNotFound, TEXT("Cannot load widget, not a UUserWidget"), *Path); Result = nullptr; return NotValid; } return Valid; } ElxValidOrNotValid UlxAssetLookup::LoadLuaWidgetAsset( TSubclassOf &Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) { Result = nullptr; FString Path = GetAssetPath(Context, UWidgetBlueprint::StaticClass(), Name); if (Path.IsEmpty()) { LogMaybeError(ErrorIfNotFound, TEXT("Widget not on search path"), *Name); Result = nullptr; return NotValid; } Result = LoadClass(nullptr, *UnderscoreC(Path)); if (Result == nullptr) { LogMaybeError(ErrorIfNotFound, TEXT("Cannot load widget, not a UlxLuaWidget"), *Path); Result = nullptr; return NotValid; } return Valid; }