AronaSlate/Source/AronaCore/Singleton/SampleManager.cpp

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");
}