204 lines
4.2 KiB
C++
204 lines
4.2 KiB
C++
#include "SampleManager.h"
|
|
|
|
#include "ExecutionTime.h"
|
|
#include "Misc/AronaConfig.h"
|
|
|
|
FArchive& operator<<(FArchive& Ar, FSamplePathNode* In)
|
|
{
|
|
return *In << Ar;
|
|
}
|
|
|
|
FSamplePathNode* FSamplePathNode::Create(const FString& Path)
|
|
{
|
|
if (!FPaths::DirectoryExists(Path))
|
|
return nullptr;
|
|
|
|
FSamplePathNode* Root = new FSamplePathNode();
|
|
Root->Value = Path;
|
|
Root->NodeType = Type::Directory;
|
|
Root->Parent = nullptr;
|
|
|
|
class FSamplePathVisitor : public IPlatformFile::FDirectoryStatVisitor
|
|
{
|
|
public:
|
|
FSamplePathVisitor(FSamplePathNode* InRoot) : Root(InRoot)
|
|
{
|
|
|
|
}
|
|
virtual bool Visit(const TCHAR* FilenameOrDirectory, const FFileStatData& StatData) override
|
|
{
|
|
if (!StatData.bIsDirectory)
|
|
{
|
|
const FString& FilePath = FPaths::GetPath(FilenameOrDirectory);
|
|
auto* PathNode = Root->GetNodeByPath(FilePath);
|
|
if (!PathNode)
|
|
{
|
|
PathNode = Root->CreateNodeByPath(FilePath);
|
|
}
|
|
FSamplePathNode* SamplePathNode = PathNode->AddChild();
|
|
SamplePathNode->NodeType = Type::File;
|
|
SamplePathNode->Value = FPaths::GetCleanFilename(FilenameOrDirectory);
|
|
return true;
|
|
}
|
|
Root->CreateNodeByPath(FilenameOrDirectory);
|
|
return true;
|
|
}
|
|
FSamplePathNode* Root;
|
|
} Visitor(Root);
|
|
|
|
IPlatformFile::GetPlatformPhysical().IterateDirectoryStatRecursively(*Path, Visitor);
|
|
return Root;
|
|
}
|
|
|
|
FSamplePathNode* FSamplePathNode::AddChild()
|
|
{
|
|
FSamplePathNode* ChildNode = new FSamplePathNode();
|
|
ChildNode->Parent = this;
|
|
Child.Add(ChildNode);
|
|
return ChildNode;
|
|
}
|
|
|
|
FSamplePathNode* FSamplePathNode::GetNodeByPath(const FString& Path)
|
|
{
|
|
if (FPaths::IsSamePath(Path, GetFullPath()))
|
|
return this;
|
|
if (FSamplePathNode** Node = GetRootNode()->ChildMap.Find(Path))
|
|
return *Node;
|
|
return nullptr;
|
|
}
|
|
|
|
FSamplePathNode* FSamplePathNode::CreateNodeByPath(FString Path)
|
|
{
|
|
const FString& FullPath = GetFullPath();
|
|
if (FullPath == Path)
|
|
return this;
|
|
TArray<FString> Paths;
|
|
FString Leaf;
|
|
do
|
|
{
|
|
FString Temp = FPaths::GetPathLeaf(Path);
|
|
if (Temp == Leaf)
|
|
break;
|
|
Leaf = Temp;
|
|
Paths.Add(Path);
|
|
Path = FPaths::GetPath(Path);
|
|
if (Path == FullPath)
|
|
break;
|
|
}
|
|
while (true);
|
|
Algo::Reverse(Paths);
|
|
return CreateNodeByPathInternal(Paths);
|
|
}
|
|
|
|
FSamplePathNode* FSamplePathNode::CreateNodeByPathInternal(const TArray<FString>& Paths)
|
|
{
|
|
FSamplePathNode* RootNode = GetRootNode();
|
|
for (auto Str : Paths)
|
|
{
|
|
FSamplePathNode* PathNode = GetNodeByPath(Str);
|
|
if (!PathNode)
|
|
{
|
|
PathNode = AddChild();
|
|
PathNode->Value = FPaths::GetPathLeaf(Str);
|
|
PathNode->NodeType = Directory;
|
|
RootNode->ChildMap.Add(Str, PathNode);
|
|
}
|
|
}
|
|
return GetNodeByPath(Paths[0]);
|
|
}
|
|
|
|
bool FSampleDirectoryCache::NeedRefresh()
|
|
{
|
|
if (!FPaths::FileExists(*GetCachePath()))
|
|
return true;
|
|
TArray<FString> PathsStr;
|
|
FAronaConfig::GetValueArray("Sample", "Path", PathsStr);
|
|
if (PathsStr.Num() != SamplePathNodes.Num())
|
|
return true;
|
|
// TODO: 比较路径是否相同
|
|
return false;
|
|
}
|
|
|
|
void FSampleDirectoryCache::Init()
|
|
{
|
|
Reload();
|
|
if (NeedRefresh())
|
|
{
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void FSampleDirectoryCache::Reload()
|
|
{
|
|
Clear();
|
|
TArray<uint8> Data;
|
|
if (!FFileHelper::LoadFileToArray(Data, *GetCachePath()))
|
|
return;
|
|
FMemoryReader MemoryReader(Data);
|
|
Serialize(MemoryReader);
|
|
Save();
|
|
}
|
|
|
|
void FSampleDirectoryCache::Refresh()
|
|
{
|
|
if (Loading || !NeedRefresh())
|
|
return;
|
|
|
|
Async(EAsyncExecution::Thread, [this]()
|
|
{
|
|
Loading = true;
|
|
RegenCache();
|
|
Loading = false;
|
|
});
|
|
}
|
|
|
|
void FSampleDirectoryCache::RegenCache()
|
|
{
|
|
DeleteCache();
|
|
|
|
FAronaConfig::GetValueArray("Sample", "Path", SamplePaths);
|
|
for (auto Str : SamplePaths)
|
|
{
|
|
if (FSamplePathNode* SamplePathNode = FSamplePathNode::Create(Str))
|
|
SamplePathNodes.Add(SamplePathNode);
|
|
}
|
|
Save();
|
|
}
|
|
|
|
bool FSampleDirectoryCache::Save()
|
|
{
|
|
TArray<uint8> Data;
|
|
FMemoryWriter MemoryWriter(Data);
|
|
Serialize(MemoryWriter);
|
|
return FFileHelper::SaveArrayToFile(Data, *GetCachePath());
|
|
}
|
|
|
|
void FSampleDirectoryCache::Clear()
|
|
{
|
|
for (const auto PathNode : SamplePathNodes)
|
|
{
|
|
delete PathNode;
|
|
}
|
|
SamplePathNodes.Empty();
|
|
}
|
|
|
|
void FSampleManager::Init()
|
|
{
|
|
Cache.Init();
|
|
}
|
|
|
|
void FSampleManager::Refresh()
|
|
{
|
|
Cache.Refresh();
|
|
}
|
|
|
|
void FSampleDirectoryCache::DeleteCache()
|
|
{
|
|
IPlatformFile::GetPlatformPhysical().DeleteFile(*GetCachePath());
|
|
}
|
|
|
|
FString FSampleDirectoryCache::GetCachePath()
|
|
{
|
|
return FPaths::ProjectSavedDir() / TEXT("SampleCache");
|
|
}
|