mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-16 08:27:01 +00:00
Added support for dragging/dropping resources; you can use drag/drop to rearrange resources/folders in the resource browser now, and you can drag/drop resources onto resource selector widgets
This commit is contained in:
@@ -79,7 +79,7 @@ void ApplyGeneratedName(CResourceEntry *pEntry, const TString& rkDir, const TStr
|
||||
if (pEntry->Directory() == pNewDir && pEntry->Name() == NewName) return;
|
||||
|
||||
// Perform the move
|
||||
bool Success = pEntry->Move(pNewDir->FullPath(), NewName, true, true);
|
||||
bool Success = pEntry->MoveAndRename(pNewDir->FullPath(), NewName, true, true);
|
||||
ASSERT(Success);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ void GenerateAssetNames(CGameProject *pProj)
|
||||
|
||||
TString NewDir = (HasCustomDir ? It->DirectoryPath() : pStore->DefaultResourceDirPath());
|
||||
TString NewName = (HasCustomName ? It->Name() : It->ID().ToString());
|
||||
It->Move(NewDir, NewName, true, true);
|
||||
It->MoveAndRename(NewDir, NewName, true, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -656,7 +656,7 @@ void GenerateAssetNames(CGameProject *pProj)
|
||||
}
|
||||
#endif
|
||||
|
||||
pStore->RootDirectory()->RemoveEmptySubdirectories();
|
||||
pStore->RootDirectory()->DeleteEmptySubdirectories();
|
||||
pStore->ConditionalSaveStore();
|
||||
Log::Write("*** Asset Name Generation FINISHED ***");
|
||||
}
|
||||
|
||||
@@ -476,7 +476,7 @@ bool CResourceEntry::CanMoveTo(const TString& rkDir, const TString& rkName)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CResourceEntry::Move(const TString& rkDir, const TString& rkName, bool IsAutoGenDir /*= false*/, bool IsAutoGenName /*= false*/)
|
||||
bool CResourceEntry::MoveAndRename(const TString& rkDir, const TString& rkName, bool IsAutoGenDir /*= false*/, bool IsAutoGenName /*= false*/)
|
||||
{
|
||||
if (!CanMoveTo(rkDir, rkName)) return false;
|
||||
|
||||
@@ -516,7 +516,7 @@ bool CResourceEntry::Move(const TString& rkDir, const TString& rkName, bool IsAu
|
||||
// Move raw file to new location
|
||||
if (FileUtil::Exists(OldRawPath))
|
||||
{
|
||||
FSMoveSuccess = FileUtil::CopyFile(OldRawPath, NewRawPath);
|
||||
FSMoveSuccess = FileUtil::MoveFile(OldRawPath, NewRawPath);
|
||||
|
||||
if (!FSMoveSuccess)
|
||||
MoveFailReason = TString::Format("Failed to move raw file to new destination (%s --> %s)", *OldRawPath, *NewRawPath);
|
||||
@@ -525,11 +525,10 @@ bool CResourceEntry::Move(const TString& rkDir, const TString& rkName, bool IsAu
|
||||
// Move cooked file to new location
|
||||
if (FSMoveSuccess && FileUtil::Exists(OldCookedPath))
|
||||
{
|
||||
FSMoveSuccess = FileUtil::CopyFile(OldCookedPath, NewCookedPath);
|
||||
FSMoveSuccess = FileUtil::MoveFile(OldCookedPath, NewCookedPath);
|
||||
|
||||
if (!FSMoveSuccess)
|
||||
{
|
||||
FileUtil::DeleteFile(NewRawPath);
|
||||
MoveFailReason = TString::Format("Failed to move cooked file to new destination (%s --> %s)", *OldCookedPath, *NewCookedPath);
|
||||
}
|
||||
}
|
||||
@@ -539,12 +538,10 @@ bool CResourceEntry::Move(const TString& rkDir, const TString& rkName, bool IsAu
|
||||
{
|
||||
if (FileUtil::Exists(OldMetaPath))
|
||||
{
|
||||
FSMoveSuccess = FileUtil::CopyFile(OldMetaPath, NewMetaPath);
|
||||
FSMoveSuccess = FileUtil::MoveFile(OldMetaPath, NewMetaPath);
|
||||
|
||||
if (!FSMoveSuccess)
|
||||
{
|
||||
FileUtil::DeleteFile(NewRawPath);
|
||||
FileUtil::DeleteFile(NewCookedPath);
|
||||
MoveFailReason = TString::Format("Failed to move metadata file to new destination (%s --> %s)", *OldMetaPath, *NewMetaPath);
|
||||
}
|
||||
}
|
||||
@@ -582,10 +579,6 @@ bool CResourceEntry::Move(const TString& rkDir, const TString& rkName, bool IsAu
|
||||
|
||||
mpStore->SetCacheDirty();
|
||||
mCachedUppercaseName = rkName.ToUpper();
|
||||
FileUtil::DeleteFile(OldRawPath);
|
||||
FileUtil::DeleteFile(OldCookedPath);
|
||||
FileUtil::DeleteFile(OldMetaPath);
|
||||
|
||||
SaveMetadata();
|
||||
return true;
|
||||
}
|
||||
@@ -597,10 +590,27 @@ bool CResourceEntry::Move(const TString& rkDir, const TString& rkName, bool IsAu
|
||||
mpDirectory = pOldDir;
|
||||
mName = OldName;
|
||||
mpStore->ConditionalDeleteDirectory(pNewDir, false);
|
||||
|
||||
if (FileUtil::Exists(NewRawPath))
|
||||
FileUtil::MoveFile(NewRawPath, OldRawPath);
|
||||
|
||||
if (FileUtil::Exists(NewCookedPath))
|
||||
FileUtil::MoveFile(NewCookedPath, OldCookedPath);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CResourceEntry::Move(const TString& rkDir, bool IsAutoGenDir /*= false*/)
|
||||
{
|
||||
return MoveAndRename(rkDir, mName, IsAutoGenDir, false);
|
||||
}
|
||||
|
||||
bool CResourceEntry::Rename(const TString& rkName, bool IsAutoGenName /*= false*/)
|
||||
{
|
||||
return MoveAndRename(mpDirectory->FullPath(), rkName, false, IsAutoGenName);
|
||||
}
|
||||
|
||||
CGameProject* CResourceEntry::Project() const
|
||||
{
|
||||
return mpStore ? mpStore->Project() : nullptr;
|
||||
|
||||
@@ -74,7 +74,10 @@ public:
|
||||
CResource* LoadCooked(IInputStream& rInput);
|
||||
bool Unload();
|
||||
bool CanMoveTo(const TString& rkDir, const TString& rkName);
|
||||
bool Move(const TString& rkDir, const TString& rkName, bool IsAutoGenDir = false, bool IsAutoGenName = false);
|
||||
bool MoveAndRename(const TString& rkDir, const TString& rkName, bool IsAutoGenDir = false, bool IsAutoGenName = false);
|
||||
bool Move(const TString& rkDir, bool IsAutoGenDir = false);
|
||||
bool Rename(const TString& rkName, bool IsAutoGenName = false);
|
||||
|
||||
CGameProject* Project() const;
|
||||
EGame Game() const;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ CResourceStore::~CResourceStore()
|
||||
void RecursiveGetListOfEmptyDirectories(CVirtualDirectory *pDir, TStringList& rOutList)
|
||||
{
|
||||
// Helper function for SerializeResourceDatabase
|
||||
if (pDir->IsEmpty())
|
||||
if (pDir->IsEmpty(false))
|
||||
{
|
||||
rOutList.push_back(pDir->FullPath());
|
||||
}
|
||||
@@ -233,7 +233,7 @@ void CResourceStore::CreateVirtualDirectory(const TString& rkPath)
|
||||
|
||||
void CResourceStore::ConditionalDeleteDirectory(CVirtualDirectory *pDir, bool Recurse)
|
||||
{
|
||||
if (pDir->IsEmpty() && !pDir->IsRoot())
|
||||
if (pDir->IsEmpty(true) && !pDir->IsRoot())
|
||||
{
|
||||
CVirtualDirectory *pParent = pDir->Parent();
|
||||
pParent->RemoveChildDirectory(pDir);
|
||||
@@ -366,8 +366,9 @@ bool CResourceStore::BuildFromDirectory(bool ShouldGenerateCacheFile)
|
||||
|
||||
void CResourceStore::RebuildFromDirectory()
|
||||
{
|
||||
ASSERT(mpProj != nullptr);
|
||||
mpProj->AudioManager()->ClearAssets();
|
||||
if (mpProj)
|
||||
mpProj->AudioManager()->ClearAssets();
|
||||
|
||||
ClearDatabase();
|
||||
BuildFromDirectory(true);
|
||||
}
|
||||
@@ -596,7 +597,7 @@ void CResourceStore::ImportNamesFromPakContentsTxt(const TString& rkTxtPath, boo
|
||||
TString Name = Path.GetFileName(false);
|
||||
if (Dir.IsEmpty()) Dir = pEntry->DirectoryPath();
|
||||
|
||||
pEntry->Move(Dir, Name);
|
||||
pEntry->MoveAndRename(Dir, Name);
|
||||
}
|
||||
|
||||
// Save
|
||||
|
||||
@@ -26,22 +26,37 @@ CVirtualDirectory::~CVirtualDirectory()
|
||||
delete mSubdirectories[iSub];
|
||||
}
|
||||
|
||||
bool CVirtualDirectory::IsEmpty() const
|
||||
bool CVirtualDirectory::IsEmpty(bool CheckFilesystem) const
|
||||
{
|
||||
if (!mResources.empty()) return false;
|
||||
if (!mResources.empty())
|
||||
return false;
|
||||
|
||||
for (u32 iSub = 0; iSub < mSubdirectories.size(); iSub++)
|
||||
if (!mSubdirectories[iSub]->IsEmpty()) return false;
|
||||
if (!mSubdirectories[iSub]->IsEmpty(CheckFilesystem))
|
||||
return false;
|
||||
|
||||
if (CheckFilesystem && !FileUtil::IsEmpty( AbsolutePath() ))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVirtualDirectory::IsDescendantOf(CVirtualDirectory *pDir) const
|
||||
{
|
||||
return mpParent && (mpParent == pDir || mpParent->IsDescendantOf(pDir));
|
||||
}
|
||||
|
||||
TString CVirtualDirectory::FullPath() const
|
||||
{
|
||||
if (IsRoot())
|
||||
return "";
|
||||
else
|
||||
return (mpParent && !mpParent->IsRoot() ? mpParent->FullPath() + mName + '/' : mName + '/');
|
||||
return (mpParent ? mpParent->FullPath() + mName : mName) + '/';
|
||||
}
|
||||
|
||||
TString CVirtualDirectory::AbsolutePath() const
|
||||
{
|
||||
return mpStore->ResourcesDir() + FullPath();
|
||||
}
|
||||
|
||||
CVirtualDirectory* CVirtualDirectory::GetRoot()
|
||||
@@ -191,24 +206,26 @@ bool CVirtualDirectory::AddChild(const TString &rkPath, CResourceEntry *pEntry)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CVirtualDirectory::AddChild(CVirtualDirectory *pDir)
|
||||
{
|
||||
if (pDir->Parent() != this) return false;
|
||||
if (FindChildDirectory(pDir->Name(), false) != nullptr) return false;
|
||||
|
||||
mSubdirectories.push_back(pDir);
|
||||
std::sort(mSubdirectories.begin(), mSubdirectories.end(), [](CVirtualDirectory *pLeft, CVirtualDirectory *pRight) -> bool {
|
||||
return (pLeft->Name().ToUpper() < pRight->Name().ToUpper());
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVirtualDirectory::RemoveChildDirectory(CVirtualDirectory *pSubdir)
|
||||
{
|
||||
ASSERT(pSubdir->IsEmpty());
|
||||
|
||||
for (auto It = mSubdirectories.begin(); It != mSubdirectories.end(); It++)
|
||||
{
|
||||
if (*It == pSubdir)
|
||||
{
|
||||
mSubdirectories.erase(It);
|
||||
|
||||
// If this is part of the resource store, delete the corresponding filesystem directory
|
||||
if (mpStore && pSubdir->GetRoot() == mpStore->RootDirectory())
|
||||
{
|
||||
TString AbsPath = mpStore->ResourcesDir() + pSubdir->FullPath();
|
||||
FileUtil::DeleteDirectory(AbsPath, true);
|
||||
}
|
||||
|
||||
delete pSubdir;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -230,19 +247,73 @@ bool CVirtualDirectory::RemoveChildResource(CResourceEntry *pEntry)
|
||||
return false;
|
||||
}
|
||||
|
||||
void CVirtualDirectory::RemoveEmptySubdirectories()
|
||||
bool CVirtualDirectory::Delete()
|
||||
{
|
||||
ASSERT(IsEmpty(true) && !IsRoot());
|
||||
|
||||
if (IsEmpty(true) && !IsRoot())
|
||||
{
|
||||
if (FileUtil::DeleteDirectory(AbsolutePath(), true))
|
||||
{
|
||||
if (!mpParent || mpParent->RemoveChildDirectory(this))
|
||||
{
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CVirtualDirectory::DeleteEmptySubdirectories()
|
||||
{
|
||||
for (u32 SubdirIdx = 0; SubdirIdx < mSubdirectories.size(); SubdirIdx++)
|
||||
{
|
||||
CVirtualDirectory *pDir = mSubdirectories[SubdirIdx];
|
||||
|
||||
if (pDir->IsEmpty())
|
||||
if (pDir->IsEmpty(true))
|
||||
{
|
||||
RemoveChildDirectory(pDir);
|
||||
pDir->Delete();
|
||||
SubdirIdx--;
|
||||
}
|
||||
else
|
||||
pDir->RemoveEmptySubdirectories();
|
||||
pDir->DeleteEmptySubdirectories();
|
||||
}
|
||||
}
|
||||
|
||||
bool CVirtualDirectory::SetParent(CVirtualDirectory *pParent)
|
||||
{
|
||||
ASSERT(!pParent->IsDescendantOf(this));
|
||||
if (mpParent == pParent) return true;
|
||||
|
||||
Log::Write("MOVING DIRECTORY: " + FullPath() + " -> " + pParent->FullPath() + mName + '/');
|
||||
|
||||
// Check for a conflict
|
||||
CVirtualDirectory *pConflictDir = pParent->FindChildDirectory(mName, false);
|
||||
|
||||
if (pConflictDir)
|
||||
{
|
||||
Log::Error("DIRECTORY MOVE FAILED: Conflicting directory exists at the destination path!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Move filesystem contents to new path
|
||||
TString AbsOldPath = mpStore->ResourcesDir() + FullPath();
|
||||
TString AbsNewPath = mpStore->ResourcesDir() + pParent->FullPath() + mName + '/';
|
||||
|
||||
if (mpParent->RemoveChildDirectory(this) && FileUtil::MoveDirectory(AbsOldPath, AbsNewPath))
|
||||
{
|
||||
mpParent = pParent;
|
||||
mpParent->AddChild(this);
|
||||
mpStore->SetCacheDirty();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Error("DIRECTORY MOVE FAILED: Filesystem move operation failed!");
|
||||
mpParent->AddChild(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,16 +24,21 @@ public:
|
||||
CVirtualDirectory(CVirtualDirectory *pParent, const TString& rkName, CResourceStore *pStore);
|
||||
~CVirtualDirectory();
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsEmpty(bool CheckFilesystem) const;
|
||||
bool IsDescendantOf(CVirtualDirectory *pDir) const;
|
||||
TString FullPath() const;
|
||||
TString AbsolutePath() const;
|
||||
CVirtualDirectory* GetRoot();
|
||||
CVirtualDirectory* FindChildDirectory(const TString& rkName, bool AllowCreate);
|
||||
CResourceEntry* FindChildResource(const TString& rkPath);
|
||||
CResourceEntry* FindChildResource(const TString& rkName, EResType Type);
|
||||
bool AddChild(const TString& rkPath, CResourceEntry *pEntry);
|
||||
bool AddChild(CVirtualDirectory *pDir);
|
||||
bool RemoveChildDirectory(CVirtualDirectory *pSubdir);
|
||||
bool RemoveChildResource(CResourceEntry *pEntry);
|
||||
void RemoveEmptySubdirectories();
|
||||
bool Delete();
|
||||
void DeleteEmptySubdirectories();
|
||||
bool SetParent(CVirtualDirectory *pParent);
|
||||
|
||||
static bool IsValidDirectoryName(const TString& rkName);
|
||||
static bool IsValidDirectoryPath(TString Path);
|
||||
|
||||
Reference in New Issue
Block a user