Files
integration/Source/Integration/AssetLookup.cpp
2026-02-27 13:31:06 -05:00

158 lines
5.6 KiB
C++

#include "AssetLookup.h"
#include "AssetRegistry/IAssetRegistry.h"
#include "AssetRegistry/AssetData.h"
#include "AssetRegistry/AssetRegistryState.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/GameInstance.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::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
RebuildIndex();
}
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<FAssetData> FoundData;
TMap<FName, FString> 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<FString> 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 = UGameplayStatics::GetGameInstance(Context)->GetSubsystem<UlxAssetLookup>();
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<AActor> &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<UUserWidget> &Result, const UObject *Context, const FString &Name)
{
Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UUserWidget::StaticClass(), Name);
return Result ? Valid : NotValid;
}
ElxValidOrNotValid UlxAssetLookup::LoadLuaWidgetAsset(
TSubclassOf<UlxLuaWidget> &Result, const UObject *Context, const FString &Name)
{
Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UlxLuaWidget::StaticClass(), Name);
return Result ? Valid : NotValid;
}