Implemented initial version of resource browser
This commit is contained in:
parent
08dcfe5e5a
commit
6f98ae5bb8
|
@ -30,7 +30,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Helper macros for creating string literals of the correct char type. Internal use only! Invalid outside of this header!
|
// Helper macros for creating string literals of the correct char type. Internal use only! Invalid outside of this header!
|
||||||
#define LITERAL(Text) (typeid(CharType) == typeid(char)) ? (const CharType*) ##Text : (const CharType*) L##Text
|
#define LITERAL(Text) (typeid(CharType) == typeid(char) ? (const CharType*) ##Text : (const CharType*) L##Text)
|
||||||
#define CHAR_LITERAL(Text) (CharType) Text
|
#define CHAR_LITERAL(Text) (CharType) Text
|
||||||
|
|
||||||
// ************ TBasicString ************
|
// ************ TBasicString ************
|
||||||
|
@ -846,7 +846,7 @@ public:
|
||||||
|
|
||||||
static TBasicString<CharType> FromFloat(float Value, int MinDecimals = 1)
|
static TBasicString<CharType> FromFloat(float Value, int MinDecimals = 1)
|
||||||
{
|
{
|
||||||
TString Out = std::to_string(Value);
|
_TString Out = std::to_string(Value);
|
||||||
int NumZeroes = Out.Size() - (Out.IndexOf(LITERAL(".")) + 1);
|
int NumZeroes = Out.Size() - (Out.IndexOf(LITERAL(".")) + 1);
|
||||||
|
|
||||||
while (Out.Back() == CHAR_LITERAL('0') && NumZeroes > MinDecimals)
|
while (Out.Back() == CHAR_LITERAL('0') && NumZeroes > MinDecimals)
|
||||||
|
@ -858,6 +858,39 @@ public:
|
||||||
return Out;
|
return Out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TBasicString<CharType> FileSizeString(u64 Size, u32 NumDecimals = 2)
|
||||||
|
{
|
||||||
|
_TString Out;
|
||||||
|
_TString Type;
|
||||||
|
|
||||||
|
if (Size < 100)
|
||||||
|
{
|
||||||
|
return FromInt64(Size, 0, 10) + LITERAL(" bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (Size < 1000000)
|
||||||
|
{
|
||||||
|
Out = FromFloat(Size / 1000.f, NumDecimals);
|
||||||
|
Type = LITERAL("KB");
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (Size < 1000000000)
|
||||||
|
{
|
||||||
|
Out = FromFloat(Size / 1000000.f, NumDecimals);
|
||||||
|
Type = LITERAL("MB");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Out = FromFloat(Size / 1000000000.f, NumDecimals);
|
||||||
|
Type = LITERAL("GB");
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 DecCount = Out.Size() - (Out.IndexOf(CHAR_LITERAL('.')) + 1);
|
||||||
|
if (DecCount > NumDecimals) Out = Out.ChopBack(DecCount - NumDecimals);
|
||||||
|
return Out + Type;
|
||||||
|
}
|
||||||
|
|
||||||
static TBasicString<CharType> HexString(unsigned char Num, int Width = 8, bool AddPrefix = true, bool Uppercase = true)
|
static TBasicString<CharType> HexString(unsigned char Num, int Width = 8, bool AddPrefix = true, bool Uppercase = true)
|
||||||
{
|
{
|
||||||
return HexString((unsigned long) Num, Width, AddPrefix, Uppercase);
|
return HexString((unsigned long) Num, Width, AddPrefix, Uppercase);
|
||||||
|
|
|
@ -195,7 +195,8 @@ HEADERS += \
|
||||||
GameProject/CGameExporter.h \
|
GameProject/CGameExporter.h \
|
||||||
GameProject/CResourceStore.h \
|
GameProject/CResourceStore.h \
|
||||||
GameProject/CVirtualDirectory.h \
|
GameProject/CVirtualDirectory.h \
|
||||||
GameProject/CResourceEntry.h
|
GameProject/CResourceEntry.h \
|
||||||
|
GameProject/CResourceIterator.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
|
|
@ -171,6 +171,7 @@ void CGameExporter::LoadPaks()
|
||||||
for (auto It = mPaks.begin(); It != mPaks.end(); It++)
|
for (auto It = mPaks.begin(); It != mPaks.end(); It++)
|
||||||
{
|
{
|
||||||
TWideString PakPath = *It;
|
TWideString PakPath = *It;
|
||||||
|
TWideString PakName = PakPath.GetFileName(false);
|
||||||
TString CharPak = PakPath.ToUTF8();
|
TString CharPak = PakPath.ToUTF8();
|
||||||
CFileInStream Pak(CharPak.ToStdString(), IOUtil::eBigEndian);
|
CFileInStream Pak(CharPak.ToStdString(), IOUtil::eBigEndian);
|
||||||
|
|
||||||
|
@ -203,6 +204,7 @@ void CGameExporter::LoadPaks()
|
||||||
u32 NameLen = Pak.ReadLong();
|
u32 NameLen = Pak.ReadLong();
|
||||||
TString Name = Pak.ReadString(NameLen);
|
TString Name = Pak.ReadString(NameLen);
|
||||||
pCollection->AddResource(Name, ResID, ResType);
|
pCollection->AddResource(Name, ResID, ResType);
|
||||||
|
SetResourcePath(ResID.ToLongLong(), PakName + L"\\", Name.ToUTF16());
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 NumResources = Pak.ReadLong();
|
u32 NumResources = Pak.ReadLong();
|
||||||
|
@ -261,6 +263,7 @@ void CGameExporter::LoadPaks()
|
||||||
CFourCC ResType = Pak.ReadLong();
|
CFourCC ResType = Pak.ReadLong();
|
||||||
CUniqueID ResID(Pak, IDLength);
|
CUniqueID ResID(Pak, IDLength);
|
||||||
pCollection->AddResource(Name, ResID, ResType);
|
pCollection->AddResource(Name, ResID, ResType);
|
||||||
|
SetResourcePath(ResID.ToLongLong(), PakName + L"\\", Name.ToUTF16());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ CResourceEntry::CResourceEntry(CResourceStore *pStore, const CUniqueID& rkID,
|
||||||
, mType(Type)
|
, mType(Type)
|
||||||
, mNeedsRecook(false)
|
, mNeedsRecook(false)
|
||||||
, mTransient(Transient)
|
, mTransient(Transient)
|
||||||
|
, mCachedSize(-1)
|
||||||
|
, mCachedUppercaseName(rkFilename.ToUpper())
|
||||||
{
|
{
|
||||||
mpDirectory = mpStore->GetVirtualDirectory(rkDir, Transient, true);
|
mpDirectory = mpStore->GetVirtualDirectory(rkDir, Transient, true);
|
||||||
if (mpDirectory) mpDirectory->AddChild(L"", this);
|
if (mpDirectory) mpDirectory->AddChild(L"", this);
|
||||||
|
@ -70,6 +72,32 @@ TString CResourceEntry::CookedAssetPath(bool Relative) const
|
||||||
return ((mTransient || Relative) ? Path + Name : mpStore->ActiveProject()->CookedDir(false) + Path + Name);
|
return ((mTransient || Relative) ? Path + Name : mpStore->ActiveProject()->CookedDir(false) + Path + Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CResourceEntry::IsInDirectory(CVirtualDirectory *pDir) const
|
||||||
|
{
|
||||||
|
CVirtualDirectory *pParentDir = mpDirectory;
|
||||||
|
|
||||||
|
while (pParentDir)
|
||||||
|
{
|
||||||
|
if (pParentDir == pDir) return true;
|
||||||
|
pParentDir = pParentDir->Parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 CResourceEntry::Size() const
|
||||||
|
{
|
||||||
|
if (mCachedSize == -1)
|
||||||
|
{
|
||||||
|
if (HasCookedVersion())
|
||||||
|
mCachedSize = FileUtil::FileSize(CookedAssetPath());
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mCachedSize;
|
||||||
|
}
|
||||||
|
|
||||||
bool CResourceEntry::NeedsRecook() const
|
bool CResourceEntry::NeedsRecook() const
|
||||||
{
|
{
|
||||||
// Assets that do not have a raw version can't be recooked since they will always just be saved cooked to begin with.
|
// Assets that do not have a raw version can't be recooked since they will always just be saved cooked to begin with.
|
||||||
|
@ -170,6 +198,7 @@ void CResourceEntry::Move(const TWideString& rkDir, const TWideString& rkName)
|
||||||
ASSERT(mpDirectory->FindChildResource(rkName) == nullptr);
|
ASSERT(mpDirectory->FindChildResource(rkName) == nullptr);
|
||||||
|
|
||||||
mName = rkName;
|
mName = rkName;
|
||||||
|
mCachedUppercaseName = rkName.ToUpper();
|
||||||
|
|
||||||
// Move files
|
// Move files
|
||||||
if (HasDirectory)
|
if (HasDirectory)
|
||||||
|
|
|
@ -21,6 +21,9 @@ class CResourceEntry
|
||||||
bool mNeedsRecook;
|
bool mNeedsRecook;
|
||||||
bool mTransient;
|
bool mTransient;
|
||||||
|
|
||||||
|
mutable u64 mCachedSize;
|
||||||
|
mutable TWideString mCachedUppercaseName; // This is used to speed up case-insensitive sorting.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CResourceEntry(CResourceStore *pStore, const CUniqueID& rkID,
|
CResourceEntry(CResourceStore *pStore, const CUniqueID& rkID,
|
||||||
const TWideString& rkDir, const TWideString& rkFilename,
|
const TWideString& rkDir, const TWideString& rkFilename,
|
||||||
|
@ -30,6 +33,8 @@ public:
|
||||||
bool HasCookedVersion() const;
|
bool HasCookedVersion() const;
|
||||||
TString RawAssetPath(bool Relative = false) const;
|
TString RawAssetPath(bool Relative = false) const;
|
||||||
TString CookedAssetPath(bool Relative = false) const;
|
TString CookedAssetPath(bool Relative = false) const;
|
||||||
|
bool IsInDirectory(CVirtualDirectory *pDir) const;
|
||||||
|
u64 Size() const;
|
||||||
bool NeedsRecook() const;
|
bool NeedsRecook() const;
|
||||||
void SetGame(EGame NewGame);
|
void SetGame(EGame NewGame);
|
||||||
CResource* Load();
|
CResource* Load();
|
||||||
|
@ -48,6 +53,7 @@ public:
|
||||||
inline EGame Game() const { return mGame; }
|
inline EGame Game() const { return mGame; }
|
||||||
inline CVirtualDirectory* Directory() const { return mpDirectory; }
|
inline CVirtualDirectory* Directory() const { return mpDirectory; }
|
||||||
inline TWideString Name() const { return mName; }
|
inline TWideString Name() const { return mName; }
|
||||||
|
inline TWideString UppercaseName() const { return mCachedUppercaseName; }
|
||||||
inline EResType ResourceType() const { return mType; }
|
inline EResType ResourceType() const { return mType; }
|
||||||
inline bool IsTransient() const { return mTransient; }
|
inline bool IsTransient() const { return mTransient; }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef CRESOURCEITERATOR
|
||||||
|
#define CRESOURCEITERATOR
|
||||||
|
|
||||||
|
#include <Core/GameProject/CResourceEntry.h>
|
||||||
|
#include <Core/GameProject/CResourceStore.h>
|
||||||
|
|
||||||
|
class CResourceIterator
|
||||||
|
{
|
||||||
|
CResourceStore *mpStore;
|
||||||
|
std::map<CUniqueID, CResourceEntry*>::iterator mIter;
|
||||||
|
CResourceEntry *mpCurEntry;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CResourceIterator(CResourceStore *pStore)
|
||||||
|
: mpStore(pStore)
|
||||||
|
, mpCurEntry(nullptr)
|
||||||
|
{
|
||||||
|
mIter = mpStore->mResourceEntries.begin();
|
||||||
|
Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CResourceEntry* Next()
|
||||||
|
{
|
||||||
|
if (mIter != mpStore->mResourceEntries.end())
|
||||||
|
{
|
||||||
|
mpCurEntry = mIter->second;
|
||||||
|
mIter++;
|
||||||
|
}
|
||||||
|
else mpCurEntry = nullptr;
|
||||||
|
|
||||||
|
return mpCurEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool DoneIterating() const
|
||||||
|
{
|
||||||
|
return mpCurEntry == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator bool() const
|
||||||
|
{
|
||||||
|
return !DoneIterating();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CResourceEntry* operator*() const
|
||||||
|
{
|
||||||
|
return mpCurEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CResourceEntry* operator->() const
|
||||||
|
{
|
||||||
|
return mpCurEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CResourceIterator& operator++()
|
||||||
|
{
|
||||||
|
Next();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CResourceIterator operator++(int)
|
||||||
|
{
|
||||||
|
CResourceIterator Copy = *this;
|
||||||
|
Next();
|
||||||
|
return Copy;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CRESOURCEITERATOR
|
||||||
|
|
|
@ -16,6 +16,8 @@ class CResource;
|
||||||
|
|
||||||
class CResourceStore
|
class CResourceStore
|
||||||
{
|
{
|
||||||
|
friend class CResourceIterator;
|
||||||
|
|
||||||
CGameProject *mpProj;
|
CGameProject *mpProj;
|
||||||
CVirtualDirectory *mpProjectRoot;
|
CVirtualDirectory *mpProjectRoot;
|
||||||
std::vector<CVirtualDirectory*> mTransientRoots;
|
std::vector<CVirtualDirectory*> mTransientRoots;
|
||||||
|
@ -61,7 +63,8 @@ public:
|
||||||
void SetTransientLoadDir(const TString& rkDir);
|
void SetTransientLoadDir(const TString& rkDir);
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
inline CGameProject* ActiveProject() const { return mpProj; }
|
inline CGameProject* ActiveProject() const { return mpProj; }
|
||||||
|
inline CVirtualDirectory* RootDirectory() const { return mpProjectRoot; }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CResourceStore *gpResourceStore;
|
extern CResourceStore *gpResourceStore;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "CProjectOverviewDialog.h"
|
#include "CProjectOverviewDialog.h"
|
||||||
#include "ui_CProjectOverviewDialog.h"
|
#include "ui_CProjectOverviewDialog.h"
|
||||||
#include "UICommon.h"
|
#include "UICommon.h"
|
||||||
|
#include "Editor/ResourceBrowser/CResourceBrowser.h"
|
||||||
#include <Common/AssertMacro.h>
|
#include <Common/AssertMacro.h>
|
||||||
#include <Core/GameProject/CGameExporter.h>
|
#include <Core/GameProject/CGameExporter.h>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
@ -18,6 +19,7 @@ CProjectOverviewDialog::CProjectOverviewDialog(QWidget *pParent)
|
||||||
connect(mpUI->ExportGameButton, SIGNAL(clicked()), this, SLOT(ExportGame()));
|
connect(mpUI->ExportGameButton, SIGNAL(clicked()), this, SLOT(ExportGame()));
|
||||||
connect(mpUI->LoadWorldButton, SIGNAL(clicked()), this, SLOT(LoadWorld()));
|
connect(mpUI->LoadWorldButton, SIGNAL(clicked()), this, SLOT(LoadWorld()));
|
||||||
connect(mpUI->LaunchEditorButton, SIGNAL(clicked()), this, SLOT(LaunchEditor()));
|
connect(mpUI->LaunchEditorButton, SIGNAL(clicked()), this, SLOT(LaunchEditor()));
|
||||||
|
connect(mpUI->ViewResourcesButton, SIGNAL(clicked()), this, SLOT(LaunchResourceBrowser()));
|
||||||
}
|
}
|
||||||
|
|
||||||
CProjectOverviewDialog::~CProjectOverviewDialog()
|
CProjectOverviewDialog::~CProjectOverviewDialog()
|
||||||
|
@ -164,3 +166,9 @@ void CProjectOverviewDialog::LaunchEditor()
|
||||||
|
|
||||||
gpResourceStore->DestroyUnreferencedResources();
|
gpResourceStore->DestroyUnreferencedResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CProjectOverviewDialog::LaunchResourceBrowser()
|
||||||
|
{
|
||||||
|
CResourceBrowser Browser(this);
|
||||||
|
Browser.exec();
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ public slots:
|
||||||
void ExportGame();
|
void ExportGame();
|
||||||
void LoadWorld();
|
void LoadWorld();
|
||||||
void LaunchEditor();
|
void LaunchEditor();
|
||||||
|
void LaunchResourceBrowser();
|
||||||
|
|
||||||
void SetupWorldsList();
|
void SetupWorldsList();
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,6 +32,13 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="ViewResourcesButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>View Resources</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="WorldsGroupBox">
|
<widget class="QGroupBox" name="WorldsGroupBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
|
|
@ -164,7 +164,11 @@ HEADERS += \
|
||||||
CGridRenderable.h \
|
CGridRenderable.h \
|
||||||
CharacterEditor/CSkeletonHierarchyModel.h \
|
CharacterEditor/CSkeletonHierarchyModel.h \
|
||||||
CLineRenderable.h \
|
CLineRenderable.h \
|
||||||
CProjectOverviewDialog.h
|
CProjectOverviewDialog.h \
|
||||||
|
ResourceBrowser/CResourceBrowser.h \
|
||||||
|
ResourceBrowser/CResourceTableModel.h \
|
||||||
|
ResourceBrowser/CResourceProxyModel.h \
|
||||||
|
ResourceBrowser/CVirtualDirectoryModel.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
@ -225,7 +229,8 @@ SOURCES += \
|
||||||
CharacterEditor/CCharacterEditor.cpp \
|
CharacterEditor/CCharacterEditor.cpp \
|
||||||
CharacterEditor/CCharacterEditorViewport.cpp \
|
CharacterEditor/CCharacterEditorViewport.cpp \
|
||||||
CharacterEditor/CSkeletonHierarchyModel.cpp \
|
CharacterEditor/CSkeletonHierarchyModel.cpp \
|
||||||
CProjectOverviewDialog.cpp
|
CProjectOverviewDialog.cpp \
|
||||||
|
ResourceBrowser/CResourceBrowser.cpp
|
||||||
|
|
||||||
# UI Files
|
# UI Files
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
@ -247,4 +252,5 @@ FORMS += \
|
||||||
WorldEditor/CRepackInfoDialog.ui \
|
WorldEditor/CRepackInfoDialog.ui \
|
||||||
CAboutDialog.ui \
|
CAboutDialog.ui \
|
||||||
CharacterEditor/CCharacterEditor.ui \
|
CharacterEditor/CCharacterEditor.ui \
|
||||||
CProjectOverviewDialog.ui
|
CProjectOverviewDialog.ui \
|
||||||
|
ResourceBrowser/CResourceBrowser.ui
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "CResourceBrowser.h"
|
||||||
|
#include "ui_CResourceBrowser.h"
|
||||||
|
|
||||||
|
CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
||||||
|
: QDialog(pParent)
|
||||||
|
, mpUI(new Ui::CResourceBrowser)
|
||||||
|
{
|
||||||
|
mpUI->setupUi(this);
|
||||||
|
|
||||||
|
// Set up table models
|
||||||
|
mpModel = new CResourceTableModel(this);
|
||||||
|
mpProxyModel = new CResourceProxyModel(this);
|
||||||
|
mpProxyModel->setSourceModel(mpModel);
|
||||||
|
mpUI->ResourceTableView->setModel(mpProxyModel);
|
||||||
|
RefreshResources();
|
||||||
|
|
||||||
|
QHeaderView *pHeader = mpUI->ResourceTableView->horizontalHeader();
|
||||||
|
pHeader->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||||
|
pHeader->resizeSection(1, 215);
|
||||||
|
pHeader->resizeSection(2, 75);
|
||||||
|
|
||||||
|
// Set up directory tree model
|
||||||
|
mpDirectoryModel = new CVirtualDirectoryModel(this);
|
||||||
|
mpDirectoryModel->SetRoot(gpResourceStore->RootDirectory());
|
||||||
|
mpUI->DirectoryTreeView->setModel(mpDirectoryModel);
|
||||||
|
mpUI->DirectoryTreeView->expand(mpDirectoryModel->index(0, 0, QModelIndex()));
|
||||||
|
|
||||||
|
// Set up connections
|
||||||
|
connect(mpUI->SearchBar, SIGNAL(textChanged(QString)), this, SLOT(OnSearchStringChanged()));
|
||||||
|
connect(mpUI->SortComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSortModeChanged(int)));
|
||||||
|
connect(mpUI->DirectoryTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnDirectorySelectionChanged(QModelIndex,QModelIndex)));
|
||||||
|
}
|
||||||
|
|
||||||
|
CResourceBrowser::~CResourceBrowser()
|
||||||
|
{
|
||||||
|
delete mpUI;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CResourceBrowser::RefreshResources()
|
||||||
|
{
|
||||||
|
mpModel->FillEntryList(gpResourceStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CResourceBrowser::OnSortModeChanged(int Index)
|
||||||
|
{
|
||||||
|
CResourceProxyModel::ESortMode Mode = (Index == 0 ? CResourceProxyModel::eSortByName : CResourceProxyModel::eSortBySize);
|
||||||
|
mpProxyModel->SetSortMode(Mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CResourceBrowser::OnSearchStringChanged()
|
||||||
|
{
|
||||||
|
mpProxyModel->SetSearchString( mpUI->SearchBar->text() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CResourceBrowser::OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& /*rkPrevIndex*/)
|
||||||
|
{
|
||||||
|
CVirtualDirectory *pDir = nullptr;
|
||||||
|
|
||||||
|
if (rkNewIndex.isValid())
|
||||||
|
pDir = mpDirectoryModel->IndexDirectory(rkNewIndex);
|
||||||
|
|
||||||
|
mpProxyModel->SetDirectory(pDir);
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef CRESOURCEBROWSER_H
|
||||||
|
#define CRESOURCEBROWSER_H
|
||||||
|
|
||||||
|
#include "CResourceProxyModel.h"
|
||||||
|
#include "CResourceTableModel.h"
|
||||||
|
#include "CVirtualDirectoryModel.h"
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class CResourceBrowser;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CResourceBrowser : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Ui::CResourceBrowser *mpUI;
|
||||||
|
CResourceTableModel *mpModel;
|
||||||
|
CResourceProxyModel *mpProxyModel;
|
||||||
|
CVirtualDirectoryModel *mpDirectoryModel;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CResourceBrowser(QWidget *pParent = 0);
|
||||||
|
~CResourceBrowser();
|
||||||
|
void RefreshResources();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void OnSortModeChanged(int Index);
|
||||||
|
void OnSearchStringChanged();
|
||||||
|
void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CRESOURCEBROWSER_H
|
|
@ -0,0 +1,157 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CResourceBrowser</class>
|
||||||
|
<widget class="QDialog" name="CResourceBrowser">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>789</width>
|
||||||
|
<height>577</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Resource Browser</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="SidebarContainerWidget" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="SearchBar">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>5</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Search</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="SortComboBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>5</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Sort by Name</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Sort by Size</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="DirectoryTreeView">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>16</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="verticalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="indentation">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<attribute name="headerVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="ResourceTableView">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>3</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::NoSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="verticalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderDefaultSectionSize">
|
||||||
|
<number>21</number>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderMinimumSectionSize">
|
||||||
|
<number>21</number>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,89 @@
|
||||||
|
#ifndef CRESOURCEPROXYMODEL
|
||||||
|
#define CRESOURCEPROXYMODEL
|
||||||
|
|
||||||
|
#include "CResourceTableModel.h"
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
class CResourceProxyModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum ESortMode
|
||||||
|
{
|
||||||
|
eSortByName, eSortBySize
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
CResourceTableModel *mpModel;
|
||||||
|
CVirtualDirectory *mpDirectory;
|
||||||
|
QString mSearchString;
|
||||||
|
ESortMode mSortMode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CResourceProxyModel(QObject *pParent = 0)
|
||||||
|
: QSortFilterProxyModel(pParent)
|
||||||
|
, mpModel(nullptr)
|
||||||
|
, mpDirectory(nullptr)
|
||||||
|
{
|
||||||
|
SetSortMode(eSortByName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSourceModel(QAbstractItemModel *pSourceModel)
|
||||||
|
{
|
||||||
|
CResourceTableModel *pResModel = qobject_cast<CResourceTableModel*>(pSourceModel);
|
||||||
|
mpModel = pResModel;
|
||||||
|
QSortFilterProxyModel::setSourceModel(pResModel);
|
||||||
|
sort(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lessThan(const QModelIndex& rkLeft, const QModelIndex& rkRight) const
|
||||||
|
{
|
||||||
|
CResourceEntry *pLeft = mpModel->IndexEntry(rkLeft);
|
||||||
|
CResourceEntry *pRight = mpModel->IndexEntry(rkRight);
|
||||||
|
|
||||||
|
if (mSortMode == eSortByName)
|
||||||
|
return pLeft->UppercaseName() < pRight->UppercaseName();
|
||||||
|
else
|
||||||
|
return pLeft->Size() < pRight->Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool filterAcceptsRow(int SourceRow, const QModelIndex& rkSourceParent) const
|
||||||
|
{
|
||||||
|
QModelIndex Index = mpModel->index(SourceRow, 0, rkSourceParent);
|
||||||
|
CResourceEntry *pEntry = mpModel->IndexEntry(Index);
|
||||||
|
|
||||||
|
if (mpDirectory && !pEntry->IsInDirectory(mpDirectory))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!mSearchString.isEmpty() && !pEntry->Name().Contains(TO_TWIDESTRING(mSearchString), false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetSortMode(ESortMode Mode)
|
||||||
|
{
|
||||||
|
if (mSortMode != Mode)
|
||||||
|
{
|
||||||
|
mSortMode = Mode;
|
||||||
|
sort(0, (mSortMode == eSortByName ? Qt::AscendingOrder : Qt::DescendingOrder));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetDirectory(CVirtualDirectory *pDir)
|
||||||
|
{
|
||||||
|
mpDirectory = pDir;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void SetSearchString(const QString& rkString)
|
||||||
|
{
|
||||||
|
mSearchString = rkString;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CRESOURCEPROXYMODEL
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
#ifndef CRESOURCETABLEMODEL
|
||||||
|
#define CRESOURCETABLEMODEL
|
||||||
|
|
||||||
|
#include "Editor/UICommon.h"
|
||||||
|
#include <Core/GameProject/CResourceEntry.h>
|
||||||
|
#include <Core/GameProject/CResourceIterator.h>
|
||||||
|
#include <Core/GameProject/CResourceStore.h>
|
||||||
|
#include <Core/Resource/CResource.h>
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
class CResourceTableModel : public QAbstractTableModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QList<CResourceEntry*> mEntries;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CResourceTableModel(QObject *pParent = 0)
|
||||||
|
: QAbstractTableModel(pParent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex& /*rkParent*/) const
|
||||||
|
{
|
||||||
|
return mEntries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int columnCount(const QModelIndex& /*rkParent*/) const
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex& rkIndex, int Role) const
|
||||||
|
{
|
||||||
|
CResourceEntry *pEntry = mEntries[rkIndex.row()];
|
||||||
|
u32 Col = rkIndex.column();
|
||||||
|
|
||||||
|
if (Role == Qt::DisplayRole)
|
||||||
|
{
|
||||||
|
if (Col == 0) return TO_QSTRING(pEntry->Name());
|
||||||
|
if (Col == 1) return TO_QSTRING(GetResourceTypeName(pEntry->ResourceType()));
|
||||||
|
|
||||||
|
if (Col == 2)
|
||||||
|
{
|
||||||
|
u64 Size = pEntry->Size();
|
||||||
|
return Size ? TO_QSTRING( TString::FileSizeString(pEntry->Size()) ) : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (Role == Qt::ToolTipRole)
|
||||||
|
return TO_QSTRING(pEntry->Directory()->FullPath() + pEntry->Name());
|
||||||
|
|
||||||
|
return QVariant::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
CResourceEntry* IndexEntry(const QModelIndex& rkIndex) const
|
||||||
|
{
|
||||||
|
return mEntries[rkIndex.row()];
|
||||||
|
}
|
||||||
|
|
||||||
|
void FillEntryList(CResourceStore *pStore)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
mEntries.clear();
|
||||||
|
|
||||||
|
for (CResourceIterator It(pStore); It; ++It)
|
||||||
|
{
|
||||||
|
if (It->IsTransient()) continue;
|
||||||
|
EResType Type = It->ResourceType();
|
||||||
|
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case eArea:
|
||||||
|
case eAreaCollision:
|
||||||
|
case eAreaLights:
|
||||||
|
case eAreaMaterials:
|
||||||
|
case eAreaSurfaceBounds:
|
||||||
|
case eAreaOctree:
|
||||||
|
case eAreaVisibilityTree:
|
||||||
|
case eMapArea:
|
||||||
|
case eMapWorld:
|
||||||
|
case ePathfinding:
|
||||||
|
case ePortalArea:
|
||||||
|
case eSaveArea:
|
||||||
|
case eSaveWorld:
|
||||||
|
case eStaticGeometryMap:
|
||||||
|
case eTweak:
|
||||||
|
case eWorld:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
mEntries << *It;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CRESOURCELISTMODEL
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
#ifndef CVIRTUALDIRECTORYMODEL
|
||||||
|
#define CVIRTUALDIRECTORYMODEL
|
||||||
|
|
||||||
|
#include "Editor/UICommon.h"
|
||||||
|
#include <Core/GameProject/CVirtualDirectory.h>
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
class CVirtualDirectoryModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
CVirtualDirectory *mpRoot;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CVirtualDirectoryModel(QObject *pParent = 0)
|
||||||
|
: QAbstractItemModel(pParent)
|
||||||
|
, mpRoot(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QModelIndex index(int Row, int Column, const QModelIndex& rkParent) const
|
||||||
|
{
|
||||||
|
if (!hasIndex(Row, Column, rkParent))
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
CVirtualDirectory *pDir = IndexDirectory(rkParent);
|
||||||
|
|
||||||
|
if (pDir && pDir->NumSubdirectories() > (u32) Row)
|
||||||
|
return createIndex(Row, Column, pDir->SubdirectoryByIndex(Row));
|
||||||
|
|
||||||
|
else if (!pDir)
|
||||||
|
return createIndex(Row, Column, mpRoot);
|
||||||
|
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex parent(const QModelIndex& rkChild) const
|
||||||
|
{
|
||||||
|
CVirtualDirectory *pDir = IndexDirectory(rkChild);
|
||||||
|
CVirtualDirectory *pParent = pDir->Parent();
|
||||||
|
|
||||||
|
if (pParent)
|
||||||
|
{
|
||||||
|
CVirtualDirectory *pGrandparent = pParent->Parent();
|
||||||
|
|
||||||
|
if (pGrandparent)
|
||||||
|
{
|
||||||
|
for (u32 iSub = 0; iSub < pGrandparent->NumSubdirectories(); iSub++)
|
||||||
|
{
|
||||||
|
if (pGrandparent->SubdirectoryByIndex(iSub) == pParent)
|
||||||
|
return createIndex(iSub, 0, pParent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else return createIndex(0, 0, mpRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex& rkParent) const
|
||||||
|
{
|
||||||
|
CVirtualDirectory *pDir = IndexDirectory(rkParent);
|
||||||
|
if (pDir) return pDir->NumSubdirectories();
|
||||||
|
else return mpRoot ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int columnCount(const QModelIndex& /*rkParent*/) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex& rkIndex, int Role) const
|
||||||
|
{
|
||||||
|
if (Role == Qt::DisplayRole || Role == Qt::ToolTipRole)
|
||||||
|
{
|
||||||
|
CVirtualDirectory *pDir = IndexDirectory(rkIndex);
|
||||||
|
if (pDir) return TO_QSTRING(pDir->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Role == Qt::DecorationRole)
|
||||||
|
{
|
||||||
|
return QIcon(":/icons/Open_24px.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CVirtualDirectory* IndexDirectory(const QModelIndex& rkIndex) const
|
||||||
|
{
|
||||||
|
if (!rkIndex.isValid()) return nullptr;
|
||||||
|
return static_cast<CVirtualDirectory*>(rkIndex.internalPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetRoot(CVirtualDirectory *pDir)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
mpRoot = pDir;
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CVIRTUALDIRECTORYMODEL
|
||||||
|
|
Loading…
Reference in New Issue