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"
#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() void UContentLoader::BeginDestroy()
{ {
if(mountedFiles.Num() > 0) //if(mountedFiles.Num() > 0)
{ //{
while(mountedFiles.Num() > 0) // while(mountedFiles.Num() > 0)
UnmountPak(*mountedFiles.begin()); // UnmountPak(*mountedFiles.begin());
//
FPlatformFileManager::Get().RemovePlatformFile(GetPakPlatformFile()); // FPlatformFileManager::Get().RemovePlatformFile(GetPakPlatformFile());
} //}
UObject::BeginDestroy(); UObject::BeginDestroy();
} }
FPakPlatformFile* UContentLoader::GetPakPlatformFile() UClass* UContentLoader::LoadPak(const FString& pakFilePath)
{ {
FPakPlatformFile* pakPlatformFile = nullptr; UE_LOG(LogTemp, Log, TEXT("ContentLoader: Starting to mount pak %s"), *pakFilePath);
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();
FPakPlatformFile* pakFileMgr = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")));
if(!pakFileMgr) 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, Warning, TEXT("ContentLoader: Unable to get PakPlatformFile."));
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Pak %s mount failed"), *FPaths::GetCleanFilename(path)); return nullptr;
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; if(!pakFileMgr->Mount(*pakFilePath, 0))
}
bool UContentLoader::UnmountPak(const FString& path)
{ {
FPakPlatformFile* pakFileMgr = GetPakPlatformFile(); UE_LOG(LogTemp, Warning, TEXT("ContentLoader: Unable to mount pak %s."), *pakFilePath);
return nullptr;
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; 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);
}
} }
void UContentLoader::RegisterMountPoint(const FString& rootPath, const FString& contentPath) return nullptr;
{
FPackageName::RegisterMountPoint(rootPath, contentPath);
}
void UContentLoader::UnRegisterMountPoint(const FString& rootPath, const FString& contentPath)
{
FPackageName::UnRegisterMountPoint(rootPath, contentPath);
} }
FString UContentLoader::GetPakMountPoint(const FString& pakFilePath) FString UContentLoader::GetPakMountContent(const FString& pakFilePath, TArray<FString>* content)
{ {
TArray<FString> contentProxy;
if(!content)
content = &contentProxy;
FString mountPoint, contentPath, contentPathTail;
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]);
if(mountPoint.Split("/Content/", &contentPath, &appendPath))
{ {
return FString::Printf(TEXT("%s/Content/"), *contentPath); return FString::Printf(TEXT("%s/Content/"), *contentPath);
} }
} }
return FString("");
} }
return {}; UClass* UContentLoader::GetPakClass(const FString& pakContentPath)
}
UClass* UContentLoader::LoadPakObjClassReference(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");
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("ContentLoader: Loading '%s' class"), *assetName)); auto result = StaticLoadClass(UObject::StaticClass(), nullptr, *className);
UE_LOG(LogTemp, Log, TEXT("ContentLoader: Loading '%s' class"), *assetName); if(!result)
UE_LOG(LogTemp, Warning, TEXT("ContentLoader: Unable to load pak class: %s."), *className);
return nullptr;//StaticLoadClass(UObject::StaticClass(), nullptr, *assetName); 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;
}
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;
}; };