mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-06-22 14:33:43 +00:00
Added functionality to import filenames from .pak.contents.txt files
This commit is contained in:
parent
ed446ccbec
commit
d96a3c2af7
@ -317,4 +317,5 @@ SOURCES += \
|
|||||||
Resource/Animation/CSkeleton.cpp \
|
Resource/Animation/CSkeleton.cpp \
|
||||||
Resource/Animation/IMetaAnimation.cpp \
|
Resource/Animation/IMetaAnimation.cpp \
|
||||||
Resource/Animation/IMetaTransition.cpp \
|
Resource/Animation/IMetaTransition.cpp \
|
||||||
GameProject/AssetNameGeneration.cpp
|
GameProject/AssetNameGeneration.cpp \
|
||||||
|
GameProject/CAssetNameMap.cpp
|
||||||
|
@ -207,10 +207,11 @@ void GenerateAssetNames(CGameProject *pProj)
|
|||||||
{
|
{
|
||||||
TString Name = pInst->InstanceName();
|
TString Name = pInst->InstanceName();
|
||||||
|
|
||||||
if (Name.EndsWith(".scan"))
|
if (Name.EndsWith(".SCAN", false))
|
||||||
{
|
{
|
||||||
TIDString ScanIDString = (pProj->Game() <= ePrime ? "0x4:0x0" : "0xBDBEC295:0xB94E9BE7");
|
TIDString ScanIDString = (pProj->Game() <= ePrime ? "0x4:0x0" : "0xBDBEC295:0xB94E9BE7");
|
||||||
TAssetProperty *pScanProperty = TPropCast<TAssetProperty>(pInst->PropertyByIDString(ScanIDString));
|
TAssetProperty *pScanProperty = TPropCast<TAssetProperty>(pInst->PropertyByIDString(ScanIDString));
|
||||||
|
ASSERT(pScanProperty); // Temporary assert to remind myself later to update this code when uncooked properties are added to the template
|
||||||
|
|
||||||
if (pScanProperty)
|
if (pScanProperty)
|
||||||
{
|
{
|
||||||
@ -220,6 +221,10 @@ void GenerateAssetNames(CGameProject *pProj)
|
|||||||
if (pEntry && !pEntry->IsNamed())
|
if (pEntry && !pEntry->IsNamed())
|
||||||
{
|
{
|
||||||
TWideString ScanName = Name.ToUTF16().ChopBack(5);
|
TWideString ScanName = Name.ToUTF16().ChopBack(5);
|
||||||
|
|
||||||
|
if (ScanName.StartsWith(L"POI_"))
|
||||||
|
ScanName = ScanName.ChopFront(4);
|
||||||
|
|
||||||
ApplyGeneratedName(pEntry, pEntry->DirectoryPath(), ScanName);
|
ApplyGeneratedName(pEntry, pEntry->DirectoryPath(), ScanName);
|
||||||
|
|
||||||
CScan *pScan = (CScan*) pEntry->Load();
|
CScan *pScan = (CScan*) pEntry->Load();
|
||||||
@ -232,6 +237,34 @@ void GenerateAssetNames(CGameProject *pProj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (pInst->ObjectTypeID() == 0x17 || pInst->ObjectTypeID() == FOURCC("MEMO"))
|
||||||
|
{
|
||||||
|
TString Name = pInst->InstanceName();
|
||||||
|
|
||||||
|
if (Name.EndsWith(".STRG", false))
|
||||||
|
{
|
||||||
|
u32 StringPropID = (pProj->Game() <= ePrime ? 0x4 : 0x9182250C);
|
||||||
|
TAssetProperty *pStringProperty = TPropCast<TAssetProperty>(pInst->Properties()->PropertyByID(StringPropID));
|
||||||
|
ASSERT(pStringProperty); // Temporary assert to remind myself later to update this code when uncooked properties are added to the template
|
||||||
|
|
||||||
|
if (pStringProperty)
|
||||||
|
{
|
||||||
|
CAssetID StringID = pStringProperty->Get();
|
||||||
|
CResourceEntry *pEntry = pStore->FindEntry(StringID);
|
||||||
|
|
||||||
|
if (pEntry && !pEntry->IsNamed())
|
||||||
|
{
|
||||||
|
TWideString StringName = Name.ToUTF16().ChopBack(5);
|
||||||
|
|
||||||
|
if (StringName.StartsWith(L"HUDMemo - "))
|
||||||
|
StringName = StringName.ChopFront(10);
|
||||||
|
|
||||||
|
ApplyGeneratedName(pEntry, pEntry->DirectoryPath(), StringName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
50
src/Core/GameProject/CAssetNameMap.cpp
Normal file
50
src/Core/GameProject/CAssetNameMap.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "CAssetNameMap.h"
|
||||||
|
|
||||||
|
std::map<EGame, CAssetNameMap*> CAssetNameMap::smGameMap;
|
||||||
|
|
||||||
|
CAssetNameMap::CAssetNameMap(EGame Game)
|
||||||
|
: mGame(Game)
|
||||||
|
{
|
||||||
|
TString ListPath = GetAssetListPath(mGame);
|
||||||
|
CXMLReader Reader(ListPath);
|
||||||
|
Serialize(Reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAssetNameMap::SaveAssetNames()
|
||||||
|
{
|
||||||
|
TString ListPath = GetAssetListPath(mGame);
|
||||||
|
CXMLWriter Writer(ListPath, "AssetList", 0, mGame);
|
||||||
|
Serialize(Writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAssetNameMap::GetNameInfo(CAssetID ID, TString& rOutDirectory, TString& rOutName)
|
||||||
|
{
|
||||||
|
auto It = mMap.find(ID);
|
||||||
|
|
||||||
|
if (It != mMap.end())
|
||||||
|
{
|
||||||
|
SAssetNameInfo& rInfo = It->second;
|
||||||
|
rOutName = rInfo.Name;
|
||||||
|
rOutDirectory = rInfo.Directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rOutDirectory = "Uncategorized\\";
|
||||||
|
rOutName = ID.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAssetNameMap::CopyFromStore(CResourceStore *pStore /*= gpResourceStore*/)
|
||||||
|
{
|
||||||
|
for (CResourceIterator It(pStore); It; ++It)
|
||||||
|
{
|
||||||
|
if (It->IsCategorized() || It->IsNamed())
|
||||||
|
{
|
||||||
|
CAssetID ID = It->ID();
|
||||||
|
TWideString Name = It->Name();
|
||||||
|
TWideString Directory = It->Directory()->FullPath();
|
||||||
|
mMap[ID] = SAssetNameInfo { Name, Directory };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,84 +10,50 @@
|
|||||||
|
|
||||||
const TString gkAssetListDir = "..\\resources\\list\\";
|
const TString gkAssetListDir = "..\\resources\\list\\";
|
||||||
|
|
||||||
struct SAssetNameInfo
|
|
||||||
{
|
|
||||||
TWideString Name;
|
|
||||||
TWideString Directory;
|
|
||||||
|
|
||||||
void Serialize(IArchive& rArc)
|
|
||||||
{
|
|
||||||
rArc << SERIAL_AUTO(Name) << SERIAL_AUTO(Directory);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CAssetNameMap
|
class CAssetNameMap
|
||||||
{
|
{
|
||||||
typedef std::map<CAssetID, SAssetNameInfo> TAssetMap;
|
struct SAssetNameInfo
|
||||||
std::shared_ptr<TAssetMap> mpMap;
|
{
|
||||||
|
TWideString Name;
|
||||||
|
TWideString Directory;
|
||||||
|
|
||||||
|
void Serialize(IArchive& rArc)
|
||||||
|
{
|
||||||
|
rArc << SERIAL_AUTO(Name) << SERIAL_AUTO(Directory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EGame mGame;
|
||||||
|
std::map<CAssetID, SAssetNameInfo> mMap;
|
||||||
|
static std::map<EGame, CAssetNameMap*> smGameMap;
|
||||||
|
|
||||||
|
// Private Methods
|
||||||
|
CAssetNameMap(EGame Game);
|
||||||
|
|
||||||
void Serialize(IArchive& rArc)
|
void Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
rArc << SERIAL_CONTAINER("AssetNameMap", *mpMap.get(), "Asset");
|
rArc << SERIAL_CONTAINER("AssetNameMap", mMap, "Asset");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CAssetNameMap()
|
void SaveAssetNames();
|
||||||
{
|
void GetNameInfo(CAssetID ID, TString& rOutDirectory, TString& rOutName);
|
||||||
mpMap = std::make_shared<TAssetMap>(TAssetMap());
|
void CopyFromStore(CResourceStore *pStore);
|
||||||
}
|
|
||||||
|
|
||||||
void GetNameInfo(CAssetID ID, TString& rOutDirectory, TString& rOutName)
|
|
||||||
{
|
|
||||||
auto It = mpMap->find(ID);
|
|
||||||
|
|
||||||
if (It != mpMap->end())
|
|
||||||
{
|
|
||||||
SAssetNameInfo& rInfo = It->second;
|
|
||||||
rOutName = rInfo.Name;
|
|
||||||
rOutDirectory = rInfo.Directory;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rOutDirectory = "Uncategorized\\";
|
|
||||||
rOutName = ID.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Static Methods
|
||||||
static TString GetAssetListPath(EGame Game)
|
static TString GetAssetListPath(EGame Game)
|
||||||
{
|
{
|
||||||
return gkAssetListDir + "AssetList" + GetGameShortName(Game) + ".xml";
|
return gkAssetListDir + "AssetList" + GetGameShortName(Game) + ".xml";
|
||||||
}
|
}
|
||||||
|
|
||||||
static CAssetNameMap LoadAssetNames(EGame Game)
|
static CAssetNameMap* GetGameNameMap(EGame Game)
|
||||||
{
|
{
|
||||||
TString ListPath = GetAssetListPath(Game);
|
auto Find = smGameMap.find(Game);
|
||||||
CXMLReader Reader(ListPath);
|
if (Find != smGameMap.end()) return Find->second;
|
||||||
|
|
||||||
CAssetNameMap Map;
|
CAssetNameMap *pMap = new CAssetNameMap(Game);
|
||||||
Map.Serialize(Reader);
|
smGameMap[Game] = pMap;
|
||||||
return Map;
|
return pMap;
|
||||||
}
|
|
||||||
|
|
||||||
static void SaveAssetNames(CResourceStore *pStore = gpResourceStore)
|
|
||||||
{
|
|
||||||
CAssetNameMap Map;
|
|
||||||
|
|
||||||
for (CResourceIterator It(pStore); It; ++It)
|
|
||||||
{
|
|
||||||
if (It->IsCategorized() || It->IsNamed())
|
|
||||||
{
|
|
||||||
CAssetID ID = It->ID();
|
|
||||||
TWideString Name = It->Name();
|
|
||||||
TWideString Directory = It->Directory()->FullPath();
|
|
||||||
(*Map.mpMap)[ID] = SAssetNameInfo { Name, Directory };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TString ListPath = GetAssetListPath(pStore->Game());
|
|
||||||
CXMLWriter Writer(ListPath, "AssetList", 0, pStore->Game());
|
|
||||||
Map.Serialize(Writer);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#define EXPORT_COOKED 1
|
#define EXPORT_COOKED 1
|
||||||
|
|
||||||
CGameExporter::CGameExporter(const TString& rkInputDir, const TString& rkOutputDir)
|
CGameExporter::CGameExporter(const TString& rkInputDir, const TString& rkOutputDir)
|
||||||
|
: mpNameMap(nullptr)
|
||||||
{
|
{
|
||||||
mGame = eUnknownGame;
|
mGame = eUnknownGame;
|
||||||
mGameDir = FileUtil::MakeAbsolute(rkInputDir);
|
mGameDir = FileUtil::MakeAbsolute(rkInputDir);
|
||||||
@ -51,7 +52,7 @@ bool CGameExporter::Export()
|
|||||||
mCookedDir = mpStore->CookedDir(false);
|
mCookedDir = mpStore->CookedDir(false);
|
||||||
|
|
||||||
#if USE_ASSET_NAME_MAP
|
#if USE_ASSET_NAME_MAP
|
||||||
mNameMap = CAssetNameMap::LoadAssetNames(mGame);
|
mpNameMap = CAssetNameMap::GetGameNameMap(mGame);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Export game data
|
// Export game data
|
||||||
@ -470,7 +471,7 @@ void CGameExporter::ExportResource(SResourceInstance& rRes)
|
|||||||
|
|
||||||
// Register resource and write to file
|
// Register resource and write to file
|
||||||
TString Directory, Name;
|
TString Directory, Name;
|
||||||
mNameMap.GetNameInfo(rRes.ResourceID, Directory, Name);
|
mpNameMap->GetNameInfo(rRes.ResourceID, Directory, Name);
|
||||||
CResourceEntry *pEntry = mpStore->RegisterResource(rRes.ResourceID, CResource::ResTypeForExtension(rRes.ResourceType), Directory, Name);
|
CResourceEntry *pEntry = mpStore->RegisterResource(rRes.ResourceID, CResource::ResTypeForExtension(rRes.ResourceType), Directory, Name);
|
||||||
|
|
||||||
#if EXPORT_COOKED
|
#if EXPORT_COOKED
|
||||||
|
@ -29,7 +29,7 @@ class CGameExporter
|
|||||||
// Resources
|
// Resources
|
||||||
TWideStringList mPaks;
|
TWideStringList mPaks;
|
||||||
std::map<CAssetID, bool> mAreaDuplicateMap;
|
std::map<CAssetID, bool> mAreaDuplicateMap;
|
||||||
CAssetNameMap mNameMap;
|
CAssetNameMap *mpNameMap;
|
||||||
|
|
||||||
struct SResourceInstance
|
struct SResourceInstance
|
||||||
{
|
{
|
||||||
|
@ -620,3 +620,73 @@ void CResourceStore::SetTransientLoadDir(const TString& rkDir)
|
|||||||
mTransientLoadDir.EnsureEndsWith('\\');
|
mTransientLoadDir.EnsureEndsWith('\\');
|
||||||
Log::Write("Set resource directory: " + rkDir);
|
Log::Write("Set resource directory: " + rkDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CResourceStore::ImportNamesFromPakContentsTxt(const TString& rkTxtPath, bool UnnamedOnly)
|
||||||
|
{
|
||||||
|
// Read file contents -first- then move assets -after-; this
|
||||||
|
// 1. avoids anything fucking up if the contents file is badly formatted and we crash, and
|
||||||
|
// 2. avoids extra redundant moves (since there are redundant entries in the file)
|
||||||
|
std::map<CResourceEntry*, TString> PathMap;
|
||||||
|
FILE *pContentsFile;
|
||||||
|
fopen_s(&pContentsFile, *rkTxtPath, "r");
|
||||||
|
|
||||||
|
if (!pContentsFile)
|
||||||
|
{
|
||||||
|
Log::Error("Failed to open .contents.txt file: " + rkTxtPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!feof(pContentsFile))
|
||||||
|
{
|
||||||
|
// Get new line, parse to extract the ID/path
|
||||||
|
char LineBuffer[512];
|
||||||
|
fgets(LineBuffer, 512, pContentsFile);
|
||||||
|
|
||||||
|
TString Line(LineBuffer);
|
||||||
|
if (Line.IsEmpty()) break;
|
||||||
|
|
||||||
|
u32 IDStart = Line.IndexOfPhrase("0x") + 2;
|
||||||
|
if (IDStart == 1) continue;
|
||||||
|
|
||||||
|
u32 IDEnd = Line.IndexOf(" \t", IDStart);
|
||||||
|
u32 PathStart = IDEnd + 1;
|
||||||
|
u32 PathEnd = Line.Size() - 4;
|
||||||
|
|
||||||
|
TString IDStr = Line.SubString(IDStart, IDEnd - IDStart);
|
||||||
|
TString Path = Line.SubString(PathStart, PathEnd - PathStart);
|
||||||
|
|
||||||
|
CAssetID ID = CAssetID::FromString(IDStr);
|
||||||
|
CResourceEntry *pEntry = FindEntry(ID);
|
||||||
|
|
||||||
|
// Only process this entry if the ID exists
|
||||||
|
if (pEntry)
|
||||||
|
{
|
||||||
|
// Chop name to just after "x_rep"
|
||||||
|
u32 RepStart = Path.IndexOfPhrase("_rep");
|
||||||
|
|
||||||
|
if (RepStart != -1)
|
||||||
|
Path = Path.ChopFront(RepStart + 5);
|
||||||
|
|
||||||
|
// If the "x_rep" folder doesn't exist in this path for some reason, then just chop off the drive letter
|
||||||
|
else
|
||||||
|
Path = Path.ChopFront(3);
|
||||||
|
|
||||||
|
PathMap[pEntry] = Path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(pContentsFile);
|
||||||
|
|
||||||
|
// Assign names
|
||||||
|
for (auto Iter = PathMap.begin(); Iter != PathMap.end(); Iter++)
|
||||||
|
{
|
||||||
|
CResourceEntry *pEntry = Iter->first;
|
||||||
|
if (UnnamedOnly && pEntry->IsNamed()) continue;
|
||||||
|
|
||||||
|
TWideString Path = Iter->second.ToUTF16();
|
||||||
|
pEntry->Move(Path.GetFileDirectory(), Path.GetFileName(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save
|
||||||
|
ConditionalSaveStore();
|
||||||
|
}
|
||||||
|
@ -77,6 +77,8 @@ public:
|
|||||||
bool DeleteResourceEntry(CResourceEntry *pEntry);
|
bool DeleteResourceEntry(CResourceEntry *pEntry);
|
||||||
void SetTransientLoadDir(const TString& rkDir);
|
void SetTransientLoadDir(const TString& rkDir);
|
||||||
|
|
||||||
|
void ImportNamesFromPakContentsTxt(const TString& rkTxtPath, bool UnnamedOnly);
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
inline CGameProject* Project() const { return mpProj; }
|
inline CGameProject* Project() const { return mpProj; }
|
||||||
inline EGame Game() const { return mGame; }
|
inline EGame Game() const { return mGame; }
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include "ui_CResourceBrowser.h"
|
#include "ui_CResourceBrowser.h"
|
||||||
#include "Editor/ModelEditor/CModelEditorWindow.h"
|
#include "Editor/ModelEditor/CModelEditorWindow.h"
|
||||||
#include "Editor/CharacterEditor/CCharacterEditor.h"
|
#include "Editor/CharacterEditor/CCharacterEditor.h"
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMenu>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
||||||
@ -17,7 +19,6 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||||||
mpProxyModel = new CResourceProxyModel(this);
|
mpProxyModel = new CResourceProxyModel(this);
|
||||||
mpProxyModel->setSourceModel(mpModel);
|
mpProxyModel->setSourceModel(mpModel);
|
||||||
mpUI->ResourceTableView->setModel(mpProxyModel);
|
mpUI->ResourceTableView->setModel(mpProxyModel);
|
||||||
RefreshResources();
|
|
||||||
|
|
||||||
QHeaderView *pHeader = mpUI->ResourceTableView->horizontalHeader();
|
QHeaderView *pHeader = mpUI->ResourceTableView->horizontalHeader();
|
||||||
pHeader->setSectionResizeMode(0, QHeaderView::Stretch);
|
pHeader->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||||
@ -26,9 +27,16 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||||||
|
|
||||||
// Set up directory tree model
|
// Set up directory tree model
|
||||||
mpDirectoryModel = new CVirtualDirectoryModel(this);
|
mpDirectoryModel = new CVirtualDirectoryModel(this);
|
||||||
mpDirectoryModel->SetRoot(gpResourceStore ? gpResourceStore->RootDirectory() : nullptr);
|
|
||||||
mpUI->DirectoryTreeView->setModel(mpDirectoryModel);
|
mpUI->DirectoryTreeView->setModel(mpDirectoryModel);
|
||||||
mpUI->DirectoryTreeView->expand(mpDirectoryModel->index(0, 0, QModelIndex()));
|
|
||||||
|
RefreshResources();
|
||||||
|
|
||||||
|
// Set up Import Names menu
|
||||||
|
QMenu *pImportNamesMenu = new QMenu(this);
|
||||||
|
mpUI->ImportNamesButton->setMenu(pImportNamesMenu);
|
||||||
|
|
||||||
|
QAction *pImportFromContentsTxtAction = new QAction("Import from Pak Contents List", this);
|
||||||
|
pImportNamesMenu->addAction(pImportFromContentsTxtAction);
|
||||||
|
|
||||||
// Set up connections
|
// Set up connections
|
||||||
connect(mpUI->StoreComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnStoreChanged(int)));
|
connect(mpUI->StoreComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnStoreChanged(int)));
|
||||||
@ -36,6 +44,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||||||
connect(mpUI->SortComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSortModeChanged(int)));
|
connect(mpUI->SortComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSortModeChanged(int)));
|
||||||
connect(mpUI->DirectoryTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnDirectorySelectionChanged(QModelIndex,QModelIndex)));
|
connect(mpUI->DirectoryTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnDirectorySelectionChanged(QModelIndex,QModelIndex)));
|
||||||
connect(mpUI->ResourceTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnDoubleClickResource(QModelIndex)));
|
connect(mpUI->ResourceTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnDoubleClickResource(QModelIndex)));
|
||||||
|
connect(pImportFromContentsTxtAction, SIGNAL(triggered()), this, SLOT(OnImportPakContentsTxt()));
|
||||||
}
|
}
|
||||||
|
|
||||||
CResourceBrowser::~CResourceBrowser()
|
CResourceBrowser::~CResourceBrowser()
|
||||||
@ -45,19 +54,21 @@ CResourceBrowser::~CResourceBrowser()
|
|||||||
|
|
||||||
void CResourceBrowser::RefreshResources()
|
void CResourceBrowser::RefreshResources()
|
||||||
{
|
{
|
||||||
|
// Fill resource table
|
||||||
mpModel->FillEntryList(mpStore);
|
mpModel->FillEntryList(mpStore);
|
||||||
|
|
||||||
|
// Fill directory tree
|
||||||
|
mpDirectoryModel->SetRoot(mpStore ? mpStore->RootDirectory() : nullptr);
|
||||||
|
QModelIndex RootIndex = mpDirectoryModel->index(0, 0, QModelIndex());
|
||||||
|
mpUI->DirectoryTreeView->expand(RootIndex);
|
||||||
|
mpUI->DirectoryTreeView->clearSelection();
|
||||||
|
OnDirectorySelectionChanged(QModelIndex(), QModelIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceBrowser::OnStoreChanged(int Index)
|
void CResourceBrowser::OnStoreChanged(int Index)
|
||||||
{
|
{
|
||||||
mpStore = (Index == 0 ? gpResourceStore : gpEditorStore);
|
mpStore = (Index == 0 ? gpResourceStore : gpEditorStore);
|
||||||
RefreshResources();
|
RefreshResources();
|
||||||
|
|
||||||
mpDirectoryModel->SetRoot(mpStore ? mpStore->RootDirectory() : nullptr);
|
|
||||||
QModelIndex RootIndex = mpDirectoryModel->index(0, 0, QModelIndex());
|
|
||||||
mpUI->DirectoryTreeView->expand(RootIndex);
|
|
||||||
mpUI->DirectoryTreeView->clearSelection();
|
|
||||||
OnDirectorySelectionChanged(QModelIndex(), QModelIndex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceBrowser::OnSortModeChanged(int Index)
|
void CResourceBrowser::OnSortModeChanged(int Index)
|
||||||
@ -117,3 +128,14 @@ void CResourceBrowser::OnDoubleClickResource(QModelIndex Index)
|
|||||||
else
|
else
|
||||||
QMessageBox::information(this, "Unsupported Resource", "The selected resource type is currently unsupported for editing.");
|
QMessageBox::information(this, "Unsupported Resource", "The selected resource type is currently unsupported for editing.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CResourceBrowser::OnImportPakContentsTxt()
|
||||||
|
{
|
||||||
|
QStringList PathList = QFileDialog::getOpenFileNames(this, "Open pak contents list", "", "*.pak.contents.txt");
|
||||||
|
if (PathList.isEmpty()) return;
|
||||||
|
|
||||||
|
foreach(const QString& rkPath, PathList)
|
||||||
|
mpStore->ImportNamesFromPakContentsTxt(TO_TSTRING(rkPath), false);
|
||||||
|
|
||||||
|
RefreshResources();
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@ public slots:
|
|||||||
void OnSearchStringChanged();
|
void OnSearchStringChanged();
|
||||||
void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex);
|
void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex);
|
||||||
void OnDoubleClickResource(QModelIndex Index);
|
void OnDoubleClickResource(QModelIndex Index);
|
||||||
|
void OnImportPakContentsTxt();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CRESOURCEBROWSER_H
|
#endif // CRESOURCEBROWSER_H
|
||||||
|
@ -187,6 +187,20 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="ImportNamesButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Import Names</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="ExportNamesButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Export Names</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -36,8 +36,15 @@ public:
|
|||||||
|
|
||||||
if (Role == Qt::DisplayRole)
|
if (Role == Qt::DisplayRole)
|
||||||
{
|
{
|
||||||
if (Col == 0) return TO_QSTRING(pEntry->Name());
|
if (Col == 0)
|
||||||
if (Col == 1) return TO_QSTRING(GetResourceTypeName(pEntry->ResourceType()));
|
{
|
||||||
|
return TO_QSTRING(pEntry->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Col == 1)
|
||||||
|
{
|
||||||
|
return TO_QSTRING(GetResourceTypeName(pEntry->ResourceType()));
|
||||||
|
}
|
||||||
|
|
||||||
if (Col == 2)
|
if (Col == 2)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user