Overhauling asset loading

This commit is contained in:
2025-11-14 02:41:44 -05:00
parent 297cd2f068
commit 3215efeef3
7 changed files with 180 additions and 192 deletions

View File

@@ -7,93 +7,9 @@
#include "Components/Widget.h"
#include "WidgetBlueprint.h"
#include "Blueprint/UserWidget.h"
#include "Animation/AnimSequence.h"
#include "Engine/StaticMesh.h"
void UlxAssetLookup::RebuildIndex()
{
CachedTangibles.Empty();
CachedStaticMeshes.Empty();
IAssetRegistry::GetChecked().WaitForCompletion();
ScanTangibles();
ScanStaticMeshes();
ScanWidgets();
}
void UlxAssetLookup::ScanTangibles()
{
TArray<FAssetData> FoundData;
FARFilter AssetFilter;
AssetFilter.PackagePaths.Add(FName(TEXT("/Game/Tangibles")));
AssetFilter.ClassPaths.Add(UBlueprint::StaticClass()->GetClassPathName());
AssetFilter.bIncludeOnlyOnDiskAssets = true;
AssetFilter.bRecursivePaths = true;
IAssetRegistry::GetChecked().GetAssets(AssetFilter, FoundData);
UE_LOG(LogLuprexIntegration, Display, TEXT("Found %d assets in /Game/Tangibles"), FoundData.Num());
for (const FAssetData &Data : FoundData)
{
FString Path = Data.GetObjectPathString() + TEXT("_C");
CachedTangibles.Add(Data.AssetName, Path);
}
}
void UlxAssetLookup::ScanStaticMeshes()
{
TArray<FAssetData> FoundData;
FARFilter AssetFilter;
AssetFilter.PackagePaths.Add(FName(TEXT("/Game/StaticMeshes")));
AssetFilter.ClassPaths.Add(UStaticMesh::StaticClass()->GetClassPathName());
AssetFilter.bIncludeOnlyOnDiskAssets = true;
AssetFilter.bRecursivePaths = true;
IAssetRegistry::GetChecked().GetAssets(AssetFilter, FoundData);
UE_LOG(LogLuprexIntegration, Display, TEXT("Found %d assets in /Game/StaticMeshes"), FoundData.Num());
for (const FAssetData &Data : FoundData)
{
FString Path = Data.GetObjectPathString();
CachedStaticMeshes.Add(Data.AssetName, Path);
}
}
void UlxAssetLookup::ScanWidgets()
{
TArray<FAssetData> FoundData;
FARFilter AssetFilter;
AssetFilter.PackagePaths.Add(FName(TEXT("/Game/Widgets")));
AssetFilter.ClassPaths.Add(UWidgetBlueprint::StaticClass()->GetClassPathName());
AssetFilter.bIncludeOnlyOnDiskAssets = true;
AssetFilter.bRecursivePaths = true;
IAssetRegistry::GetChecked().GetAssets(AssetFilter, FoundData);
UE_LOG(LogLuprexIntegration, Display, TEXT("Found %d assets in /Game/Widgets"), FoundData.Num());
for (const FAssetData &Data : FoundData)
{
FString Path = Data.GetObjectPathString() + TEXT("_C");
CachedWidgets.Add(Data.AssetName, Path);
}
}
FString UlxAssetLookup::TangibleLoadPath(const FName &AssetName) const
{
const FString *Result = CachedTangibles.Find(AssetName);
if (Result == nullptr) return TEXT("");
return *Result;
}
FString UlxAssetLookup::StaticMeshLoadPath(const FName &AssetName) const
{
const FString *Result = CachedStaticMeshes.Find(AssetName);
if (Result == nullptr) return TEXT("");
return *Result;
}
FString UlxAssetLookup::WidgetLoadPath(const FName &AssetName) const
{
const FString *Result = CachedWidgets.Find(AssetName);
if (Result == nullptr) return TEXT("");
return *Result;
}
void UlxAssetLookup::LogMaybeError(bool Error, const TCHAR *Message, const TCHAR *Path)
{
if (Error)
@@ -106,94 +22,154 @@ void UlxAssetLookup::LogMaybeError(bool Error, const TCHAR *Message, const TCHAR
}
}
UStaticMesh *UlxAssetLookup::LoadStaticMeshAsset(const UObject *Context, const FString &Name, bool ErrorIfNotFound)
{
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
FString Path = mode->GetAssetLookup()->StaticMeshLoadPath(FName(FString("SM_") + Name));
if (Path.IsEmpty())
{
LogMaybeError(ErrorIfNotFound, TEXT("Static mesh not on search path"), *Name);
return nullptr;
}
UStaticMesh *Result = LoadObject<UStaticMesh>(nullptr, *Path);
if (Result == nullptr)
{
LogMaybeError(ErrorIfNotFound, TEXT("Cannot load static mesh"), *Path);
return nullptr;
}
return Result;
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_"));
}
TSubclassOf<AActor> UlxAssetLookup::LoadTangibleBlueprintAsset(const UObject *Context, const FString &Name, bool ErrorIfNotFound) {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
FString Path = mode->GetAssetLookup()->TangibleLoadPath(FName(FString("TAN_") + Name));
void UlxAssetLookup::AddAssets(const TCHAR *Path, const 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);
}
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("Tangible not on search path"), *Name);
return nullptr;
LogMaybeError(ErrorIfNotFound, TEXT("Static Mesh not found"), *Name);
Result = nullptr; return NotValid;
}
UClass *Result = LoadObject<UClass>(nullptr, *Path);
Result = LoadObject<UStaticMesh>(nullptr, *Path);
if (Result == nullptr)
{
LogMaybeError(ErrorIfNotFound, TEXT("Cannot load tangible class"), *Path);
return nullptr;
LogMaybeError(ErrorIfNotFound, TEXT("Cannot load Static Mesh"), *Path);
Result = nullptr; return NotValid;
}
if (!Result->IsChildOf(AActor::StaticClass()))
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("Tangible class is not an actor"), *Path);
return nullptr;
LogMaybeError(ErrorIfNotFound, TEXT("Anim Sequence not found"), *Name);
Result = nullptr; return NotValid;
}
Result = LoadObject<UAnimSequence>(nullptr, *Path);
if (Result == nullptr)
{
LogMaybeError(ErrorIfNotFound, TEXT("Cannot load Anim Sequence"), *Path);
Result = nullptr; return NotValid;
}
return Valid;
}
ElxValidOrNotValid UlxAssetLookup::LoadTangibleBlueprintAsset(
TSubclassOf<AActor> &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<AActor>(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);
return nullptr;
Result = nullptr; return NotValid;
}
return Result;
return Valid;
}
TSubclassOf<UUserWidget> UlxAssetLookup::LoadUserWidgetAsset(const UObject *Context, const FString &Name, bool ErrorIfNotFound) {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
FString Path = mode->GetAssetLookup()->WidgetLoadPath(FName(FString("WB_") + Name));
ElxValidOrNotValid UlxAssetLookup::LoadUserWidgetAsset(
TSubclassOf<UUserWidget> &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<UUserWidget>(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<UlxLuaWidget> &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);
return nullptr;
Result = nullptr; return NotValid;
}
UClass *Result = LoadObject<UClass>(nullptr, *Path);
Result = LoadClass<UlxLuaWidget>(nullptr, *UnderscoreC(Path));
if (Result == nullptr)
{
LogMaybeError(ErrorIfNotFound, TEXT("Cannot load widget blueprint"), *Path);
return nullptr;
LogMaybeError(ErrorIfNotFound, TEXT("Cannot load widget, not a UlxLuaWidget"), *Path);
Result = nullptr; return NotValid;
}
if (!Result->IsChildOf(UUserWidget::StaticClass()))
{
LogMaybeError(ErrorIfNotFound, TEXT("Blueprint does not derive from UUserWidget"), *Path);
return nullptr;
}
return Result;
}
TSubclassOf<UlxLuaWidget> UlxAssetLookup::LoadLuaWidgetAsset(const UObject *Context, const FString &Name, bool ErrorIfNotFound) {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
FString Path = mode->GetAssetLookup()->WidgetLoadPath(FName(FString("WB_") + Name));
if (Path.IsEmpty())
{
LogMaybeError(ErrorIfNotFound, TEXT("Widget not on search path"), *Name);
return nullptr;
}
UClass *Result = LoadObject<UClass>(nullptr, *Path);
if (Result == nullptr)
{
LogMaybeError(ErrorIfNotFound, TEXT("Cannot load widget blueprint"), *Path);
return nullptr;
}
if (!Result->IsChildOf(UlxLuaWidget::StaticClass()))
{
LogMaybeError(ErrorIfNotFound, TEXT("Blueprint does not derive from UlxLuaWidget"), *Path);
return nullptr;
}
return Result;
return Valid;
}