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] [/Script/EngineSettings.GameMapsSettings]
GameDefaultMap=/Engine/Maps/Templates/OpenWorld GameDefaultMap=/Game/Levels/Test/L_Test.L_Test
EditorStartupMap=/Game/Levels/Test/L_Test.L_Test EditorStartupMap=/Game/Levels/Test/L_Test.L_Test
bUseSplitscreen=False bUseSplitscreen=False
GlobalDefaultGameMode=/Game/Blueprints/GameModes/BP_MainGameMode.BP_MainGameMode_C 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 "IPlatformFilePak.h"
#include "UObject/Class.h" void UContentLoader::BeginDestroy()
#include "UObject/UObjectIterator.h"
namespace
{ {
constexpr auto mountPath = TEXT("/Game/LoadedContent"); //if(mountedFiles.Num() > 0)
//{
// while(mountedFiles.Num() > 0)
// UnmountPak(*mountedFiles.begin());
//
// FPlatformFileManager::Get().RemovePlatformFile(GetPakPlatformFile());
//}
UObject::BeginDestroy();
} }
UClass* UContentLoader::MountAndRegisterPak(FString pakFilePath) UClass* UContentLoader::LoadPak(const FString& pakFilePath)
{ {
if(pakFilePath.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("ContentLoader: Starting to mount pak %s"), *pakFilePath);
FPakPlatformFile* pakFileMgr = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")));
if(!pakFileMgr)
{
UE_LOG(LogTemp, Warning, TEXT("ContentLoader: Unable to get PakPlatformFile."));
return nullptr; return nullptr;
}
pakFilePath = FPaths::ProjectContentDir() / pakFilePath; if(!pakFileMgr->Mount(*pakFilePath, 0))
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("ContentLoader: Starting to mount pak: %s"), *pakFilePath)); UE_LOG(LogTemp, Warning, TEXT("ContentLoader: Unable to mount pak %s."), *pakFilePath);
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Starting to mount pak: %s"), *pakFilePath);
if(!MountPak(*pakFilePath))
return nullptr; return nullptr;
}
UE_LOG(LogTemp, Warning, TEXT("ContentLoader: Pak %s mounted successfully."), *pakFilePath);
TArray<FString> content; TArray<FString> content;
FString mountPoint = GetPakMountContentPath(pakFilePath, content); const FString mountPoint = GetPakMountContent(pakFilePath, &content);
RegisterMountPoint(mountPath, mountPoint); UE_LOG(LogTemp, Log, TEXT("ContentLoader: Pak '%s' contains %d items."), *FPaths::GetCleanFilename(pakFilePath), content.Num());
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());
FPackageName::RegisterMountPoint("/Game/", mountPoint);
for(auto& i : content) for(auto& i : content)
{ {
if(FPaths::GetCleanFilename(i).StartsWith(TEXT("BP_"))) 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' of pak %s."), *i, *pakFilePath);
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Found BP class: '%s'"), *i); return GetPakClass(i);
return LoadPakObjClassReference(i);
} }
} }
return nullptr; return nullptr;
} }
void UContentLoader::BeginDestroy() FString UContentLoader::GetPakMountContent(const FString& pakFilePath, TArray<FString>* content)
{ {
if(mountedFiles.Num() > 0) TArray<FString> contentProxy;
{ if(!content)
while(mountedFiles.Num() > 0) content = &contentProxy;
UnmountPak(*mountedFiles.begin());
FPlatformFileManager::Get().RemovePlatformFile(GetPakPlatformFile()); FString mountPoint, contentPath, contentPathTail;
}
UObject::BeginDestroy();
}
FPakPlatformFile* UContentLoader::GetPakPlatformFile()
{
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();
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();
}
return true;
}
bool UContentLoader::UnmountPak(const FString& path)
{
FPakPlatformFile* pakFileMgr = GetPakPlatformFile();
if(!pakFileMgr)
return false;
bool unmounted = pakFileMgr->Unmount(*path);
if(!unmounted)
{
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();
}
return true;
}
void UContentLoader::RegisterMountPoint(const FString& rootPath, const FString& contentPath)
{
FPackageName::RegisterMountPoint(rootPath, contentPath);
}
void UContentLoader::UnRegisterMountPoint(const FString& rootPath, const FString& contentPath)
{
FPackageName::UnRegisterMountPoint(rootPath, contentPath);
}
FString UContentLoader::GetPakMountPoint(const FString& pakFilePath)
{
TRefCountPtr<FPakFile> pakFile = new FPakFile(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")), *pakFilePath, false); TRefCountPtr<FPakFile> pakFile = new FPakFile(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")), *pakFilePath, false);
auto pak = pakFile.GetReference();
if(pakFile.GetReference()->IsValid()) 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 {}; if(!contentPath.IsEmpty())
}
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())
{ {
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); return FString::Printf(TEXT("%s/Content/"), *contentPath);
} }
else else if(content->Num())
{ {
content = GetPakContent(pakFilePath, appendPath); const FString fullPath = FString::Printf(TEXT("%s%s"), *mountPoint, *((*content)[0]));
if(content.Num() > 0) if(fullPath.Split("/Content/", &contentPath, &contentPathTail))
{ {
mountPoint = FString::Printf(TEXT("%s%s"), *mountPoint, *content[0]); return FString::Printf(TEXT("%s/Content/"), *contentPath);
if(mountPoint.Split("/Content/", &contentPath, &appendPath))
{
return FString::Printf(TEXT("%s/Content/"), *contentPath);
}
} }
} }
return {}; return FString("");
} }
UClass* UContentLoader::LoadPakObjClassReference(const FString& pakContentPath) UClass* UContentLoader::GetPakClass(const FString& pakContentPath)
{ {
FString assetName = FString::Printf(TEXT("%s/%s.%s_C"), mountPath, *FPaths::GetBaseFilename(pakContentPath, false), *FPaths::GetBaseFilename(pakContentPath, true)); 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;
}
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("ContentLoader: Loading '%s' class"), *assetName)); bool UContentLoader::UnloadPak(const FString& pakFilePath)
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Loading '%s' class"), *assetName); {
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 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: public:
UFUNCTION(BlueprintCallable, Category = "ContentLoader") UFUNCTION(BlueprintCallable, Category = "ContentLoader")
UClass* MountAndRegisterPak(FString pakFilePath); UClass* LoadPak(const FString& pakFilePath);
protected: protected:
virtual void BeginDestroy() override; virtual void BeginDestroy() override;
class FPakPlatformFile* GetPakPlatformFile(); UFUNCTION(BlueprintCallable, Category = "ContentLoader")
bool UnloadPak(const FString& pakFilePath);
bool MountPak(const FString& path); protected:
bool UnmountPak(const FString& path); FString GetPakMountContent(const FString& pakFilePath, TArray<FString>* content = nullptr);
UClass* GetPakClass(const FString& pakContentPath);
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;
}; };