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:
Aruki
2017-07-14 18:41:56 -06:00
parent fe9a074029
commit dbe8b7922c
25 changed files with 897 additions and 198 deletions

View File

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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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);