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!
|
||||
#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
|
||||
|
||||
// ************ TBasicString ************
|
||||
|
@ -846,7 +846,7 @@ public:
|
|||
|
||||
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);
|
||||
|
||||
while (Out.Back() == CHAR_LITERAL('0') && NumZeroes > MinDecimals)
|
||||
|
@ -858,6 +858,39 @@ public:
|
|||
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)
|
||||
{
|
||||
return HexString((unsigned long) Num, Width, AddPrefix, Uppercase);
|
||||
|
|
|
@ -195,7 +195,8 @@ HEADERS += \
|
|||
GameProject/CGameExporter.h \
|
||||
GameProject/CResourceStore.h \
|
||||
GameProject/CVirtualDirectory.h \
|
||||
GameProject/CResourceEntry.h
|
||||
GameProject/CResourceEntry.h \
|
||||
GameProject/CResourceIterator.h
|
||||
|
||||
# Source Files
|
||||
SOURCES += \
|
||||
|
|
|
@ -171,6 +171,7 @@ void CGameExporter::LoadPaks()
|
|||
for (auto It = mPaks.begin(); It != mPaks.end(); It++)
|
||||
{
|
||||
TWideString PakPath = *It;
|
||||
TWideString PakName = PakPath.GetFileName(false);
|
||||
TString CharPak = PakPath.ToUTF8();
|
||||
CFileInStream Pak(CharPak.ToStdString(), IOUtil::eBigEndian);
|
||||
|
||||
|
@ -203,6 +204,7 @@ void CGameExporter::LoadPaks()
|
|||
u32 NameLen = Pak.ReadLong();
|
||||
TString Name = Pak.ReadString(NameLen);
|
||||
pCollection->AddResource(Name, ResID, ResType);
|
||||
SetResourcePath(ResID.ToLongLong(), PakName + L"\\", Name.ToUTF16());
|
||||
}
|
||||
|
||||
u32 NumResources = Pak.ReadLong();
|
||||
|
@ -261,6 +263,7 @@ void CGameExporter::LoadPaks()
|
|||
CFourCC ResType = Pak.ReadLong();
|
||||
CUniqueID ResID(Pak, IDLength);
|
||||
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)
|
||||
, mNeedsRecook(false)
|
||||
, mTransient(Transient)
|
||||
, mCachedSize(-1)
|
||||
, mCachedUppercaseName(rkFilename.ToUpper())
|
||||
{
|
||||
mpDirectory = mpStore->GetVirtualDirectory(rkDir, Transient, true);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
// 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);
|
||||
|
||||
mName = rkName;
|
||||
mCachedUppercaseName = rkName.ToUpper();
|
||||
|
||||
// Move files
|
||||
if (HasDirectory)
|
||||
|
|
|
@ -21,6 +21,9 @@ class CResourceEntry
|
|||
bool mNeedsRecook;
|
||||
bool mTransient;
|
||||
|
||||
mutable u64 mCachedSize;
|
||||
mutable TWideString mCachedUppercaseName; // This is used to speed up case-insensitive sorting.
|
||||
|
||||
public:
|
||||
CResourceEntry(CResourceStore *pStore, const CUniqueID& rkID,
|
||||
const TWideString& rkDir, const TWideString& rkFilename,
|
||||
|
@ -30,6 +33,8 @@ public:
|
|||
bool HasCookedVersion() const;
|
||||
TString RawAssetPath(bool Relative = false) const;
|
||||
TString CookedAssetPath(bool Relative = false) const;
|
||||
bool IsInDirectory(CVirtualDirectory *pDir) const;
|
||||
u64 Size() const;
|
||||
bool NeedsRecook() const;
|
||||
void SetGame(EGame NewGame);
|
||||
CResource* Load();
|
||||
|
@ -48,6 +53,7 @@ public:
|
|||
inline EGame Game() const { return mGame; }
|
||||
inline CVirtualDirectory* Directory() const { return mpDirectory; }
|
||||
inline TWideString Name() const { return mName; }
|
||||
inline TWideString UppercaseName() const { return mCachedUppercaseName; }
|
||||
inline EResType ResourceType() const { return mType; }
|
||||
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
|
||||
{
|
||||
friend class CResourceIterator;
|
||||
|
||||
CGameProject *mpProj;
|
||||
CVirtualDirectory *mpProjectRoot;
|
||||
std::vector<CVirtualDirectory*> mTransientRoots;
|
||||
|
@ -61,7 +63,8 @@ public:
|
|||
void SetTransientLoadDir(const TString& rkDir);
|
||||
|
||||
// Accessors
|
||||
inline CGameProject* ActiveProject() const { return mpProj; }
|
||||
inline CGameProject* ActiveProject() const { return mpProj; }
|
||||
inline CVirtualDirectory* RootDirectory() const { return mpProjectRoot; }
|
||||
};
|
||||
|
||||
extern CResourceStore *gpResourceStore;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "CProjectOverviewDialog.h"
|
||||
#include "ui_CProjectOverviewDialog.h"
|
||||
#include "UICommon.h"
|
||||
#include "Editor/ResourceBrowser/CResourceBrowser.h"
|
||||
#include <Common/AssertMacro.h>
|
||||
#include <Core/GameProject/CGameExporter.h>
|
||||
#include <QFileDialog>
|
||||
|
@ -18,6 +19,7 @@ CProjectOverviewDialog::CProjectOverviewDialog(QWidget *pParent)
|
|||
connect(mpUI->ExportGameButton, SIGNAL(clicked()), this, SLOT(ExportGame()));
|
||||
connect(mpUI->LoadWorldButton, SIGNAL(clicked()), this, SLOT(LoadWorld()));
|
||||
connect(mpUI->LaunchEditorButton, SIGNAL(clicked()), this, SLOT(LaunchEditor()));
|
||||
connect(mpUI->ViewResourcesButton, SIGNAL(clicked()), this, SLOT(LaunchResourceBrowser()));
|
||||
}
|
||||
|
||||
CProjectOverviewDialog::~CProjectOverviewDialog()
|
||||
|
@ -164,3 +166,9 @@ void CProjectOverviewDialog::LaunchEditor()
|
|||
|
||||
gpResourceStore->DestroyUnreferencedResources();
|
||||
}
|
||||
|
||||
void CProjectOverviewDialog::LaunchResourceBrowser()
|
||||
{
|
||||
CResourceBrowser Browser(this);
|
||||
Browser.exec();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ public slots:
|
|||
void ExportGame();
|
||||
void LoadWorld();
|
||||
void LaunchEditor();
|
||||
void LaunchResourceBrowser();
|
||||
|
||||
void SetupWorldsList();
|
||||
};
|
||||
|
|
|
@ -32,6 +32,13 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ViewResourcesButton">
|
||||
<property name="text">
|
||||
<string>View Resources</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="WorldsGroupBox">
|
||||
<property name="sizePolicy">
|
||||
|
|
|
@ -164,7 +164,11 @@ HEADERS += \
|
|||
CGridRenderable.h \
|
||||
CharacterEditor/CSkeletonHierarchyModel.h \
|
||||
CLineRenderable.h \
|
||||
CProjectOverviewDialog.h
|
||||
CProjectOverviewDialog.h \
|
||||
ResourceBrowser/CResourceBrowser.h \
|
||||
ResourceBrowser/CResourceTableModel.h \
|
||||
ResourceBrowser/CResourceProxyModel.h \
|
||||
ResourceBrowser/CVirtualDirectoryModel.h
|
||||
|
||||
# Source Files
|
||||
SOURCES += \
|
||||
|
@ -225,7 +229,8 @@ SOURCES += \
|
|||
CharacterEditor/CCharacterEditor.cpp \
|
||||
CharacterEditor/CCharacterEditorViewport.cpp \
|
||||
CharacterEditor/CSkeletonHierarchyModel.cpp \
|
||||
CProjectOverviewDialog.cpp
|
||||
CProjectOverviewDialog.cpp \
|
||||
ResourceBrowser/CResourceBrowser.cpp
|
||||
|
||||
# UI Files
|
||||
FORMS += \
|
||||
|
@ -247,4 +252,5 @@ FORMS += \
|
|||
WorldEditor/CRepackInfoDialog.ui \
|
||||
CAboutDialog.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