runtime load final

This commit is contained in:
Oleg Petruny 2024-08-16 12:52:53 +02:00
parent 449d943948
commit cc5a0b3c4e
6 changed files with 80 additions and 185 deletions

View File

@ -1,7 +1,7 @@
[/Script/EngineSettings.GameMapsSettings]
GameDefaultMap=/Engine/Maps/Templates/OpenWorld
GameDefaultMap=/Game/Levels/Test/L_Test.L_Test
EditorStartupMap=/Game/Levels/Test/L_Test.L_Test
bUseSplitscreen=False
GlobalDefaultGameMode=/Game/Blueprints/GameModes/BP_MainGameMode.BP_MainGameMode_C

Binary file not shown.

Binary file not shown.

View File

@ -5,210 +5,117 @@
#include "IPlatformFilePak.h"
#include "UObject/Class.h"
#include "UObject/UObjectIterator.h"
namespace
{
constexpr auto mountPath = TEXT("/Game/LoadedContent");
}
UClass* UContentLoader::MountAndRegisterPak(FString pakFilePath)
{
if(pakFilePath.IsEmpty())
return nullptr;
pakFilePath = FPaths::ProjectContentDir() / pakFilePath;
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("ContentLoader: Starting to mount pak: %s"), *pakFilePath));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Starting to mount pak: %s"), *pakFilePath);
if(!MountPak(*pakFilePath))
return nullptr;
TArray<FString> content;
FString mountPoint = GetPakMountContentPath(pakFilePath, content);
RegisterMountPoint(mountPath, mountPoint);
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("ContentLoader: Pak '%s' contains %d items"), *FPaths::GetCleanFilename(pakFilePath), content.Num()));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Pak '%s' contains %d items"), *FPaths::GetCleanFilename(pakFilePath), content.Num());
for(auto& i : content)
{
if(FPaths::GetCleanFilename(i).StartsWith(TEXT("BP_")))
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("ContentLoader: Found BP class: '%s'"), *i));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Found BP class: '%s'"), *i);
return LoadPakObjClassReference(i);
}
}
return nullptr;
}
void UContentLoader::BeginDestroy()
{
if(mountedFiles.Num() > 0)
{
while(mountedFiles.Num() > 0)
UnmountPak(*mountedFiles.begin());
FPlatformFileManager::Get().RemovePlatformFile(GetPakPlatformFile());
}
//if(mountedFiles.Num() > 0)
//{
// while(mountedFiles.Num() > 0)
// UnmountPak(*mountedFiles.begin());
//
// FPlatformFileManager::Get().RemovePlatformFile(GetPakPlatformFile());
//}
UObject::BeginDestroy();
}
FPakPlatformFile* UContentLoader::GetPakPlatformFile()
UClass* UContentLoader::LoadPak(const FString& pakFilePath)
{
FPakPlatformFile* pakPlatformFile = nullptr;
IPlatformFile& platformFile = FPlatformFileManager::Get().GetPlatformFile();
if(!platformFile.GetLowerLevel())
{
pakPlatformFile = new FPakPlatformFile();
pakPlatformFile->Initialize(&platformFile, TEXT(""));
FPlatformFileManager::Get().SetPlatformFile(*pakPlatformFile);
}
else
{
pakPlatformFile = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")));
}
if(!pakPlatformFile)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("ContentLoader: PakFileManager not found"));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: PakFileManager not found"));
}
return pakPlatformFile;
}
bool UContentLoader::MountPak(const FString& path)
{
FPakPlatformFile* pakFileMgr = GetPakPlatformFile();
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Starting to mount pak %s"), *pakFilePath);
FPakPlatformFile* pakFileMgr = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")));
if(!pakFileMgr)
return false;
FString mountPoint = FString::Printf(TEXT("%s/%s"), mountPath, *FPaths::GetBaseFilename(*path));
bool mounted = pakFileMgr->Mount(*path, 0, *mountPoint);
if(!mounted)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("ContentLoader: Pak %s mount failed"), *FPaths::GetCleanFilename(path)));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Pak %s mount failed"), *FPaths::GetCleanFilename(path));
return false;
}
else
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("ContentLoader: Pak %s mounted at %s"), *FPaths::GetCleanFilename(path), *mountPoint));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Pak %s mounted at %s"), *FPaths::GetCleanFilename(path), *mountPoint);
mountedLock.Lock();
mountedFiles.Add(path);
mountedLock.Unlock();
UE_LOG(LogTemp, Warning, TEXT("ContentLoader: Unable to get PakPlatformFile."));
return nullptr;
}
return true;
}
bool UContentLoader::UnmountPak(const FString& path)
{
FPakPlatformFile* pakFileMgr = GetPakPlatformFile();
if(!pakFileMgr)
return false;
bool unmounted = pakFileMgr->Unmount(*path);
if(!unmounted)
if(!pakFileMgr->Mount(*pakFilePath, 0))
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("ContentLoader: Pak %s unmount failed"), *FPaths::GetCleanFilename(path)));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Pak %s unmount failed"), *FPaths::GetCleanFilename(path));
return false;
}
else
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("ContentLoader: Pak %s unmounted successfully"), *FPaths::GetCleanFilename(path)));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Pak %s unmounted successfully"), *FPaths::GetCleanFilename(path));
mountedLock.Lock();
mountedFiles.Remove(path);
mountedLock.Unlock();
UE_LOG(LogTemp, Warning, TEXT("ContentLoader: Unable to mount pak %s."), *pakFilePath);
return nullptr;
}
return true;
UE_LOG(LogTemp, Warning, TEXT("ContentLoader: Pak %s mounted successfully."), *pakFilePath);
TArray<FString> content;
const FString mountPoint = GetPakMountContent(pakFilePath, &content);
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Pak '%s' contains %d items."), *FPaths::GetCleanFilename(pakFilePath), content.Num());
FPackageName::RegisterMountPoint("/Game/", mountPoint);
for(auto& i : content)
{
if(FPaths::GetCleanFilename(i).StartsWith(TEXT("BP_")))
{
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Found BP class '%s' of pak %s."), *i, *pakFilePath);
return GetPakClass(i);
}
}
return nullptr;
}
void UContentLoader::RegisterMountPoint(const FString& rootPath, const FString& contentPath)
FString UContentLoader::GetPakMountContent(const FString& pakFilePath, TArray<FString>* content)
{
FPackageName::RegisterMountPoint(rootPath, contentPath);
}
void UContentLoader::UnRegisterMountPoint(const FString& rootPath, const FString& contentPath)
{
FPackageName::UnRegisterMountPoint(rootPath, contentPath);
}
TArray<FString> contentProxy;
if(!content)
content = &contentProxy;
FString UContentLoader::GetPakMountPoint(const FString& pakFilePath)
{
FString mountPoint, contentPath, contentPathTail;
TRefCountPtr<FPakFile> pakFile = new FPakFile(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")), *pakFilePath, false);
auto pak = pakFile.GetReference();
if(pakFile.GetReference()->IsValid())
{
return pakFile.GetReference()->GetMountPoint();
mountPoint = pakFile.GetReference()->GetMountPoint();
mountPoint.Split("/Content/", &contentPath, &contentPathTail);
for(FPakFile::FFilenameIterator It(*pakFile.GetReference(), false); It; ++It)
if(FPaths::GetExtension(It.Filename()) == TEXT("uasset"))
content->Add(FString::Printf(TEXT("%s%s"), *contentPathTail, *It.Filename()));
}
return {};
}
TArray<FString> UContentLoader::GetPakContent(const FString& pakFilePath, const FString& appendPath)
{
TRefCountPtr<FPakFile> pakFile = new FPakFile(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")), *pakFilePath, false);
TArray<FString> pakContent;
if(pakFile.GetReference()->IsValid())
if(!contentPath.IsEmpty())
{
for(FPakFile::FFilenameIterator it{ *pakFile, false }; it; ++it)
{
if(FPaths::GetExtension(it.Filename()) == TEXT("uasset"))
{
pakContent.Add(FString::Printf(TEXT("%s%s"), *appendPath, *it.Filename()));
}
}
}
return pakContent;
}
FString UContentLoader::GetPakMountContentPath(const FString& pakFilePath, TArray<FString>& content)
{
FString contentPath, appendPath;
FString mountPoint = GetPakMountPoint(pakFilePath);
if(mountPoint.Split("/Content/", &contentPath, &appendPath))
{
content = GetPakContent(pakFilePath, appendPath);
return FString::Printf(TEXT("%s/Content/"), *contentPath);
}
else
else if(content->Num())
{
content = GetPakContent(pakFilePath, appendPath);
if(content.Num() > 0)
{
mountPoint = FString::Printf(TEXT("%s%s"), *mountPoint, *content[0]);
if(mountPoint.Split("/Content/", &contentPath, &appendPath))
const FString fullPath = FString::Printf(TEXT("%s%s"), *mountPoint, *((*content)[0]));
if(fullPath.Split("/Content/", &contentPath, &contentPathTail))
{
return FString::Printf(TEXT("%s/Content/"), *contentPath);
}
}
return FString("");
}
UClass* UContentLoader::GetPakClass(const FString& pakContentPath)
{
const FString assetName = FString::Printf(TEXT("/Game/%s.%s"), *FPaths::GetBaseFilename(pakContentPath, false), *FPaths::GetBaseFilename(pakContentPath, true));
const FString className = assetName + TEXT(".") + FPackageName::GetShortName(assetName) + TEXT("_C");
auto result = StaticLoadClass(UObject::StaticClass(), nullptr, *className);
if(!result)
UE_LOG(LogTemp, Warning, TEXT("ContentLoader: Unable to load pak class: %s."), *className);
return result;
}
bool UContentLoader::UnloadPak(const FString& pakFilePath)
{
FPakPlatformFile* pakFileMgr = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")));
if(!pakFileMgr)
{
UE_LOG(LogTemp, Warning, TEXT("Unable to get PakPlatformFile for pak file (Unmount): %s"), *pakFilePath);
return false;
}
return {};
}
UClass* UContentLoader::LoadPakObjClassReference(const FString& pakContentPath)
{
FString assetName = FString::Printf(TEXT("%s/%s.%s_C"), mountPath, *FPaths::GetBaseFilename(pakContentPath, false), *FPaths::GetBaseFilename(pakContentPath, true));
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("ContentLoader: Loading '%s' class"), *assetName));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Loading '%s' class"), *assetName);
return nullptr;//StaticLoadClass(UObject::StaticClass(), nullptr, *assetName);
if(!pakFileMgr->Unmount(*pakFilePath))
{
UE_LOG(LogTemp, Warning, TEXT("Unable to unmount pak: %s"), *pakFilePath);
return false;
}
const FString mountPoint = GetPakMountContent(pakFilePath);
FPackageName::UnRegisterMountPoint("/Game/", mountPoint);
return true;
}

View File

@ -13,27 +13,15 @@ class UContentLoader : public UObject
public:
UFUNCTION(BlueprintCallable, Category = "ContentLoader")
UClass* MountAndRegisterPak(FString pakFilePath);
UClass* LoadPak(const FString& pakFilePath);
protected:
virtual void BeginDestroy() override;
class FPakPlatformFile* GetPakPlatformFile();
UFUNCTION(BlueprintCallable, Category = "ContentLoader")
bool UnloadPak(const FString& pakFilePath);
bool MountPak(const FString& path);
bool UnmountPak(const FString& path);
void RegisterMountPoint(const FString& rootPath, const FString& contentPath);
void UnRegisterMountPoint(const FString& rootPath, const FString& contentPath);
FString GetPakMountPoint(const FString& pakFilePath);
TArray<FString> GetPakContent(const FString& pakFilePath, const FString& appendPath);
FString GetPakMountContentPath(const FString& pakFilePath, TArray<FString>& content);
UClass* LoadPakObjClassReference(const FString& pakContentPath);
TSet<FString> mountedFiles;
FCriticalSection mountedLock;
protected:
FString GetPakMountContent(const FString& pakFilePath, TArray<FString>* content = nullptr);
UClass* GetPakClass(const FString& pakContentPath);
};