Merge pull request #4 from NickJohn547745/feature/new_shit
Add a tonnn of stuff
82
XPlor.pro
@ -1,72 +1,12 @@
|
|||||||
QT += core gui 3dcore 3drender 3dinput 3dextras
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
RC_ICONS = XPlor.ico
|
SUBDIRS += libs/core \
|
||||||
|
libs/compression \
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
libs/encryption \
|
||||||
|
libs/fastfile \
|
||||||
CONFIG += c++17
|
libs/zonefile \
|
||||||
|
libs/ddsfile \
|
||||||
SOURCES += \
|
libs/iwifile \
|
||||||
aboutdialog.cpp \
|
libs/ipakfile \
|
||||||
ddsfile.cpp \
|
app \
|
||||||
ddsviewer.cpp \
|
tests
|
||||||
fastfile.cpp \
|
|
||||||
fastfileviewer.cpp \
|
|
||||||
imagewidget.cpp \
|
|
||||||
iwifile.cpp \
|
|
||||||
iwiviewer.cpp \
|
|
||||||
localstringviewer.cpp \
|
|
||||||
lzokay.cpp \
|
|
||||||
main.cpp \
|
|
||||||
mainwindow.cpp \
|
|
||||||
modelviewer.cpp \
|
|
||||||
iwifile.cpp \
|
|
||||||
techsetviewer.cpp \
|
|
||||||
xtreewidget.cpp \
|
|
||||||
zonefile.cpp \
|
|
||||||
zonefileviewer.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
aboutdialog.h \
|
|
||||||
asset_structs.h \
|
|
||||||
compressor.h \
|
|
||||||
d3dbsp_structs.h \
|
|
||||||
dds_structs.h \
|
|
||||||
ddsfile.h \
|
|
||||||
ddsviewer.h \
|
|
||||||
enums.h \
|
|
||||||
fastfile.h \
|
|
||||||
fastfileviewer.h \
|
|
||||||
imagewidget.h \
|
|
||||||
ipak_structs.h \
|
|
||||||
iwifile.h \
|
|
||||||
iwiviewer.h \
|
|
||||||
localstringviewer.h \
|
|
||||||
lzokay.hpp \
|
|
||||||
lzx.h \
|
|
||||||
mainwindow.h \
|
|
||||||
modelviewer.h \
|
|
||||||
techsetviewer.h \
|
|
||||||
utils.h \
|
|
||||||
xtreewidget.h \
|
|
||||||
iwifile.h \
|
|
||||||
zonefile.h \
|
|
||||||
zonefileviewer.h
|
|
||||||
|
|
||||||
FORMS += \
|
|
||||||
aboutdialog.ui \
|
|
||||||
ddsviewer.ui \
|
|
||||||
fastfileviewer.ui \
|
|
||||||
imagewidget.ui \
|
|
||||||
iwiviewer.ui \
|
|
||||||
localstringviewer.ui \
|
|
||||||
mainwindow.ui \
|
|
||||||
techsetviewer.ui \
|
|
||||||
zonefileviewer.ui
|
|
||||||
|
|
||||||
RESOURCES += \
|
|
||||||
data/Data.qrc
|
|
||||||
|
|
||||||
LIBS += -L$$PWD/DevILSDK/lib/x64/Unicode/Release -lDevIL
|
|
||||||
LIBS += -L$$PWD/DevILSDK/lib/x64/Unicode/Release -lILU
|
|
||||||
LIBS += -L$$PWD/DevILSDK/lib/x64/Unicode/Release -lILUT
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
113
app/app.pro
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
QT += core widgets gui multimedia
|
||||||
|
|
||||||
|
RC_ICONS = app.ico
|
||||||
|
|
||||||
|
SUBDIRS += app
|
||||||
|
|
||||||
|
CONFIG += c++17
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
aboutdialog.cpp \
|
||||||
|
ddsviewer.cpp \
|
||||||
|
fastfileviewer.cpp \
|
||||||
|
imagewidget.cpp \
|
||||||
|
iwiviewer.cpp \
|
||||||
|
localstringviewer.cpp \
|
||||||
|
main.cpp \
|
||||||
|
mainwindow.cpp \
|
||||||
|
materialviewer.cpp \
|
||||||
|
preferenceeditor.cpp \
|
||||||
|
soundviewer.cpp \
|
||||||
|
stringtableviewer.cpp \
|
||||||
|
techsetviewer.cpp \
|
||||||
|
xtreewidget.cpp \
|
||||||
|
xtreewidgetitem.cpp \
|
||||||
|
zonefileviewer.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
aboutdialog.h \
|
||||||
|
d3dbsp_structs.h \
|
||||||
|
ddsviewer.h \
|
||||||
|
fastfileviewer.h \
|
||||||
|
imagewidget.h \
|
||||||
|
iwiviewer.h \
|
||||||
|
localstringviewer.h \
|
||||||
|
mainwindow.h \
|
||||||
|
materialviewer.h \
|
||||||
|
preferenceeditor.h \
|
||||||
|
soundviewer.h \
|
||||||
|
stringtableviewer.h \
|
||||||
|
techsetviewer.h \
|
||||||
|
xtreewidget.h \
|
||||||
|
xtreewidgetitem.h \
|
||||||
|
zonefileviewer.h
|
||||||
|
|
||||||
|
FORMS += \
|
||||||
|
aboutdialog.ui \
|
||||||
|
ddsviewer.ui \
|
||||||
|
fastfileviewer.ui \
|
||||||
|
imagewidget.ui \
|
||||||
|
iwiviewer.ui \
|
||||||
|
localstringviewer.ui \
|
||||||
|
mainwindow.ui \
|
||||||
|
materialviewer.ui \
|
||||||
|
modelviewer.ui \
|
||||||
|
preferenceeditor.ui \
|
||||||
|
soundviewer.ui \
|
||||||
|
stringtableviewer.ui \
|
||||||
|
techsetviewer.ui \
|
||||||
|
zonefileviewer.ui
|
||||||
|
|
||||||
|
RESOURCES += ../data/data.qrc
|
||||||
|
|
||||||
|
app.depends += \
|
||||||
|
libs/core \
|
||||||
|
libs/compression \
|
||||||
|
libs/encryption \
|
||||||
|
libs/fastfile \
|
||||||
|
libs/ddsfile \
|
||||||
|
libs/ipakfile \
|
||||||
|
libs/iwifile \
|
||||||
|
libs/zonefile
|
||||||
|
|
||||||
|
LIBS += \
|
||||||
|
-L$$PWD/../third_party/devil_sdk/lib/ -lDevIL -lILU -lILUT \
|
||||||
|
-L$$PWD/../third_party/zlib/lib/ -lzlib \
|
||||||
|
-L$$OUT_PWD/../libs/ -lcore \
|
||||||
|
-L$$OUT_PWD/../libs/ -lcompression \
|
||||||
|
-L$$OUT_PWD/../libs/ -lencryption \
|
||||||
|
-L$$OUT_PWD/../libs/ -lfastfile \
|
||||||
|
-L$$OUT_PWD/../libs/ -lddsfile \
|
||||||
|
-L$$OUT_PWD/../libs/ -lipakfile \
|
||||||
|
-L$$OUT_PWD/../libs/ -liwifile \
|
||||||
|
-L$$OUT_PWD/../libs/ -lzonefile
|
||||||
|
|
||||||
|
INCLUDEPATH += \
|
||||||
|
$$PWD/../third_party/devil_sdk/include/ \
|
||||||
|
$$PWD/../third_party/zlib/include \
|
||||||
|
$$PWD/../libs/core \
|
||||||
|
$$PWD/../libs/compression \
|
||||||
|
$$PWD/../libs/encryption \
|
||||||
|
$$PWD/../libs/fastfile \
|
||||||
|
$$PWD/../libs/ddsfile \
|
||||||
|
$$PWD/../libs/ipakfile \
|
||||||
|
$$PWD/../libs/iwifile \
|
||||||
|
$$PWD/../libs/zonefile
|
||||||
|
|
||||||
|
DEPENDPATH += \
|
||||||
|
$$PWD/../third_party/devil_sdk/include/ \
|
||||||
|
$$PWD/../third_party/zlib/include \
|
||||||
|
$$PWD/../libs/core \
|
||||||
|
$$PWD/../libs/compression \
|
||||||
|
$$PWD/../libs/encryption \
|
||||||
|
$$PWD/../libs/fastfile \
|
||||||
|
$$PWD/../libs/ddsfile \
|
||||||
|
$$PWD/../libs/ipakfile \
|
||||||
|
$$PWD/../libs/iwifile \
|
||||||
|
$$PWD/../libs/zonefile
|
||||||
|
|
||||||
|
# Copy DLLs to Debug folder
|
||||||
|
QMAKE_POST_LINK += xcopy /Y /E /I \"G:/Projects/Qt/XPlor/third_party/devil_sdk/lib\\*.dll\" \"$$OUT_PWD/debug/\" $$escape_expand(\\n\\t)
|
||||||
|
|
||||||
|
# Copy DLLs to Release folder
|
||||||
|
QMAKE_POST_LINK += xcopy /Y /E /I \"G:/Projects/Qt/XPlor/third_party/devil_sdk/lib\\*.dll\" \"$$OUT_PWD/release/\" $$escape_expand(\\n\\t)
|
||||||
@ -18,9 +18,9 @@ FastFileViewer::~FastFileViewer()
|
|||||||
void FastFileViewer::SetFastFile(std::shared_ptr<FastFile> aFastFile) {
|
void FastFileViewer::SetFastFile(std::shared_ptr<FastFile> aFastFile) {
|
||||||
mFastFile.swap(aFastFile);
|
mFastFile.swap(aFastFile);
|
||||||
|
|
||||||
ui->label_Title->setText(mFastFile->GetFileStem());
|
ui->label_Title->setText(mFastFile->GetStem() + ".ff");
|
||||||
ui->comboBox_Company->setCurrentIndex(mFastFile->GetCompany());
|
ui->comboBox_Company->setCurrentIndex(mFastFile->GetCompany());
|
||||||
ui->comboBox_FileType->setCurrentIndex(mFastFile->GetFileType());
|
ui->comboBox_FileType->setCurrentIndex(mFastFile->GetType());
|
||||||
ui->checkBox_Signed->setChecked(mFastFile->GetSignage() == SIGNAGE_SIGNED);
|
ui->checkBox_Signed->setChecked(mFastFile->GetSignage() == SIGNAGE_SIGNED);
|
||||||
ui->lineEdit_Magic->setText(mFastFile->GetMagic());
|
ui->lineEdit_Magic->setText(mFastFile->GetMagic());
|
||||||
ui->spinBox_Version->setValue(mFastFile->GetVersion());
|
ui->spinBox_Version->setValue(mFastFile->GetVersion());
|
||||||
@ -52,7 +52,7 @@ void LocalStringViewer::SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile) {
|
|||||||
mLocalStrings.clear();
|
mLocalStrings.clear();
|
||||||
ui->tableWidget_Strings->clear();
|
ui->tableWidget_Strings->clear();
|
||||||
|
|
||||||
ui->label_Title->setText(aZoneFile->GetFileStem().section('.', 0, 0) + ".str");
|
ui->label_Title->setText(aZoneFile->GetStem().section('.', 0, 0) + ".str");
|
||||||
for (LocalString localStr : aZoneFile->GetAssetMap().localStrings) {
|
for (LocalString localStr : aZoneFile->GetAssetMap().localStrings) {
|
||||||
AddLocalString(localStr);
|
AddLocalString(localStr);
|
||||||
}
|
}
|
||||||
@ -1,18 +1,29 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "aboutdialog.h"
|
#include "aboutdialog.h"
|
||||||
#include "fastfile.h"
|
#include "fastfile.h"
|
||||||
#include "qheaderview.h"
|
#include "materialviewer.h"
|
||||||
|
#include "preferenceeditor.h"
|
||||||
|
#include "soundviewer.h"
|
||||||
|
#include "stringtableviewer.h"
|
||||||
#include "techsetviewer.h"
|
#include "techsetviewer.h"
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
#include "compressor.h"
|
#include "compression.h"
|
||||||
#include "dds_structs.h"
|
|
||||||
#include "iwifile.h"
|
#include "iwifile.h"
|
||||||
#include "ddsfile.h"
|
#include "ddsfile.h"
|
||||||
|
#include "statusbarmanager.h"
|
||||||
|
#include "ddsviewer.h"
|
||||||
|
#include "fastfileviewer.h"
|
||||||
|
#include "ipak_structs.h"
|
||||||
|
#include "iwiviewer.h"
|
||||||
|
#include "localstringviewer.h"
|
||||||
|
#include "imagewidget.h"
|
||||||
|
#include "xtreewidget.h"
|
||||||
|
#include "zonefileviewer.h"
|
||||||
|
#include "techsetviewer.h"
|
||||||
|
#include "logmanager.h"
|
||||||
|
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
|
|
||||||
#include "DevILSDK/include/IL/il.h"
|
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent), ui(new Ui::MainWindow) {
|
: QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
@ -30,10 +41,33 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
mDiskLumpOrder = QVector<quint32>();
|
mDiskLumpOrder = QVector<quint32>();
|
||||||
mLumps = QMap<quint32, Lump>();
|
mLumps = QMap<quint32, Lump>();
|
||||||
mTreeWidget = new XTreeWidget(this);
|
mTreeWidget = new XTreeWidget(this);
|
||||||
|
mLogWidget = new QPlainTextEdit(this);
|
||||||
|
|
||||||
//ModelViewer *mModelViewer = new ModelViewer(container);
|
//ModelViewer *mModelViewer = new ModelViewer(container);
|
||||||
//mModelViewer->setAcceptDrops(false);
|
//mModelViewer->setAcceptDrops(false);
|
||||||
|
|
||||||
|
mProgressBar = new QProgressBar(this);
|
||||||
|
mProgressBar->setMaximum(100); // Default max value
|
||||||
|
mProgressBar->setVisible(false); // Initially hidden
|
||||||
|
|
||||||
|
connect(&StatusBarManager::instance(), &StatusBarManager::statusUpdated,
|
||||||
|
this, &MainWindow::HandleStatusUpdate);
|
||||||
|
|
||||||
|
connect(&StatusBarManager::instance(), &StatusBarManager::progressUpdated,
|
||||||
|
this, &MainWindow::HandleProgressUpdate);
|
||||||
|
|
||||||
|
connect(&LogManager::instance(), &LogManager::entryAdded,
|
||||||
|
this, &MainWindow::HandleLogEntry);
|
||||||
|
|
||||||
|
statusBar()->addPermanentWidget(mProgressBar);
|
||||||
|
|
||||||
|
connect(ui->actionPreferences, &QAction::triggered, this, [this](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
PreferenceEditor *prefEditor = new PreferenceEditor(this);
|
||||||
|
prefEditor->exec();
|
||||||
|
});
|
||||||
|
|
||||||
ui->tabWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
ui->tabWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
connect(ui->tabWidget, &QTabWidget::customContextMenuRequested, this, [this](const QPoint &pos) {
|
connect(ui->tabWidget, &QTabWidget::customContextMenuRequested, this, [this](const QPoint &pos) {
|
||||||
if (pos.isNull())
|
if (pos.isNull())
|
||||||
@ -104,9 +138,14 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->tabWidget->removeTab(index);
|
ui->tabWidget->removeTab(index);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mTreeWidget, &XTreeWidget::RawFileSelected, this, [this](std::shared_ptr<RawFile> rawFile) {
|
connect(mTreeWidget, &XTreeWidget::Cleared, this, [this]() {
|
||||||
|
ui->tabWidget->clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(mTreeWidget, &XTreeWidget::RawFileSelected, this, [this](std::shared_ptr<RawFile> rawFile, const QString aParentName) {
|
||||||
QPlainTextEdit *scriptEditor = new QPlainTextEdit(this);
|
QPlainTextEdit *scriptEditor = new QPlainTextEdit(this);
|
||||||
scriptEditor->setAcceptDrops(false);
|
scriptEditor->setAcceptDrops(false);
|
||||||
|
scriptEditor->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
if (rawFile->contents.isEmpty()) {
|
if (rawFile->contents.isEmpty()) {
|
||||||
scriptEditor->setPlainText("EMPTY");
|
scriptEditor->setPlainText("EMPTY");
|
||||||
@ -121,15 +160,19 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->tabWidget->addTab(scriptEditor, fileStem);
|
QScrollArea *scrollArea = new QScrollArea(ui->tabWidget);
|
||||||
|
scrollArea->layout()->addWidget(scriptEditor);
|
||||||
|
|
||||||
|
ui->tabWidget->addTab(scrollArea, fileStem);
|
||||||
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_GSCFile.png"));
|
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_GSCFile.png"));
|
||||||
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mTreeWidget, &XTreeWidget::ImageSelected, this, [this](std::shared_ptr<Image> image) {
|
connect(mTreeWidget, &XTreeWidget::ImageSelected, this, [this](std::shared_ptr<Image> image, const QString aParentName) {
|
||||||
ImageWidget *mImageWidget = new ImageWidget(this);
|
ImageWidget *mImageWidget = new ImageWidget(this);
|
||||||
mImageWidget->setAcceptDrops(false);
|
mImageWidget->setAcceptDrops(false);
|
||||||
mImageWidget->SetImage(image);
|
mImageWidget->SetImage(image);
|
||||||
|
mImageWidget->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
QString fileStem = image->materialName;
|
QString fileStem = image->materialName;
|
||||||
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
@ -143,14 +186,15 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mTreeWidget, &XTreeWidget::MenuSelected, this, [this](std::shared_ptr<Menu> menu) {
|
connect(mTreeWidget, &XTreeWidget::MenuSelected, this, [](std::shared_ptr<Menu> menu, const QString aParentName) {
|
||||||
Q_UNUSED(menu);
|
Q_UNUSED(menu);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mTreeWidget, &XTreeWidget::DDSFileSelected, this, [this](std::shared_ptr<DDSFile> ddsFile) {
|
connect(mTreeWidget, &XTreeWidget::DDSFileSelected, this, [this](std::shared_ptr<DDSFile> ddsFile, const QString aParentName) {
|
||||||
DDSViewer *ddsViewer = new DDSViewer(this);
|
DDSViewer *ddsViewer = new DDSViewer(this);
|
||||||
ddsViewer->setAcceptDrops(false);
|
ddsViewer->setAcceptDrops(false);
|
||||||
ddsViewer->SetDDSFile(ddsFile);
|
ddsViewer->SetDDSFile(ddsFile);
|
||||||
|
ddsViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
QString fileStem = ddsFile->fileStem + ".dds";
|
QString fileStem = ddsFile->fileStem + ".dds";
|
||||||
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
@ -164,10 +208,47 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mTreeWidget, &XTreeWidget::IWIFileSelected, this, [this](std::shared_ptr<IWIFile> iwiFile) {
|
connect(mTreeWidget, &XTreeWidget::MaterialSelected, this, [this](std::shared_ptr<Material> material, const QString aParentName) {
|
||||||
|
MaterialViewer *matViewer = new MaterialViewer(this);
|
||||||
|
matViewer->setAcceptDrops(false);
|
||||||
|
matViewer->SetMaterial(material);
|
||||||
|
matViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
|
QString fileStem = material->name;
|
||||||
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
|
if (ui->tabWidget->tabText(i) == fileStem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->tabWidget->addTab(matViewer, fileStem);
|
||||||
|
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_Material.png"));
|
||||||
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(mTreeWidget, &XTreeWidget::DDSFileSelected, this, [this](std::shared_ptr<DDSFile> ddsFile, const QString aParentName) {
|
||||||
|
DDSViewer *ddsViewer = new DDSViewer(this);
|
||||||
|
ddsViewer->setAcceptDrops(false);
|
||||||
|
ddsViewer->SetDDSFile(ddsFile);
|
||||||
|
ddsViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
|
QString fileStem = ddsFile->fileStem + ".dds";
|
||||||
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
|
if (ui->tabWidget->tabText(i) == fileStem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->tabWidget->addTab(ddsViewer, fileStem);
|
||||||
|
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_DDSFile.png"));
|
||||||
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(mTreeWidget, &XTreeWidget::IWIFileSelected, this, [this](std::shared_ptr<IWIFile> iwiFile, const QString aParentName) {
|
||||||
IWIViewer *iwiViewer = new IWIViewer(this);
|
IWIViewer *iwiViewer = new IWIViewer(this);
|
||||||
iwiViewer->setAcceptDrops(false);
|
iwiViewer->setAcceptDrops(false);
|
||||||
iwiViewer->SetIWIFile(iwiFile);
|
iwiViewer->SetIWIFile(iwiFile);
|
||||||
|
iwiViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
QString fileStem = iwiFile->fileStem + ".iwi";
|
QString fileStem = iwiFile->fileStem + ".iwi";
|
||||||
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
@ -181,12 +262,13 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mTreeWidget, &XTreeWidget::FastFileSelected, this, [this](std::shared_ptr<FastFile> aFastFile) {
|
connect(mTreeWidget, &XTreeWidget::FastFileSelected, this, [this](std::shared_ptr<FastFile> aFastFile, const QString aParentName) {
|
||||||
FastFileViewer *fastFileViewer = new FastFileViewer(this);
|
FastFileViewer *fastFileViewer = new FastFileViewer(this);
|
||||||
fastFileViewer->setAcceptDrops(false);
|
fastFileViewer->setAcceptDrops(false);
|
||||||
fastFileViewer->SetFastFile(aFastFile);
|
fastFileViewer->SetFastFile(aFastFile);
|
||||||
|
fastFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
QString fileStem = aFastFile->GetFileStem();
|
QString fileStem = aFastFile->GetStem() + ".ff";
|
||||||
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
if (ui->tabWidget->tabText(i) == fileStem) {
|
if (ui->tabWidget->tabText(i) == fileStem) {
|
||||||
return;
|
return;
|
||||||
@ -198,29 +280,43 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mTreeWidget, &XTreeWidget::ZoneFileSelected, this, [this](std::shared_ptr<ZoneFile> aZoneFile) {
|
connect(mTreeWidget, &XTreeWidget::ZoneFileSelected, this, [this](std::shared_ptr<ZoneFile> aZoneFile, const QString aParentName) {
|
||||||
ZoneFileViewer *zoneFileViewer = new ZoneFileViewer(this);
|
ZoneFileViewer *zoneFileViewer = new ZoneFileViewer(this);
|
||||||
zoneFileViewer->setAcceptDrops(false);
|
zoneFileViewer->setAcceptDrops(false);
|
||||||
zoneFileViewer->SetZoneFile(aZoneFile);
|
zoneFileViewer->SetZoneFile(aZoneFile);
|
||||||
|
zoneFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
QString fileStem = aZoneFile->GetFileStem();
|
QString fileStem = aZoneFile->GetStem() + ".zone";
|
||||||
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
if (ui->tabWidget->tabText(i) == fileStem) {
|
if (ui->tabWidget->tabText(i) == fileStem) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->tabWidget->addTab(zoneFileViewer, fileStem);
|
QWidget *containerWidget = new QWidget();
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(containerWidget);
|
||||||
|
layout->addWidget(zoneFileViewer);
|
||||||
|
containerWidget->setLayout(layout);
|
||||||
|
|
||||||
|
// Create a scroll area and set its properties
|
||||||
|
QScrollArea *scrollArea = new QScrollArea(ui->tabWidget);
|
||||||
|
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||||
|
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||||
|
scrollArea->setWidgetResizable(true); // Important to allow resizing
|
||||||
|
scrollArea->setWidget(containerWidget);
|
||||||
|
|
||||||
|
ui->tabWidget->addTab(scrollArea, fileStem);
|
||||||
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_ZoneFile.png"));
|
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_ZoneFile.png"));
|
||||||
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mTreeWidget, &XTreeWidget::LocalStringSelected, this, [this](std::shared_ptr<ZoneFile> aZoneFile) {
|
connect(mTreeWidget, &XTreeWidget::LocalStringSelected, this, [this](std::shared_ptr<ZoneFile> aZoneFile, const QString aParentName) {
|
||||||
LocalStringViewer *localStrViewer = new LocalStringViewer(this);
|
LocalStringViewer *localStrViewer = new LocalStringViewer(this);
|
||||||
localStrViewer->setAcceptDrops(false);
|
localStrViewer->setAcceptDrops(false);
|
||||||
localStrViewer->SetZoneFile(aZoneFile);
|
localStrViewer->SetZoneFile(aZoneFile);
|
||||||
|
localStrViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
QString fileStem = aZoneFile->GetFileStem() + ".str";
|
QString fileStem = aZoneFile->GetStem() + ".str";
|
||||||
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
if (ui->tabWidget->tabText(i) == fileStem) {
|
if (ui->tabWidget->tabText(i) == fileStem) {
|
||||||
return;
|
return;
|
||||||
@ -232,11 +328,11 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mTreeWidget, &XTreeWidget::TechSetSelected, this, [this](std::shared_ptr<TechSet> aTechSet) {
|
connect(mTreeWidget, &XTreeWidget::TechSetSelected, this, [this](std::shared_ptr<TechSet> aTechSet, const QString aParentName) {
|
||||||
|
|
||||||
TechSetViewer *techSetViewer = new TechSetViewer(this);
|
TechSetViewer *techSetViewer = new TechSetViewer(this);
|
||||||
techSetViewer->setAcceptDrops(false);
|
techSetViewer->setAcceptDrops(false);
|
||||||
techSetViewer->SetTechSet(aTechSet);
|
techSetViewer->SetTechSet(aTechSet);
|
||||||
|
techSetViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
QString fileStem = aTechSet->name;
|
QString fileStem = aTechSet->name;
|
||||||
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
@ -250,6 +346,61 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(mTreeWidget, &XTreeWidget::StrTableSelected, this, [this](std::shared_ptr<StringTable> aStrTable, const QString aParentName) {
|
||||||
|
StringTableViewer *strTableViewer = new StringTableViewer(this);
|
||||||
|
strTableViewer->setAcceptDrops(false);
|
||||||
|
strTableViewer->SetStringTable(aStrTable);
|
||||||
|
strTableViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
|
QString fileStem = aStrTable->name;
|
||||||
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
|
if (ui->tabWidget->tabText(i) == fileStem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->tabWidget->addTab(strTableViewer, fileStem);
|
||||||
|
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_StringTable.png"));
|
||||||
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(mTreeWidget, &XTreeWidget::SoundSelected, this, [this](std::shared_ptr<Sound> aSound, const QString aParentName) {
|
||||||
|
SoundViewer *soundViewer = new SoundViewer(this);
|
||||||
|
soundViewer->setAcceptDrops(false);
|
||||||
|
soundViewer->SetSound(aSound);
|
||||||
|
soundViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
|
||||||
|
|
||||||
|
QString fileStem = aSound->path.split('/').last();
|
||||||
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
|
if (ui->tabWidget->tabText(i) == fileStem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->tabWidget->addTab(soundViewer, fileStem);
|
||||||
|
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_Sound.png"));
|
||||||
|
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(mTreeWidget, &XTreeWidget::ItemSelected, this, [this](const QString itemText) {
|
||||||
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
|
if (ui->tabWidget->tabText(i) == itemText) {
|
||||||
|
ui->tabWidget->setCurrentIndex(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(mTreeWidget, &XTreeWidget::ItemClosed, this, [this](const QString itemText) {
|
||||||
|
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||||
|
const QString parentName = ui->tabWidget->widget(i)->property("PARENT_NAME").toString();
|
||||||
|
if (parentName == itemText) {
|
||||||
|
ui->tabWidget->removeTab(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Connect Help > About dialog
|
// Connect Help > About dialog
|
||||||
connect(ui->actionAbout, &QAction::triggered, this, [this](bool checked) {
|
connect(ui->actionAbout, &QAction::triggered, this, [this](bool checked) {
|
||||||
Q_UNUSED(checked);
|
Q_UNUSED(checked);
|
||||||
@ -273,8 +424,14 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
|
|
||||||
QDockWidget *treeDockWidget = new QDockWidget(this);
|
QDockWidget *treeDockWidget = new QDockWidget(this);
|
||||||
treeDockWidget->setWidget(mTreeWidget);
|
treeDockWidget->setWidget(mTreeWidget);
|
||||||
|
treeDockWidget->setWindowTitle("Tree Browser");
|
||||||
addDockWidget(Qt::LeftDockWidgetArea, treeDockWidget);
|
addDockWidget(Qt::LeftDockWidgetArea, treeDockWidget);
|
||||||
|
|
||||||
|
QDockWidget *logDockWidget = new QDockWidget(this);
|
||||||
|
logDockWidget->setWidget(mLogWidget);
|
||||||
|
logDockWidget->setWindowTitle("Logs");
|
||||||
|
addDockWidget(Qt::RightDockWidgetArea, logDockWidget);
|
||||||
|
|
||||||
ui->toolBar->addAction(ui->actionNew_Fast_File);
|
ui->toolBar->addAction(ui->actionNew_Fast_File);
|
||||||
ui->toolBar->addAction(ui->actionNew_Zone_File);
|
ui->toolBar->addAction(ui->actionNew_Zone_File);
|
||||||
ui->toolBar->addAction(ui->actionOpen_Fast_File);
|
ui->toolBar->addAction(ui->actionOpen_Fast_File);
|
||||||
@ -318,15 +475,18 @@ void MainWindow::Reset() {
|
|||||||
and opens the selected file.
|
and opens the selected file.
|
||||||
*/
|
*/
|
||||||
bool MainWindow::OpenFastFile(const QString aFastFilePath) {
|
bool MainWindow::OpenFastFile(const QString aFastFilePath) {
|
||||||
FastFile fastFile;
|
const QString fastFileStem = aFastFilePath.section("/", -1, -1).section('.', 0, 0);
|
||||||
if (!fastFile.Load(aFastFilePath)) {
|
if (mTreeWidget->HasFastFile(fastFileStem)) {
|
||||||
qDebug() << "Error: Failed to load fast file!";
|
LogManager::instance().addError("Can't add duplicate file!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mTreeWidget->AddFastFile(std::make_shared<FastFile>(fastFile));
|
|
||||||
|
std::shared_ptr<FastFile> fastFile = FastFile::Open(aFastFilePath);
|
||||||
|
fastFile->SetStem(fastFileStem);
|
||||||
|
mTreeWidget->AddFastFile(fastFile);
|
||||||
|
|
||||||
// Open zone file after decompressing ff and writing
|
// Open zone file after decompressing ff and writing
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -351,14 +511,15 @@ bool MainWindow::OpenFastFile() {
|
|||||||
and opens the selected file.
|
and opens the selected file.
|
||||||
*/
|
*/
|
||||||
bool MainWindow::OpenZoneFile(const QString aZoneFilePath, bool fromFF) {
|
bool MainWindow::OpenZoneFile(const QString aZoneFilePath, bool fromFF) {
|
||||||
|
Q_UNUSED(aZoneFilePath);
|
||||||
Q_UNUSED(fromFF);
|
Q_UNUSED(fromFF);
|
||||||
|
|
||||||
ZoneFile zoneFile;
|
//ZoneFile zoneFile;
|
||||||
if (!zoneFile.Load(aZoneFilePath)) {
|
//if (!zoneFile.Load(aZoneFilePath)) {
|
||||||
qDebug() << "Error: Failed to load zone file!";
|
// qDebug() << "Error: Failed to load zone file!";
|
||||||
return false;
|
// return false;
|
||||||
}
|
//}
|
||||||
mTreeWidget->AddZoneFile(std::make_shared<ZoneFile>(zoneFile));
|
//mTreeWidget->AddZoneFile(std::make_shared<ZoneFile>(zoneFile));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -453,6 +614,28 @@ int MainWindow::LoadFile_DDSFiles(const QStringList aFilePaths) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::HandleLogEntry(const QString &entry) {
|
||||||
|
QString logContents = mLogWidget->toPlainText() + "\n" + entry;
|
||||||
|
if (mLogWidget->toPlainText().isEmpty()) {
|
||||||
|
logContents = entry;
|
||||||
|
}
|
||||||
|
mLogWidget->setPlainText(logContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HandleStatusUpdate(const QString &message, int timeout) {
|
||||||
|
statusBar()->showMessage(message, timeout);
|
||||||
|
mProgressBar->setVisible(false); // Hide progress bar if just a message
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HandleProgressUpdate(const QString &message, int progress, int max) {
|
||||||
|
mProgressBar->setMaximum(max);
|
||||||
|
mProgressBar->setValue(progress);
|
||||||
|
mProgressBar->setVisible(true);
|
||||||
|
|
||||||
|
QString progressText = QString("%1 (%2/%3)").arg(message).arg(progress).arg(max);
|
||||||
|
statusBar()->showMessage(progressText);
|
||||||
|
}
|
||||||
|
|
||||||
int MainWindow::LoadFile_DDS(const QString aFilePath) {
|
int MainWindow::LoadFile_DDS(const QString aFilePath) {
|
||||||
if (!aFilePath.endsWith(".dds", Qt::CaseInsensitive)) {
|
if (!aFilePath.endsWith(".dds", Qt::CaseInsensitive)) {
|
||||||
qDebug() << "Error: Invalid filename " << aFilePath;
|
qDebug() << "Error: Invalid filename " << aFilePath;
|
||||||
@ -572,7 +755,7 @@ int MainWindow::LoadFile_IPAK(const QString aFilePath) {
|
|||||||
|
|
||||||
QString outputFilePath = outputFolder.filePath(QString("%1.iwi").arg(j));
|
QString outputFilePath = outputFolder.filePath(QString("%1.iwi").arg(j));
|
||||||
if (command.compressed) {
|
if (command.compressed) {
|
||||||
data = Compressor::DecompressLZO(data);
|
data = Compression::DecompressLZO(data);
|
||||||
}
|
}
|
||||||
QFile outputFile(outputFilePath);
|
QFile outputFile(outputFilePath);
|
||||||
if (!outputFile.open(QIODevice::WriteOnly)) {
|
if (!outputFile.open(QIODevice::WriteOnly)) {
|
||||||
@ -666,9 +849,9 @@ void MainWindow::dropEvent(QDropEvent *event) {
|
|||||||
foreach (const QUrl url, mimeData->urls()) {
|
foreach (const QUrl url, mimeData->urls()) {
|
||||||
const QString urlStr = url.toLocalFile();
|
const QString urlStr = url.toLocalFile();
|
||||||
if (urlStr.contains(".zone")) {
|
if (urlStr.contains(".zone")) {
|
||||||
OpenZoneFile(urlStr);
|
qDebug() << "OpenZoneFile Returned: " << OpenZoneFile(urlStr);
|
||||||
} else if (urlStr.contains(".ff")) {
|
} else if (urlStr.contains(".ff")) {
|
||||||
OpenFastFile(urlStr);
|
qDebug() << "OpenFastFile Returned: " << OpenFastFile(urlStr);
|
||||||
} else if (urlStr.contains(".ipak")) {
|
} else if (urlStr.contains(".ipak")) {
|
||||||
qDebug() << "LoadFile_IPAK Returned: " << LoadFile_IPAK(urlStr);
|
qDebug() << "LoadFile_IPAK Returned: " << LoadFile_IPAK(urlStr);
|
||||||
} else if (urlStr.contains(".xsub")) {
|
} else if (urlStr.contains(".xsub")) {
|
||||||
@ -689,11 +872,11 @@ void MainWindow::dropEvent(QDropEvent *event) {
|
|||||||
qDebug() << "LZO: Failed to read file!";
|
qDebug() << "LZO: Failed to read file!";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QByteArray data = Compressor::DecompressLZO(lzoFile.readAll());
|
QByteArray data = Compression::DecompressLZO(lzoFile.readAll());
|
||||||
lzoFile.close();
|
lzoFile.close();
|
||||||
|
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
qDebug() << "LZO: Decompressor gave empty result!";
|
qDebug() << "LZO: Decompression gave empty result!";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3,16 +3,7 @@
|
|||||||
|
|
||||||
#include "d3dbsp_structs.h"
|
#include "d3dbsp_structs.h"
|
||||||
#include "asset_structs.h"
|
#include "asset_structs.h"
|
||||||
#include "ddsviewer.h"
|
|
||||||
#include "fastfileviewer.h"
|
|
||||||
#include "ipak_structs.h"
|
|
||||||
#include "iwiviewer.h"
|
|
||||||
#include "localstringviewer.h"
|
|
||||||
#include "modelviewer.h"
|
|
||||||
#include "imagewidget.h"
|
|
||||||
#include "xtreewidget.h"
|
#include "xtreewidget.h"
|
||||||
#include "zonefileviewer.h"
|
|
||||||
#include "techsetviewer.h"
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
@ -24,6 +15,7 @@
|
|||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
|
#include <QProgressBar>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -55,6 +47,10 @@ private slots:
|
|||||||
int LoadFile_DDS(const QString aFilePath);
|
int LoadFile_DDS(const QString aFilePath);
|
||||||
int LoadFile_DDSFiles(const QStringList aFilePaths);
|
int LoadFile_DDSFiles(const QStringList aFilePaths);
|
||||||
|
|
||||||
|
void HandleLogEntry(const QString &entry);
|
||||||
|
void HandleStatusUpdate(const QString &message, int timeout);
|
||||||
|
void HandleProgressUpdate(const QString &message, int progress, int max);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||||
@ -72,6 +68,8 @@ private:
|
|||||||
QMap<QString, QTreeWidgetItem*> mTreeMap;
|
QMap<QString, QTreeWidgetItem*> mTreeMap;
|
||||||
QMap<QString, QVector<QPair<QString, QString>>> mStrTableMap;
|
QMap<QString, QVector<QPair<QString, QString>>> mStrTableMap;
|
||||||
XTreeWidget *mTreeWidget;
|
XTreeWidget *mTreeWidget;
|
||||||
|
QPlainTextEdit *mLogWidget;
|
||||||
|
QProgressBar *mProgressBar;
|
||||||
|
|
||||||
quint32 mBSPVersion;
|
quint32 mBSPVersion;
|
||||||
quint32 mDiskLumpCount;
|
quint32 mDiskLumpCount;
|
||||||
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>986</width>
|
<width>1579</width>
|
||||||
<height>692</height>
|
<height>857</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@ -46,7 +46,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>986</width>
|
<width>1579</width>
|
||||||
<height>21</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -58,17 +58,11 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Recent...</string>
|
<string>Recent...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentOpenRecent"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuImport">
|
<widget class="QMenu" name="menuImport">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Import...</string>
|
<string>Import...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::FolderNew"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="actionNew_File_2"/>
|
<addaction name="actionNew_File_2"/>
|
||||||
<addaction name="actionNew_Fast_File"/>
|
<addaction name="actionNew_Fast_File"/>
|
||||||
@ -114,6 +108,8 @@
|
|||||||
<addaction name="menuUndo_History"/>
|
<addaction name="menuUndo_History"/>
|
||||||
<addaction name="menuRedo_History"/>
|
<addaction name="menuRedo_History"/>
|
||||||
<addaction name="actionClear_Undo_History"/>
|
<addaction name="actionClear_Undo_History"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionPreferences"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuHelp">
|
<widget class="QMenu" name="menuHelp">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -140,7 +136,8 @@
|
|||||||
<widget class="QStatusBar" name="statusBar"/>
|
<widget class="QStatusBar" name="statusBar"/>
|
||||||
<action name="actionNew_File_2">
|
<action name="actionNew_File_2">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentNew"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_NewFile.png</normaloff>:/icons/icons/Icon_NewFile.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>New</string>
|
<string>New</string>
|
||||||
@ -148,7 +145,8 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionNew_Fast_File">
|
<action name="actionNew_Fast_File">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentNew"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_NewFile.png</normaloff>:/icons/icons/Icon_NewFile.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>New Fast File</string>
|
<string>New Fast File</string>
|
||||||
@ -156,7 +154,8 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionNew_Zone_File">
|
<action name="actionNew_Zone_File">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentNew"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_NewFile.png</normaloff>:/icons/icons/Icon_NewFile.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>New Zone File</string>
|
<string>New Zone File</string>
|
||||||
@ -164,7 +163,8 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionOpen_Fast_File">
|
<action name="actionOpen_Fast_File">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentOpen"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_OpenFile.png</normaloff>:/icons/icons/Icon_OpenFile.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open Fast File</string>
|
<string>Open Fast File</string>
|
||||||
@ -172,7 +172,8 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionOpen_Zone_File">
|
<action name="actionOpen_Zone_File">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentOpen"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_OpenFile.png</normaloff>:/icons/icons/Icon_OpenFile.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open Zone File</string>
|
<string>Open Zone File</string>
|
||||||
@ -180,7 +181,8 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionOpen_Folder">
|
<action name="actionOpen_Folder">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentOpen"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_OpenFile.png</normaloff>:/icons/icons/Icon_OpenFile.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open Folder</string>
|
<string>Open Folder</string>
|
||||||
@ -188,16 +190,14 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionSave">
|
<action name="actionSave">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentSave"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_Save.png</normaloff>:/icons/icons/Icon_Save.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save</string>
|
<string>Save</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionSave_As">
|
<action name="actionSave_As">
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentSaveAs"/>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save As</string>
|
<string>Save As</string>
|
||||||
</property>
|
</property>
|
||||||
@ -248,24 +248,19 @@
|
|||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionUndo">
|
<action name="actionUndo">
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::EditUndo"/>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Undo</string>
|
<string>Undo</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionRedo">
|
<action name="actionRedo">
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::EditRedo"/>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Redo</string>
|
<string>Redo</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionCut">
|
<action name="actionCut">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::EditCut"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_Cut.png</normaloff>:/icons/icons/Icon_Cut.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Cut</string>
|
<string>Cut</string>
|
||||||
@ -273,7 +268,8 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionCopy">
|
<action name="actionCopy">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::EditCopy"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_Copy.png</normaloff>:/icons/icons/Icon_Copy.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Copy</string>
|
<string>Copy</string>
|
||||||
@ -281,16 +277,14 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionPaste">
|
<action name="actionPaste">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::EditPaste"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_Paste.png</normaloff>:/icons/icons/Icon_Paste.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Paste</string>
|
<string>Paste</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionRename">
|
<action name="actionRename">
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::MailMessageNew"/>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Rename</string>
|
<string>Rename</string>
|
||||||
</property>
|
</property>
|
||||||
@ -306,9 +300,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionDelete">
|
<action name="actionDelete">
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::EditDelete"/>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Delete</string>
|
<string>Delete</string>
|
||||||
</property>
|
</property>
|
||||||
@ -334,9 +325,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionAbout">
|
<action name="actionAbout">
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::HelpAbout"/>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>About</string>
|
<string>About</string>
|
||||||
</property>
|
</property>
|
||||||
@ -347,22 +335,27 @@
|
|||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionCheck_for_Updates">
|
<action name="actionCheck_for_Updates">
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::SyncSynchronizing"/>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Check for Updates</string>
|
<string>Check for Updates</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionFind_2">
|
<action name="actionFind_2">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="QIcon::ThemeIcon::EditFind"/>
|
<iconset resource="../data/data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_Find.png</normaloff>:/icons/icons/Icon_Find.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Find</string>
|
<string>Find</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionPreferences">
|
||||||
|
<property name="text">
|
||||||
|
<string>Preferences...</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources>
|
||||||
|
<include location="../data/data.qrc"/>
|
||||||
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
42
app/materialviewer.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "materialviewer.h"
|
||||||
|
#include "ui_materialviewer.h"
|
||||||
|
|
||||||
|
MaterialViewer::MaterialViewer(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, ui(new Ui::MaterialViewer) {
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialViewer::~MaterialViewer() {
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ToHexStr(quint32 in) {
|
||||||
|
return QString("%1").arg(in, 8, 16, QChar('0')).toUpper();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialViewer::SetMaterial(std::shared_ptr<Material> aMaterial) {
|
||||||
|
ui->lineEdit_NamePtr->setText(ToHexStr(aMaterial->namePtr));
|
||||||
|
ui->lineEdit_Name->setText(aMaterial->name);
|
||||||
|
ui->lineEdit_RefPtr->setText(ToHexStr(aMaterial->refNamePtr));
|
||||||
|
ui->lineEdit_RefName->setText(aMaterial->refName);
|
||||||
|
ui->lineEdit_Unknowns->setText(ToHexStr(aMaterial->unknownA[0])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[1])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[2])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[3])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[4])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[5])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[6])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[7])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[8])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[9])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[10])
|
||||||
|
+ ToHexStr(aMaterial->unknownA[11]));
|
||||||
|
ui->lineEdit_StateA->setText(ToHexStr(aMaterial->stateBits[0]));
|
||||||
|
ui->lineEdit_StateA->setText(ToHexStr(aMaterial->stateBits[1]));
|
||||||
|
ui->spinBox_TextureCount->setValue(aMaterial->textureCount);
|
||||||
|
ui->spinBox_ConstCount->setValue(aMaterial->constCount);
|
||||||
|
ui->lineEdit_TechSetPtr->setText(ToHexStr(aMaterial->techSetPtr));
|
||||||
|
ui->lineEdit_TexturePtr->setText(ToHexStr(aMaterial->texturePtr));
|
||||||
|
ui->lineEdit_ConstantPtr->setText(ToHexStr(aMaterial->constPtr));
|
||||||
|
}
|
||||||
27
app/materialviewer.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef MATERIALVIEWER_H
|
||||||
|
#define MATERIALVIEWER_H
|
||||||
|
|
||||||
|
#include "asset_structs.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QScrollArea>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MaterialViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MaterialViewer : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MaterialViewer(QWidget *parent = nullptr);
|
||||||
|
~MaterialViewer();
|
||||||
|
|
||||||
|
void SetMaterial(std::shared_ptr<Material> aMaterial);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::MaterialViewer *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MATERIALVIEWER_H
|
||||||
236
app/materialviewer.ui
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MaterialViewer</class>
|
||||||
|
<widget class="QWidget" name="MaterialViewer">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1001</width>
|
||||||
|
<height>650</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_Title">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>16</pointsize>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Material 0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>325</width>
|
||||||
|
<height>398</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>325</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Header</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Name Ptr:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_NamePtr"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Name:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Ref Ptr:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Ref Name:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Unknowns:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>State A:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>State B:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Texture Count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_Name"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_RefPtr"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_RefName"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_Unknowns"/>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_StateA"/>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_StateB"/>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_TextureCount"/>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ConstCount"/>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_TechSetPtr"/>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>Constant Count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>Tech Set Ptr:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>Texture Ptr:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>Constant Ptr:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_TexturePtr"/>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_ConstantPtr"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_4">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>400</width>
|
||||||
|
<height>400</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Data</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_6"/>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>143</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
14
app/modelviewer.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "modelviewer.h"
|
||||||
|
#include "ui_modelviewer.h"
|
||||||
|
|
||||||
|
ModelViewer::ModelViewer(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, ui(new Ui::ModelViewer)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelViewer::~ModelViewer()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
22
app/modelviewer.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef MODELVIEWER_H
|
||||||
|
#define MODELVIEWER_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ModelViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModelViewer : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ModelViewer(QWidget *parent = nullptr);
|
||||||
|
~ModelViewer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::ModelViewer *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MODELVIEWER_H
|
||||||
624
app/modelviewer.ui
Normal file
@ -0,0 +1,624 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ModelViewer</class>
|
||||||
|
<widget class="QWidget" name="ModelViewer">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1001</width>
|
||||||
|
<height>897</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Properties</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Name Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_NamePtr">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_42">
|
||||||
|
<property name="text">
|
||||||
|
<string>Model Name:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Tag Count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_TagCount">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> tags</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Root Tag Count: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_RootTagCount">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> root tags</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Surface Count: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_SurfaceCount">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> surfaces</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Unknown A:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_UnknownA">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bone Name Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_BoneNamePtr">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Parent List Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ParentListPtr">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>Quats Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_QuatsPtr">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>Transformation Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_TransPtr">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>Classification Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="0">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Base Material Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_BaseMatPtr">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="12" column="0">
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>Surfaces Pointer;</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="12" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_SurfacesPtr">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="13" column="0">
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>Material Handlers Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="13" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_MatHandlesPtr">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="14" column="0">
|
||||||
|
<widget class="QLabel" name="label_23">
|
||||||
|
<property name="text">
|
||||||
|
<string>Coll Surf Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="14" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_2">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="15" column="0">
|
||||||
|
<widget class="QLabel" name="label_24">
|
||||||
|
<property name="text">
|
||||||
|
<string>Coll Surface Count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="15" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_3">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="16" column="0">
|
||||||
|
<widget class="QLabel" name="label_25">
|
||||||
|
<property name="text">
|
||||||
|
<string>Contents:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="16" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_4">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="17" column="0">
|
||||||
|
<widget class="QLabel" name="label_26">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bone Info Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="17" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_5">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="18" column="0">
|
||||||
|
<widget class="QLabel" name="label_28">
|
||||||
|
<property name="text">
|
||||||
|
<string>Radius:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="18" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_2"/>
|
||||||
|
</item>
|
||||||
|
<item row="19" column="0">
|
||||||
|
<widget class="QLabel" name="label_29">
|
||||||
|
<property name="text">
|
||||||
|
<string>Min X: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="19" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_3"/>
|
||||||
|
</item>
|
||||||
|
<item row="20" column="0">
|
||||||
|
<widget class="QLabel" name="label_30">
|
||||||
|
<property name="text">
|
||||||
|
<string>Min Y: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="20" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_4"/>
|
||||||
|
</item>
|
||||||
|
<item row="21" column="0">
|
||||||
|
<widget class="QLabel" name="label_31">
|
||||||
|
<property name="text">
|
||||||
|
<string>Min Z: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="21" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_5"/>
|
||||||
|
</item>
|
||||||
|
<item row="22" column="0">
|
||||||
|
<widget class="QLabel" name="label_32">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max X: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="22" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_6"/>
|
||||||
|
</item>
|
||||||
|
<item row="23" column="0">
|
||||||
|
<widget class="QLabel" name="label_33">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max Y: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="23" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_7"/>
|
||||||
|
</item>
|
||||||
|
<item row="24" column="0">
|
||||||
|
<widget class="QLabel" name="label_34">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max Z: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="24" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_8"/>
|
||||||
|
</item>
|
||||||
|
<item row="25" column="0">
|
||||||
|
<widget class="QLabel" name="label_35">
|
||||||
|
<property name="text">
|
||||||
|
<string>Lod Count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="25" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_7">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="26" column="0">
|
||||||
|
<widget class="QLabel" name="label_36">
|
||||||
|
<property name="text">
|
||||||
|
<string>Coll Lod:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="26" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_8">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="27" column="0">
|
||||||
|
<widget class="QLabel" name="label_37">
|
||||||
|
<property name="text">
|
||||||
|
<string>Stream Info Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="27" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_9">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="28" column="0">
|
||||||
|
<widget class="QLabel" name="label_38">
|
||||||
|
<property name="text">
|
||||||
|
<string>Memory Usage:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="28" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_10">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="29" column="0">
|
||||||
|
<widget class="QLabel" name="label_39">
|
||||||
|
<property name="text">
|
||||||
|
<string>Flags:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="29" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_11">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="30" column="0">
|
||||||
|
<widget class="QLabel" name="label_40">
|
||||||
|
<property name="text">
|
||||||
|
<string>Phys Preset Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="30" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_12">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="31" column="0">
|
||||||
|
<widget class="QLabel" name="label_41">
|
||||||
|
<property name="text">
|
||||||
|
<string>Phys Geometry Pointer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="31" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_ClassPtr_13">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
|
<property name="title">
|
||||||
|
<string>Lod Info</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_14">
|
||||||
|
<property name="text">
|
||||||
|
<string>Lod Info Index:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="comboBox_LodIndex"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="Line" name="line_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_15">
|
||||||
|
<property name="text">
|
||||||
|
<string>Distance:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_16">
|
||||||
|
<property name="text">
|
||||||
|
<string>Surface Count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_BoneNamePtr_2">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_17">
|
||||||
|
<property name="text">
|
||||||
|
<string>Surface Index:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_BoneNamePtr_3">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_18">
|
||||||
|
<property name="text">
|
||||||
|
<string>Part Bit 1: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_BoneNamePtr_4">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_19">
|
||||||
|
<property name="text">
|
||||||
|
<string>Part Bit 2: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_BoneNamePtr_5">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_20">
|
||||||
|
<property name="text">
|
||||||
|
<string>Part Bit 3: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_BoneNamePtr_6">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_21">
|
||||||
|
<property name="text">
|
||||||
|
<string>Part Bit 4: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_BoneNamePtr_7">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QLabel" name="label_22">
|
||||||
|
<property name="text">
|
||||||
|
<string>Part Bit 5: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_BoneNamePtr_8">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_3DWindow">
|
||||||
|
<property name="title">
|
||||||
|
<string>3D Window</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
35
app/preferenceeditor.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "preferenceeditor.h"
|
||||||
|
#include "ui_preferenceeditor.h"
|
||||||
|
|
||||||
|
PreferenceEditor::PreferenceEditor(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, ui(new Ui::PreferenceEditor)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
ui->frame_View->show();
|
||||||
|
ui->frame_TreeWidget->hide();
|
||||||
|
ui->frame_FileEditors->hide();
|
||||||
|
|
||||||
|
connect(ui->listWidget_Categories, &QListWidget::itemSelectionChanged, this, [this]() {
|
||||||
|
const QString itemText = ui->listWidget_Categories->selectedItems().first()->text();
|
||||||
|
if (itemText == "View") {
|
||||||
|
ui->frame_View->show();
|
||||||
|
ui->frame_TreeWidget->hide();
|
||||||
|
ui->frame_FileEditors->hide();
|
||||||
|
} else if (itemText == "Tree Widget") {
|
||||||
|
ui->frame_View->hide();
|
||||||
|
ui->frame_TreeWidget->show();
|
||||||
|
ui->frame_FileEditors->hide();
|
||||||
|
} else if (itemText == "File Editors") {
|
||||||
|
ui->frame_View->hide();
|
||||||
|
ui->frame_TreeWidget->hide();
|
||||||
|
ui->frame_FileEditors->show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferenceEditor::~PreferenceEditor()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
22
app/preferenceeditor.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef PREFERENCEEDITOR_H
|
||||||
|
#define PREFERENCEEDITOR_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class PreferenceEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PreferenceEditor : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PreferenceEditor(QWidget *parent = nullptr);
|
||||||
|
~PreferenceEditor();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::PreferenceEditor *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PREFERENCEEDITOR_H
|
||||||
528
app/preferenceeditor.ui
Normal file
@ -0,0 +1,528 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>PreferenceEditor</class>
|
||||||
|
<widget class="QDialog" name="PreferenceEditor">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1118</width>
|
||||||
|
<height>861</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>703</width>
|
||||||
|
<height>512</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Filter</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listWidget_Categories">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="currentRow">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>View</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="data/Data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_Views.png</normaloff>:/icons/icons/Icon_Views.png</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Tree Widget</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="data/Data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_Tree.png</normaloff>:/icons/icons/Icon_Tree.png</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>File Editors</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="data/Data.qrc">
|
||||||
|
<normaloff>:/icons/icons/Icon_Editor.png</normaloff>:/icons/icons/Icon_Editor.png</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame_View">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Shape::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Shadow::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="data/Data.qrc">:/icons/icons/Icon_Views.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>View</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabWidget_Editors_3">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab_3">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Font && Colors</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Font</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Family:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBox_FontFamily"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Size:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBox_FontSize"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Zoom:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBox_ViewZoom">
|
||||||
|
<property name="suffix">
|
||||||
|
<string>%</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>588</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame_TreeWidget">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Shape::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Shadow::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="data/Data.qrc">:/icons/icons/Icon_Tree.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Tree Widget</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabWidget_Editors">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Tab 1</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_2">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Tab 2</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame_FileEditors">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Shape::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Shadow::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="data/Data.qrc">:/icons/icons/Icon_Editor.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>File Editors</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabWidget_Editors_2">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab_FastFile">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Fast File</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_Zone">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Zone File</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_IWIFile">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Images</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_LocalString">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Local Strings</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab__StringTable">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>String Table</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_Sounds">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Sounds</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_TechSet">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Tech Set</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_Model">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Model</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_6">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Page</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="data/Data.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>PreferenceEditor</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>PreferenceEditor</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
80
app/soundviewer.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#include "soundviewer.h"
|
||||||
|
#include "ui_soundviewer.h"
|
||||||
|
|
||||||
|
SoundViewer::SoundViewer(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, ui(new Ui::SoundViewer)
|
||||||
|
, player(new QMediaPlayer())
|
||||||
|
, buffer(new QBuffer())
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
connect(ui->pushButton_Play, &QPushButton::clicked, player, &QMediaPlayer::play);
|
||||||
|
connect(ui->pushButton_Pause, &QPushButton::clicked, player, &QMediaPlayer::pause);
|
||||||
|
connect(ui->pushButton_Stop, &QPushButton::clicked, this, [this]() {
|
||||||
|
if (player->isPlaying()) {
|
||||||
|
player->stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(ui->pushButton_SkipForward, &QPushButton::clicked, this, [this]() {
|
||||||
|
player->setPosition(player->position() + 30);
|
||||||
|
});
|
||||||
|
connect(ui->pushButton_SkipBack, &QPushButton::clicked, this, [this]() {
|
||||||
|
player->setPosition(player->position() - 30);
|
||||||
|
});
|
||||||
|
connect(player, &QMediaPlayer::positionChanged, player, [this](qint64 position) {
|
||||||
|
ui->horizontalSlider->setSliderPosition(position);
|
||||||
|
ui->label_Time->setText(QString("%1:%2:%3")
|
||||||
|
.arg(position / 60000)
|
||||||
|
.arg((position % 60000) / 1000)
|
||||||
|
.arg(position % 1000));
|
||||||
|
});
|
||||||
|
connect(player, &QMediaPlayer::durationChanged, player, [this](qint64 duration) {
|
||||||
|
ui->horizontalSlider->setMaximum(duration);
|
||||||
|
ui->label_TimeMax->setText(QString("%1:%2:%3")
|
||||||
|
.arg(duration / 60000)
|
||||||
|
.arg((duration % 60000) / 1000)
|
||||||
|
.arg(duration % 1000));
|
||||||
|
});
|
||||||
|
connect(ui->horizontalSlider, &QSlider::sliderMoved, this, [this](int position) {
|
||||||
|
player->setPosition(position);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (auto outputDevice : QMediaDevices::audioOutputs()) {
|
||||||
|
ui->comboBox_Output->addItem(outputDevice.description());
|
||||||
|
}
|
||||||
|
connect(ui->comboBox_Output, &QComboBox::currentIndexChanged, this, [this](int index) {
|
||||||
|
auto outputDevice = QMediaDevices::audioOutputs()[index];
|
||||||
|
QAudioOutput *audioOutput = new QAudioOutput(outputDevice);
|
||||||
|
player->setAudioOutput(audioOutput);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto outputDevice = QMediaDevices::defaultAudioOutput();
|
||||||
|
QAudioOutput *audioOutput = new QAudioOutput(outputDevice);
|
||||||
|
player->setAudioOutput(audioOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundViewer::~SoundViewer()
|
||||||
|
{
|
||||||
|
delete buffer;
|
||||||
|
delete player;
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundViewer::SetSound(std::shared_ptr<Sound> aSound)
|
||||||
|
{
|
||||||
|
buffer->setData(aSound->data);
|
||||||
|
if (!buffer->open(QIODevice::ReadOnly)) {
|
||||||
|
qWarning() << "Failed to open QBuffer.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->groupBox->setTitle(aSound->path);
|
||||||
|
player->setSourceDevice(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundViewer::SetOutput(QAudioOutput *aOutput) {
|
||||||
|
if (!aOutput) { return; }
|
||||||
|
|
||||||
|
player->setAudioOutput(aOutput);
|
||||||
|
}
|
||||||
34
app/soundviewer.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef SOUNDVIEWER_H
|
||||||
|
#define SOUNDVIEWER_H
|
||||||
|
|
||||||
|
#include "asset_structs.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QMediaPlayer>
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QAudioDevice>
|
||||||
|
#include <QMediaDevices>
|
||||||
|
#include <QAudioOutput>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class SoundViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SoundViewer : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SoundViewer(QWidget *parent = nullptr);
|
||||||
|
~SoundViewer();
|
||||||
|
|
||||||
|
void SetSound(std::shared_ptr<Sound> aSound);
|
||||||
|
|
||||||
|
void SetOutput(QAudioOutput *aOutput);
|
||||||
|
private:
|
||||||
|
Ui::SoundViewer *ui;
|
||||||
|
QMediaPlayer *player;
|
||||||
|
QBuffer *buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SOUNDVIEWER_H
|
||||||
2573
app/soundviewer.ui
Normal file
36
app/stringtableviewer.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "stringtableviewer.h"
|
||||||
|
#include "ui_stringtableviewer.h"
|
||||||
|
|
||||||
|
StringTableViewer::StringTableViewer(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, ui(new Ui::StringTableViewer)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTableViewer::~StringTableViewer()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTableViewer::SetStringTable(std::shared_ptr<StringTable> aStringTable) {
|
||||||
|
ui->tableWidget_Strings->clear();
|
||||||
|
|
||||||
|
ui->tableWidget_Strings->setRowCount(aStringTable->rowCount);
|
||||||
|
ui->tableWidget_Strings->setColumnCount(aStringTable->columnCount);
|
||||||
|
|
||||||
|
int currentIndex = 0;
|
||||||
|
for (const QString &key : aStringTable->content.keys()) {
|
||||||
|
const QString value = aStringTable->content[key];
|
||||||
|
|
||||||
|
QTableWidgetItem *tableKeyItem = new QTableWidgetItem();
|
||||||
|
tableKeyItem->setText(key);
|
||||||
|
ui->tableWidget_Strings->setItem(currentIndex, 0, tableKeyItem);
|
||||||
|
|
||||||
|
QTableWidgetItem *tableValItem = new QTableWidgetItem();
|
||||||
|
tableValItem->setText(value);
|
||||||
|
ui->tableWidget_Strings->setItem(currentIndex, 1, tableValItem);
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
app/stringtableviewer.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef STRINGTABLEVIEWER_H
|
||||||
|
#define STRINGTABLEVIEWER_H
|
||||||
|
|
||||||
|
#include "asset_structs.h"
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class StringTableViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringTableViewer : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit StringTableViewer(QWidget *parent = nullptr);
|
||||||
|
~StringTableViewer();
|
||||||
|
|
||||||
|
void SetStringTable(std::shared_ptr<StringTable> aStringTable);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::StringTableViewer *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // STRINGTABLEVIEWER_H
|
||||||
24
app/stringtableviewer.ui
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>StringTableViewer</class>
|
||||||
|
<widget class="QWidget" name="StringTableViewer">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>525</width>
|
||||||
|
<height>752</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QTableWidget" name="tableWidget_Strings"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
800
app/xtreewidget.cpp
Normal file
@ -0,0 +1,800 @@
|
|||||||
|
#include "xtreewidget.h"
|
||||||
|
#include "qheaderview.h"
|
||||||
|
#include "qmenu.h"
|
||||||
|
#include "logmanager.h"
|
||||||
|
|
||||||
|
XTreeWidget::XTreeWidget(QWidget *parent)
|
||||||
|
: QTreeWidget(parent) {
|
||||||
|
mFastFiles = QMap<QString, std::shared_ptr<FastFile>>();
|
||||||
|
mZoneFiles = QMap<QString, std::shared_ptr<ZoneFile>>();
|
||||||
|
mDDSFiles = QMap<QString, std::shared_ptr<DDSFile>>();
|
||||||
|
mIWIFiles = QMap<QString, std::shared_ptr<IWIFile>>();
|
||||||
|
|
||||||
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
setSelectionMode(QTreeWidget::SingleSelection);
|
||||||
|
setColumnCount(3);
|
||||||
|
header()->hide();
|
||||||
|
setMinimumWidth(350);
|
||||||
|
setSortingEnabled(true);
|
||||||
|
|
||||||
|
header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
||||||
|
|
||||||
|
// Set the last two columns to a fixed width
|
||||||
|
//header()->setSectionResizeMode(1, QHeaderView::Fixed);
|
||||||
|
//header()->setSectionResizeMode(2, QHeaderView::Fixed);
|
||||||
|
|
||||||
|
// Adjust the fixed widths to suit your icon size (e.g., 32 pixels)
|
||||||
|
//header()->resizeSection(0, 275);
|
||||||
|
//header()->resizeSection(1, 32);
|
||||||
|
//header()->resizeSection(2, 32);
|
||||||
|
|
||||||
|
connect(this, &XTreeWidget::itemSelectionChanged, this, &XTreeWidget::ItemSelectionChanged);
|
||||||
|
connect(this, &XTreeWidget::customContextMenuRequested, this, &XTreeWidget::PrepareContextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
XTreeWidget::~XTreeWidget() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void XTreeWidget::AddFastFile(std::shared_ptr<FastFile> aFastFile) {
|
||||||
|
XTreeWidgetItem *fastFileItem = new XTreeWidgetItem(this);
|
||||||
|
fastFileItem->setText(0, aFastFile->GetStem() + ".ff");
|
||||||
|
fastFileItem->setIcon(0, QIcon(":/icons/icons/Icon_FastFile.png"));
|
||||||
|
if (aFastFile->GetPlatform() == "PC") {
|
||||||
|
fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_PC.png"));
|
||||||
|
} else if (aFastFile->GetPlatform() == "360") {
|
||||||
|
fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_Xbox.png"));
|
||||||
|
} else if (aFastFile->GetPlatform() == "Wii") {
|
||||||
|
fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_Wii.png"));
|
||||||
|
} else if (aFastFile->GetPlatform() == "WiiU") {
|
||||||
|
fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_WiiU.png"));
|
||||||
|
}
|
||||||
|
if (aFastFile->GetGame() == "COD2") {
|
||||||
|
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD2.png"));
|
||||||
|
} if (aFastFile->GetGame() == "COD4") {
|
||||||
|
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD4.png"));
|
||||||
|
} else if (aFastFile->GetGame() == "COD5") {
|
||||||
|
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD5.png"));
|
||||||
|
} else if (aFastFile->GetGame() == "COD6") {
|
||||||
|
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD6.png"));
|
||||||
|
} else if (aFastFile->GetGame() == "COD7") {
|
||||||
|
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD7.png"));
|
||||||
|
} else if (aFastFile->GetGame() == "COD8") {
|
||||||
|
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD8.png"));
|
||||||
|
} else if (aFastFile->GetGame() == "COD9") {
|
||||||
|
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD9.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
AddZoneFile(aFastFile->GetZoneFile(), fastFileItem);
|
||||||
|
|
||||||
|
mFastFiles[aFastFile->GetStem().section(".", 0, 0)] = aFastFile;
|
||||||
|
|
||||||
|
resizeColumnToContents(1);
|
||||||
|
setSortingEnabled(true);
|
||||||
|
sortByColumn(0, Qt::AscendingOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XTreeWidget::AddZoneFile(std::shared_ptr<ZoneFile> aZoneFile, XTreeWidgetItem *aParentItem) {
|
||||||
|
XTreeWidgetItem *zoneItem;
|
||||||
|
if (aParentItem != nullptr) {
|
||||||
|
zoneItem = new XTreeWidgetItem(aParentItem);
|
||||||
|
} else {
|
||||||
|
zoneItem = new XTreeWidgetItem(this);
|
||||||
|
}
|
||||||
|
zoneItem->setIcon(0, QIcon(":/icons/icons/Icon_ZoneFile.png"));
|
||||||
|
zoneItem->setText(0, aZoneFile->GetStem() + ".zone");
|
||||||
|
|
||||||
|
auto assetMap = aZoneFile->GetAssetMap();
|
||||||
|
|
||||||
|
if (!assetMap.localStrings.isEmpty()) {
|
||||||
|
XTreeWidgetItem *localStrRoot = new XTreeWidgetItem(zoneItem);
|
||||||
|
localStrRoot->setText(0, "String Files");
|
||||||
|
localStrRoot->setIcon(0, QIcon(":/icons/icons/Icon_StringFile.png"));
|
||||||
|
|
||||||
|
XTreeWidgetItem *localStrItem = new XTreeWidgetItem(localStrRoot);
|
||||||
|
localStrItem->setText(0, aZoneFile->GetStem().section('.', 0, 0) + ".str");
|
||||||
|
localStrItem->setIcon(0, QIcon(":/icons/icons/Icon_StringFile.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assetMap.techSets.isEmpty()) {
|
||||||
|
XTreeWidgetItem *techSetRoot = new XTreeWidgetItem(zoneItem);
|
||||||
|
techSetRoot->setText(0, "Tech Sets");
|
||||||
|
techSetRoot->setIcon(0, QIcon(":/icons/icons/Icon_TechSetFile.png"));
|
||||||
|
|
||||||
|
for (TechSet techSet : assetMap.techSets) {
|
||||||
|
XTreeWidgetItem *techSetItem = new XTreeWidgetItem(techSetRoot);
|
||||||
|
techSetItem->setText(0, techSet.name);
|
||||||
|
techSetItem->setIcon(0, QIcon(":/icons/icons/Icon_TechSetFile.png"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assetMap.rawFiles.isEmpty()) {
|
||||||
|
XTreeWidgetItem *rawFileRoot = new XTreeWidgetItem(zoneItem);
|
||||||
|
rawFileRoot->setText(0, "Raw Files");
|
||||||
|
rawFileRoot->setIcon(0, QIcon(":/icons/icons/Icon_GSCFile.png"));
|
||||||
|
for (RawFile rawFile : assetMap.rawFiles) {
|
||||||
|
if (!rawFile.length) { continue; }
|
||||||
|
|
||||||
|
XTreeWidgetItem *tempItem = rawFileRoot;
|
||||||
|
for (const QString &pathPart : rawFile.path.split('/')) {
|
||||||
|
bool childFound = false;
|
||||||
|
for (int i = 0; i < tempItem->childCount(); i++) {
|
||||||
|
QTreeWidgetItem *rawChildItem = tempItem->child(i);
|
||||||
|
XTreeWidgetItem *childItem = dynamic_cast<XTreeWidgetItem*>(rawChildItem);
|
||||||
|
if (childItem->text(0) == pathPart) {
|
||||||
|
tempItem = childItem;
|
||||||
|
|
||||||
|
childFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathPart.contains(".gsc")) {
|
||||||
|
XTreeWidgetItem *rawFileItem = new XTreeWidgetItem(tempItem);
|
||||||
|
rawFileItem->setText(0, pathPart);
|
||||||
|
|
||||||
|
tempItem = rawFileItem;
|
||||||
|
} else if (!childFound) {
|
||||||
|
tempItem = new XTreeWidgetItem(tempItem);
|
||||||
|
tempItem->setText(0, pathPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
tempItem->setIcon(0, QIcon(":/icons/icons/Icon_GSCFile.png"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assetMap.menuFiles.isEmpty()) {
|
||||||
|
XTreeWidgetItem *menuRoot = new XTreeWidgetItem(zoneItem);
|
||||||
|
menuRoot->setText(0, "Menu Files");
|
||||||
|
menuRoot->setIcon(0, QIcon(":/icons/icons/Icon_MenuFile.png"));
|
||||||
|
|
||||||
|
int menuIndex = 1;
|
||||||
|
for (MenuFile menuFile : assetMap.menuFiles) {
|
||||||
|
XTreeWidgetItem *menuFileRoot = new XTreeWidgetItem(menuRoot);
|
||||||
|
menuFileRoot->setText(0, QString("Menu %1").arg(menuIndex));
|
||||||
|
for (Menu menu : menuFile.menuDefs) {
|
||||||
|
XTreeWidgetItem *menuItem = new XTreeWidgetItem(menuFileRoot);
|
||||||
|
menuItem->setText(0, menu.name);
|
||||||
|
menuItem->setIcon(0, QIcon(":/icons/icons/Icon_MenuFile.png"));
|
||||||
|
}
|
||||||
|
menuIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assetMap.images.isEmpty()) {
|
||||||
|
XTreeWidgetItem *imageRoot = new XTreeWidgetItem(zoneItem);
|
||||||
|
imageRoot->setText(0, "Images");
|
||||||
|
imageRoot->setIcon(0, QIcon(":/icons/icons/Icon_Image.png"));
|
||||||
|
|
||||||
|
for (Image image : assetMap.images) {
|
||||||
|
XTreeWidgetItem *imageItem = new XTreeWidgetItem(imageRoot);
|
||||||
|
imageItem->setText(0, image.materialName);
|
||||||
|
imageItem->setIcon(0, QIcon(":/icons/icons/Icon_Image.png"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assetMap.models.isEmpty()) {
|
||||||
|
XTreeWidgetItem *modelsRoot = new XTreeWidgetItem(zoneItem);
|
||||||
|
modelsRoot->setText(0, "Models");
|
||||||
|
modelsRoot->setIcon(0, QIcon(":/icons/icons/Icon_Model.png"));
|
||||||
|
|
||||||
|
for (Model model: assetMap.models) {
|
||||||
|
XTreeWidgetItem *modelItem = new XTreeWidgetItem(modelsRoot);
|
||||||
|
modelItem->setText(0, model.modelName);
|
||||||
|
modelItem->setIcon(0, QIcon(":/icons/icons/Icon_Model.png"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assetMap.materials.isEmpty()) {
|
||||||
|
XTreeWidgetItem *materialsRoot = new XTreeWidgetItem(zoneItem);
|
||||||
|
materialsRoot->setText(0, "Materials");
|
||||||
|
materialsRoot->setIcon(0, QIcon(":/icons/icons/Icon_Material.png"));
|
||||||
|
|
||||||
|
for (Material material: assetMap.materials) {
|
||||||
|
XTreeWidgetItem *materialItem = new XTreeWidgetItem(materialsRoot);
|
||||||
|
materialItem->setText(0, material.name);
|
||||||
|
materialItem->setIcon(0, QIcon(":/icons/icons/Icon_Material.png"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assetMap.stringTables.isEmpty()) {
|
||||||
|
XTreeWidgetItem *strTableRoot = new XTreeWidgetItem(zoneItem);
|
||||||
|
strTableRoot->setText(0, "String Tables");
|
||||||
|
strTableRoot->setIcon(0, QIcon(":/icons/icons/Icon_StringTable.png"));
|
||||||
|
|
||||||
|
for (StringTable strTable: assetMap.stringTables) {
|
||||||
|
XTreeWidgetItem *modelItem = new XTreeWidgetItem(strTableRoot);
|
||||||
|
modelItem->setText(0, strTable.name);
|
||||||
|
modelItem->setIcon(0, QIcon(":/icons/icons/Icon_StringTable.png"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assetMap.sounds.isEmpty()) {
|
||||||
|
XTreeWidgetItem *soundsRoot = new XTreeWidgetItem(zoneItem);
|
||||||
|
soundsRoot->setText(0, "Sounds");
|
||||||
|
soundsRoot->setIcon(0, QIcon(":/icons/icons/Icon_Sound.png"));
|
||||||
|
for (SoundAsset soundAsset : assetMap.sounds) {
|
||||||
|
for (Sound sound : soundAsset.sounds) {
|
||||||
|
XTreeWidgetItem *tempItem = soundsRoot;
|
||||||
|
|
||||||
|
if (!sound.dataLength) { continue; }
|
||||||
|
|
||||||
|
for (const QString &pathPart : sound.path.split('/')) {
|
||||||
|
if (pathPart.isEmpty()) { continue; }
|
||||||
|
|
||||||
|
bool childFound = false;
|
||||||
|
for (int i = 0; i < tempItem->childCount(); i++) {
|
||||||
|
XTreeWidgetItem *childItem = dynamic_cast<XTreeWidgetItem*>(tempItem->child(i));
|
||||||
|
if (childItem->text(0) == pathPart) {
|
||||||
|
tempItem = childItem;
|
||||||
|
|
||||||
|
childFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathPart.contains(".wav")) {
|
||||||
|
XTreeWidgetItem *soundItem = new XTreeWidgetItem(tempItem);
|
||||||
|
soundItem->setText(0, pathPart);
|
||||||
|
|
||||||
|
tempItem = soundItem;
|
||||||
|
} else if (!childFound) {
|
||||||
|
tempItem = new XTreeWidgetItem(tempItem);
|
||||||
|
tempItem->setText(0, pathPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
tempItem->setIcon(0, QIcon(":/icons/icons/Icon_Sound.png"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mZoneFiles[aZoneFile->GetStem().section(".", 0, 0)] = aZoneFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XTreeWidget::CloseFastFile(const QString aFFName) {
|
||||||
|
const QString fileStem = aFFName.section(".", 0, 0);
|
||||||
|
emit ItemClosed(fileStem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XTreeWidget::PrepareContextMenu(const QPoint &pos) {
|
||||||
|
auto activeItem = itemAt(pos);
|
||||||
|
if (!activeItem) { return; }
|
||||||
|
if (activeItem->text(0).isEmpty()) { return; }
|
||||||
|
|
||||||
|
QString activeText = activeItem->text(0);
|
||||||
|
QMenu *contextMenu = new QMenu(this);
|
||||||
|
|
||||||
|
if (activeText.contains(".dds")) {
|
||||||
|
const QString fileStem = activeText.replace(".dds", "");
|
||||||
|
if (!mDDSFiles.contains(fileStem)) {
|
||||||
|
qDebug() << "Error: Could not find " << fileStem << " in DDS map!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAction *closeAction = new QAction("Close File");
|
||||||
|
contextMenu->addAction(closeAction);
|
||||||
|
connect(closeAction, &QAction::triggered, this, [this, &fileStem, &activeItem](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
mDDSFiles.remove(fileStem);
|
||||||
|
invisibleRootItem()->removeChild(activeItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
QMenu *exportSubmenu = new QMenu("Export...", this);
|
||||||
|
contextMenu->addMenu(exportSubmenu);
|
||||||
|
|
||||||
|
std::shared_ptr<DDSFile> ddsFile = mDDSFiles[fileStem];
|
||||||
|
|
||||||
|
QAction *exportIWIAction = new QAction("Export as IWI");
|
||||||
|
exportSubmenu->addAction(exportIWIAction);
|
||||||
|
connect(exportIWIAction, &QAction::triggered, this, [ddsFile](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
ddsFile->SaveIWI();
|
||||||
|
});
|
||||||
|
|
||||||
|
QAction *exportPNGAction = new QAction("Export as PNG");
|
||||||
|
exportSubmenu->addAction(exportPNGAction);
|
||||||
|
connect(exportPNGAction, &QAction::triggered, this, [ddsFile](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
ddsFile->SavePNG();
|
||||||
|
});
|
||||||
|
|
||||||
|
QAction *exportJPGAction = new QAction("Export as JPG");
|
||||||
|
exportSubmenu->addAction(exportJPGAction);
|
||||||
|
connect(exportJPGAction, &QAction::triggered, this, [ddsFile](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
ddsFile->SaveJPG();
|
||||||
|
});
|
||||||
|
} else if (activeText.contains(".iwi")) {
|
||||||
|
const QString fileStem = activeText.replace(".iwi", "");
|
||||||
|
if (!mIWIFiles.contains(fileStem)) {
|
||||||
|
qDebug() << "Error: Could not find " << fileStem << " in IWI map!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAction *closeAction = new QAction("Close File");
|
||||||
|
contextMenu->addAction(closeAction);
|
||||||
|
connect(closeAction, &QAction::triggered, this, [this, &fileStem, &activeItem](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
mIWIFiles.remove(fileStem);
|
||||||
|
invisibleRootItem()->removeChild(activeItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
QMenu *exportSubmenu = new QMenu("Export...", this);
|
||||||
|
contextMenu->addMenu(exportSubmenu);
|
||||||
|
|
||||||
|
std::shared_ptr<IWIFile> iwiFile = mIWIFiles[fileStem];
|
||||||
|
|
||||||
|
QAction *exportDDSAction = new QAction("Export as DDS");
|
||||||
|
exportSubmenu->addAction(exportDDSAction);
|
||||||
|
connect(exportDDSAction, &QAction::triggered, this, [iwiFile](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
iwiFile->SaveDDS();
|
||||||
|
});
|
||||||
|
|
||||||
|
QAction *exportPNGAction = new QAction("Export as PNG");
|
||||||
|
exportSubmenu->addAction(exportPNGAction);
|
||||||
|
connect(exportPNGAction, &QAction::triggered, this, [iwiFile](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
iwiFile->SavePNG();
|
||||||
|
});
|
||||||
|
|
||||||
|
QAction *exportJPGAction = new QAction("Export as JPG");
|
||||||
|
exportSubmenu->addAction(exportJPGAction);
|
||||||
|
connect(exportJPGAction, &QAction::triggered, this, [iwiFile](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
iwiFile->SaveJPG();
|
||||||
|
});
|
||||||
|
} else if (activeText.contains(".ff")) {
|
||||||
|
const QString fileStem = activeText.replace(".zone", "");
|
||||||
|
|
||||||
|
QMenu *closeMultipleAction = new QMenu("Close Multiple Tabs");
|
||||||
|
|
||||||
|
QAction *closeAllAction = new QAction("Close All");
|
||||||
|
closeMultipleAction->addAction(closeAllAction);
|
||||||
|
connect(closeAllAction, &QAction::triggered, this, [this](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
mFastFiles.clear();
|
||||||
|
clear();
|
||||||
|
|
||||||
|
emit Cleared();
|
||||||
|
});
|
||||||
|
|
||||||
|
QAction *closeAllButAction = new QAction("Close All BUT This");
|
||||||
|
closeMultipleAction->addAction(closeAllButAction);
|
||||||
|
connect(closeAllButAction, &QAction::triggered, this, [this, &activeItem](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
for (int i = 0; i < invisibleRootItem()->childCount(); i++) {
|
||||||
|
auto childItem = invisibleRootItem()->child(i);
|
||||||
|
if (childItem == activeItem) { continue; }
|
||||||
|
|
||||||
|
const QString fileStem = childItem->text(0).replace(".ff", "");
|
||||||
|
if (!mFastFiles.contains(fileStem)) {
|
||||||
|
qDebug() << "Error: Could not find " << fileStem << " in Fast File map!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFastFiles.remove(fileStem);
|
||||||
|
CloseFastFile(fileStem);
|
||||||
|
invisibleRootItem()->removeChild(childItem);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QAction *closeAboveAction = new QAction("Close All Above");
|
||||||
|
closeMultipleAction->addAction(closeAboveAction);
|
||||||
|
connect(closeAboveAction, &QAction::triggered, this, [this, &activeItem](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
for (int i = 0; i < invisibleRootItem()->childCount(); i++) {
|
||||||
|
auto childItem = invisibleRootItem()->child(i);
|
||||||
|
if (childItem == activeItem) { return; }
|
||||||
|
|
||||||
|
const QString fileStem = childItem->text(0).replace(".ff", "");
|
||||||
|
if (!mFastFiles.contains(fileStem)) {
|
||||||
|
qDebug() << "Error: Could not find " << fileStem << " in Fast File map!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFastFiles.remove(fileStem);
|
||||||
|
CloseFastFile(fileStem);
|
||||||
|
invisibleRootItem()->removeChild(childItem);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QAction *closeBelowAction = new QAction("Close All Below");
|
||||||
|
closeMultipleAction->addAction(closeBelowAction);
|
||||||
|
connect(closeBelowAction, &QAction::triggered, this, [this, &activeItem](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
bool ready = false;
|
||||||
|
for (int i = 0; i < invisibleRootItem()->childCount(); i++) {
|
||||||
|
auto childItem = invisibleRootItem()->child(i);
|
||||||
|
if (!ready && (childItem != activeItem)) { continue; }
|
||||||
|
if (childItem == activeItem) {
|
||||||
|
ready = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString fileStem = childItem->text(0).replace(".ff", "");
|
||||||
|
if (!mFastFiles.contains(fileStem)) {
|
||||||
|
qDebug() << "Error: Could not find " << fileStem << " in Fast File map!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFastFiles.remove(fileStem);
|
||||||
|
CloseFastFile(fileStem);
|
||||||
|
invisibleRootItem()->removeChild(childItem);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
contextMenu->addMenu(closeMultipleAction);
|
||||||
|
|
||||||
|
QAction *closeAction = new QAction("Close File");
|
||||||
|
contextMenu->addAction(closeAction);
|
||||||
|
connect(closeAction, &QAction::triggered, this, [this, &activeItem, &activeText](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
const QString fileStem = activeItem->text(0).replace(".ff", "");
|
||||||
|
|
||||||
|
mFastFiles.remove(fileStem);
|
||||||
|
CloseFastFile(activeText);
|
||||||
|
invisibleRootItem()->removeChild(activeItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
QMenu *exportSubmenu = new QMenu("Export...", this);
|
||||||
|
contextMenu->addMenu(exportSubmenu);
|
||||||
|
|
||||||
|
std::shared_ptr<FastFile> fastFile = mFastFiles[fileStem];
|
||||||
|
|
||||||
|
QAction *exportFastFileAction = new QAction("Export Fast File");
|
||||||
|
exportSubmenu->addAction(exportFastFileAction);
|
||||||
|
connect(exportFastFileAction, &QAction::triggered, this, [fastFile](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
const QString fastFilePath = QFileDialog::getSaveFileName(
|
||||||
|
nullptr, "Export Fast File...", QDir::currentPath(),
|
||||||
|
"Fast File (*.ff);;All Files(*.*)");
|
||||||
|
|
||||||
|
fastFile->ExportFastFile(fastFilePath);
|
||||||
|
});
|
||||||
|
QAction *exportZoneFileAction = new QAction("Export Zone File");
|
||||||
|
exportSubmenu->addAction(exportZoneFileAction);
|
||||||
|
connect(exportZoneFileAction, &QAction::triggered, this, [fastFile](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
const QString zoneFilePath = QFileDialog::getSaveFileName(
|
||||||
|
nullptr, "Export Zone File...", QDir::currentPath(),
|
||||||
|
"Zone File (*.zone);;All Files(*.*)");
|
||||||
|
fastFile->GetZoneFile()->SaveZoneFile(zoneFilePath);
|
||||||
|
});
|
||||||
|
} else if (activeText.contains(".zone")) {
|
||||||
|
const QString fileStem = activeText.replace(".zone", "");
|
||||||
|
if (!mZoneFiles.contains(fileStem)) {
|
||||||
|
qDebug() << "Error: Could not find " << fileStem << " in Zone File map!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu *exportSubmenu = new QMenu("Export...", this);
|
||||||
|
contextMenu->addMenu(exportSubmenu);
|
||||||
|
|
||||||
|
std::shared_ptr<ZoneFile> zoneFile = mZoneFiles[fileStem];
|
||||||
|
|
||||||
|
QAction *exportZoneFileAction = new QAction("Export Zone File");
|
||||||
|
exportSubmenu->addAction(exportZoneFileAction);
|
||||||
|
connect(exportZoneFileAction, &QAction::triggered, this, [](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
});
|
||||||
|
QAction *exportFastFileAction = new QAction("Export Fast File");
|
||||||
|
exportSubmenu->addAction(exportFastFileAction);
|
||||||
|
connect(exportFastFileAction, &QAction::triggered, this, [](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
});
|
||||||
|
} else if (activeItem && activeText.contains(".wav")) {
|
||||||
|
XTreeWidgetItem *parentItem = dynamic_cast<XTreeWidgetItem*>(activeItem->parent());
|
||||||
|
while (parentItem && !parentItem->text(0).contains(".zone")) {
|
||||||
|
parentItem = dynamic_cast<XTreeWidgetItem*>(parentItem->parent());
|
||||||
|
|
||||||
|
if (parentItem == invisibleRootItem()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parentItem && parentItem != invisibleRootItem() && parentItem->text(0).contains(".zone")) {
|
||||||
|
const QString fileStem = parentItem->text(0).section('.', 0, 0);
|
||||||
|
QVector<SoundAsset> soundAssets = mZoneFiles[fileStem]->GetAssetMap().sounds;
|
||||||
|
for (SoundAsset soundAsset : soundAssets) {
|
||||||
|
for (Sound sound : soundAsset.sounds) {
|
||||||
|
if (sound.path.contains(activeText)) {
|
||||||
|
QMenu *exportSubmenu = new QMenu("Export...", this);
|
||||||
|
contextMenu->addMenu(exportSubmenu);
|
||||||
|
|
||||||
|
QAction *exportWAVAction = new QAction("Export as WAV File");
|
||||||
|
exportSubmenu->addAction(exportWAVAction);
|
||||||
|
connect(exportWAVAction, &QAction::triggered, this, [sound](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
QDir dir = QDir::currentPath();
|
||||||
|
if (!dir.exists("exports/")) {
|
||||||
|
dir.mkdir("exports/");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dir.exists("exports/sounds/")) {
|
||||||
|
dir.mkdir("exports/sounds/");
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString fileName = "exports/sounds/" + sound.path.split('/').last();
|
||||||
|
QFile wavFile(fileName);
|
||||||
|
if (!wavFile.open(QIODevice::WriteOnly)) {
|
||||||
|
qDebug() << "Failed to write wav file!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wavFile.write(sound.data);
|
||||||
|
wavFile.close();
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (activeItem && activeText == "Sounds") {
|
||||||
|
XTreeWidgetItem *parentItem = dynamic_cast<XTreeWidgetItem*>(activeItem->parent());
|
||||||
|
while (parentItem && !parentItem->text(0).contains(".zone")) {
|
||||||
|
parentItem = dynamic_cast<XTreeWidgetItem*>(parentItem->parent());
|
||||||
|
|
||||||
|
if (parentItem == invisibleRootItem()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parentItem && parentItem != invisibleRootItem() && parentItem->text(0).contains(".zone")) {
|
||||||
|
const QString fileStem = parentItem->text(0).section('.', 0, 0);
|
||||||
|
auto zoneFile = mZoneFiles[fileStem];
|
||||||
|
|
||||||
|
QMenu *exportSubmenu = new QMenu("Export...", this);
|
||||||
|
contextMenu->addMenu(exportSubmenu);
|
||||||
|
|
||||||
|
QAction *exportAllWAVAction = new QAction("Export ALL as WAV Files");
|
||||||
|
exportSubmenu->addAction(exportAllWAVAction);
|
||||||
|
connect(exportAllWAVAction, &QAction::triggered, this, [zoneFile](bool checked) {
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
|
||||||
|
for (SoundAsset soundAsset : zoneFile->GetAssetMap().sounds) {
|
||||||
|
for (Sound sound : soundAsset.sounds) {
|
||||||
|
if (!sound.dataLength) { continue; }
|
||||||
|
|
||||||
|
QDir dir = QDir::currentPath();
|
||||||
|
if (!dir.exists("exports/")) {
|
||||||
|
dir.mkdir("exports/");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dir.exists("exports/sounds/")) {
|
||||||
|
dir.mkdir("exports/sounds/");
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString fileName = "exports/sounds/" + sound.path.split('/').last();
|
||||||
|
QFile wavFile(fileName);
|
||||||
|
if (!wavFile.open(QIODevice::WriteOnly)) {
|
||||||
|
qDebug() << "Failed to write wav file!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wavFile.write(sound.data);
|
||||||
|
wavFile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint pt(pos);
|
||||||
|
contextMenu->exec(mapToGlobal(pt));
|
||||||
|
|
||||||
|
delete contextMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XTreeWidget::ItemSelectionChanged() {
|
||||||
|
if (selectedItems().isEmpty()) { return; }
|
||||||
|
|
||||||
|
XTreeWidgetItem *selectedItem = dynamic_cast<XTreeWidgetItem*>(selectedItems().first());
|
||||||
|
if (!selectedItem) { return; }
|
||||||
|
if (selectedItem->text(0).isEmpty()) { return; }
|
||||||
|
QString selectedText = selectedItem->text(0);
|
||||||
|
emit ItemSelected(selectedText);
|
||||||
|
|
||||||
|
const QString fileStem = selectedText.section(".", 0, 0);
|
||||||
|
|
||||||
|
XTreeWidgetItem *parentItem = dynamic_cast<XTreeWidgetItem*>(selectedItem->parent());
|
||||||
|
|
||||||
|
if (selectedText.contains(".dds")) {
|
||||||
|
if (!mDDSFiles.contains(fileStem)) {
|
||||||
|
LogManager::instance().addError("Could not find " + fileStem + " in DDS map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::shared_ptr<DDSFile> ddsFile = mDDSFiles[fileStem];
|
||||||
|
emit DDSFileSelected(ddsFile, fileStem);
|
||||||
|
} else if (selectedText.contains(".iwi")) {
|
||||||
|
if (!mIWIFiles.contains(fileStem)) {
|
||||||
|
LogManager::instance().addError("Could not find " + fileStem + " in IWI map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit IWIFileSelected(mIWIFiles[fileStem], fileStem);
|
||||||
|
} else if (selectedText.contains(".ff")) {
|
||||||
|
if (!mFastFiles.contains(fileStem)) {
|
||||||
|
LogManager::instance().addError("Could not find " + fileStem + " in Fast File map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit FastFileSelected(mFastFiles[fileStem], fileStem);
|
||||||
|
} else if (selectedText.contains(".zone")) {
|
||||||
|
if (!mZoneFiles.contains(fileStem)) {
|
||||||
|
LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit ZoneFileSelected(mZoneFiles[fileStem], fileStem);
|
||||||
|
} else if (selectedText.contains(".str")) {
|
||||||
|
if (!mZoneFiles.contains(fileStem)) {
|
||||||
|
LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit LocalStringSelected(mZoneFiles[fileStem], fileStem);
|
||||||
|
} else if (selectedText.contains(".gsc")) {
|
||||||
|
XTreeWidgetItem *zoneRoot = selectedItem;
|
||||||
|
if (!zoneRoot) { return; }
|
||||||
|
|
||||||
|
while (!zoneRoot->text(0).contains(".zone")) {
|
||||||
|
zoneRoot = dynamic_cast<XTreeWidgetItem*>(zoneRoot->parent());
|
||||||
|
if (!zoneRoot) { return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString fileStem = zoneRoot->text(0).section('.', 0, 0);
|
||||||
|
if (!mZoneFiles.contains(fileStem)) {
|
||||||
|
LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<RawFile> rawFiles = mZoneFiles[fileStem]->GetAssetMap().rawFiles;
|
||||||
|
for (RawFile rawFile : rawFiles) {
|
||||||
|
if (rawFile.path.contains(selectedText)) {
|
||||||
|
emit RawFileSelected(std::make_shared<RawFile>(rawFile), fileStem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (parentItem && (parentItem->text(0) == "Images")) {
|
||||||
|
XTreeWidgetItem *grandpaItem = dynamic_cast<XTreeWidgetItem*>(parentItem->parent());
|
||||||
|
if (grandpaItem && grandpaItem->text(0).contains(".zone")) {
|
||||||
|
const QString fileStem = grandpaItem->text(0).section('.', 0, 0);
|
||||||
|
QVector<Image> images = mZoneFiles[fileStem]->GetAssetMap().images;
|
||||||
|
for (Image image : images) {
|
||||||
|
if (image.materialName == selectedText) {
|
||||||
|
emit ImageSelected(std::make_shared<Image>(image), fileStem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (parentItem && (parentItem->text(0) == "Tech Sets")) {
|
||||||
|
XTreeWidgetItem *grandpaItem = dynamic_cast<XTreeWidgetItem*>(parentItem->parent());
|
||||||
|
if (grandpaItem && grandpaItem->text(0).contains(".zone")) {
|
||||||
|
const QString fileStem = grandpaItem->text(0).section('.', 0, 0);
|
||||||
|
auto techsets = mZoneFiles[fileStem]->GetAssetMap().techSets;
|
||||||
|
for (auto techset : techsets) {
|
||||||
|
if (techset.name == selectedText) {
|
||||||
|
emit TechSetSelected(std::make_shared<TechSet>(techset), fileStem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (parentItem && (parentItem->text(0) == "Tech Sets")) {
|
||||||
|
XTreeWidgetItem *grandpaItem = dynamic_cast<XTreeWidgetItem*>(parentItem->parent());
|
||||||
|
if (grandpaItem && grandpaItem->text(0).contains(".zone")) {
|
||||||
|
const QString fileStem = grandpaItem->text(0).section('.', 0, 0);
|
||||||
|
auto techsets = mZoneFiles[fileStem]->GetAssetMap().techSets;
|
||||||
|
for (auto techset : techsets) {
|
||||||
|
if (techset.name == selectedText) {
|
||||||
|
emit TechSetSelected(std::make_shared<TechSet>(techset), fileStem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (parentItem && (parentItem->text(0) == "Materials")) {
|
||||||
|
XTreeWidgetItem *grandpaItem = dynamic_cast<XTreeWidgetItem*>(parentItem->parent());
|
||||||
|
if (grandpaItem && grandpaItem->text(0).contains(".zone")) {
|
||||||
|
const QString fileStem = grandpaItem->text(0).section('.', 0, 0);
|
||||||
|
QVector<Material> materials = mZoneFiles[fileStem]->GetAssetMap().materials;
|
||||||
|
for (Material material : materials) {
|
||||||
|
if (material.name == selectedText) {
|
||||||
|
emit MaterialSelected(std::make_shared<Material>(material), fileStem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (parentItem && selectedText.contains(".wav")) {
|
||||||
|
XTreeWidgetItem *grandpaItem = dynamic_cast<XTreeWidgetItem*>(parentItem->parent());
|
||||||
|
while (grandpaItem && !grandpaItem->text(0).contains(".zone")) {
|
||||||
|
grandpaItem = dynamic_cast<XTreeWidgetItem*>(grandpaItem->parent());
|
||||||
|
|
||||||
|
if (grandpaItem == invisibleRootItem()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (grandpaItem && grandpaItem != invisibleRootItem() && grandpaItem->text(0).contains(".zone")) {
|
||||||
|
const QString fileStem = grandpaItem->text(0).section('.', 0, 0);
|
||||||
|
QVector<SoundAsset> soundAssets = mZoneFiles[fileStem]->GetAssetMap().sounds;
|
||||||
|
for (SoundAsset soundAsset : soundAssets) {
|
||||||
|
for (Sound sound : soundAsset.sounds) {
|
||||||
|
if (sound.path.contains(selectedText)) {
|
||||||
|
emit SoundSelected(std::make_shared<Sound>(sound), fileStem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ZoneFile> XTreeWidget::FindZoneFile(const QString aStem) {
|
||||||
|
foreach (auto zoneFile, mZoneFiles) {
|
||||||
|
if (zoneFile->GetStem() == aStem) {
|
||||||
|
return zoneFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<FastFile> XTreeWidget::FindFastFile(const QString aStem) {
|
||||||
|
foreach (auto fastFile, mFastFiles) {
|
||||||
|
if (fastFile->GetStem() == aStem) {
|
||||||
|
return fastFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XTreeWidget::HasZoneFile(const QString aStem) {
|
||||||
|
return FindZoneFile(aStem) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XTreeWidget::HasFastFile(const QString aStem) {
|
||||||
|
return FindFastFile(aStem) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XTreeWidget::AddIWIFile(std::shared_ptr<IWIFile> aIWIFile) {
|
||||||
|
const QString iwiFileName = QString(aIWIFile->fileStem + ".iwi");
|
||||||
|
|
||||||
|
for (int i = 0; i < invisibleRootItem()->childCount(); i++) {
|
||||||
|
auto iwiFileItem = invisibleRootItem()->child(i);
|
||||||
|
if (iwiFileItem->text(0) == iwiFileName) {
|
||||||
|
delete iwiFileItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XTreeWidgetItem *iwiItem = new XTreeWidgetItem(this);
|
||||||
|
iwiItem->setIcon(0, QIcon(":/icons/icons/Icon_IWIFile.png"));
|
||||||
|
iwiItem->setText(0, iwiFileName);
|
||||||
|
mIWIFiles[aIWIFile->fileStem.section(".", 0, 0)] = aIWIFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XTreeWidget::AddDDSFile(std::shared_ptr<DDSFile> aDDSFile) {
|
||||||
|
const QString ddsFileName = QString(aDDSFile->fileStem + ".dds");
|
||||||
|
|
||||||
|
for (int i = 0; i < invisibleRootItem()->childCount(); i++) {
|
||||||
|
auto ddsFileItem = invisibleRootItem()->child(i);
|
||||||
|
if (ddsFileItem->text(0) == ddsFileName) {
|
||||||
|
delete ddsFileItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XTreeWidgetItem *ddsItem = new XTreeWidgetItem(this);
|
||||||
|
ddsItem->setIcon(0, QIcon(":/icons/icons/Icon_DDSFile.png"));
|
||||||
|
ddsItem->setText(0, ddsFileName);
|
||||||
|
mDDSFiles[aDDSFile->fileStem.section(".", 0, 0)] = aDDSFile;
|
||||||
|
}
|
||||||
62
app/xtreewidget.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#ifndef XTREEWIDGET_H
|
||||||
|
#define XTREEWIDGET_H
|
||||||
|
|
||||||
|
#include "d3dbsp_structs.h"
|
||||||
|
#include "asset_structs.h"
|
||||||
|
#include "ddsfile.h"
|
||||||
|
#include "iwifile.h"
|
||||||
|
#include "fastfile.h"
|
||||||
|
#include "xtreewidgetitem.h"
|
||||||
|
#include "zonefile.h"
|
||||||
|
|
||||||
|
#include <QTreeWidget>
|
||||||
|
|
||||||
|
class XTreeWidget : public QTreeWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit XTreeWidget(QWidget *parent = nullptr);
|
||||||
|
~XTreeWidget();
|
||||||
|
|
||||||
|
void AddFastFile(std::shared_ptr<FastFile> aFastFile);
|
||||||
|
void AddZoneFile(std::shared_ptr<ZoneFile> aZoneFile, XTreeWidgetItem *aParentItem = nullptr);
|
||||||
|
void AddIWIFile(std::shared_ptr<IWIFile> aIWIFile);
|
||||||
|
void AddDDSFile(std::shared_ptr<DDSFile> aDDSFile);
|
||||||
|
|
||||||
|
std::shared_ptr<ZoneFile> FindZoneFile(const QString aStem);
|
||||||
|
std::shared_ptr<FastFile> FindFastFile(const QString aStem);
|
||||||
|
|
||||||
|
bool HasZoneFile(const QString aStem);
|
||||||
|
bool HasFastFile(const QString aStem);
|
||||||
|
|
||||||
|
void CloseFastFile(const QString aFFName);
|
||||||
|
signals:
|
||||||
|
void DDSFileSelected(std::shared_ptr<DDSFile> aDDSFile, const QString aParentName);
|
||||||
|
void IWIFileSelected(std::shared_ptr<IWIFile> aIWIFile, const QString aParentName);
|
||||||
|
void FastFileSelected(std::shared_ptr<FastFile> aFastFile, const QString aParentName);
|
||||||
|
void ZoneFileSelected(std::shared_ptr<ZoneFile> aZoneFile, const QString aParentName);
|
||||||
|
void LocalStringSelected(std::shared_ptr<ZoneFile> aZoneFile, const QString aParentName);
|
||||||
|
void RawFileSelected(std::shared_ptr<RawFile> aRawFile, const QString aParentName);
|
||||||
|
void ImageSelected(std::shared_ptr<Image> aImage, const QString aParentName);
|
||||||
|
void TechSetSelected(std::shared_ptr<TechSet> aZoneFile, const QString aParentName);
|
||||||
|
void StrTableSelected(std::shared_ptr<StringTable> aStrTable, const QString aParentName);
|
||||||
|
void MenuSelected(std::shared_ptr<Menu> aMenu, const QString aParentName);
|
||||||
|
void SoundSelected(std::shared_ptr<Sound> aSound, const QString aParentName);
|
||||||
|
void MaterialSelected(std::shared_ptr<Material> aMaterial, const QString aParentName);
|
||||||
|
void ItemSelected(const QString itemText);
|
||||||
|
|
||||||
|
void ItemClosed(const QString itemText);
|
||||||
|
void Cleared();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ItemSelectionChanged();
|
||||||
|
void PrepareContextMenu(const QPoint &pos);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMap<QString, std::shared_ptr<FastFile>> mFastFiles;
|
||||||
|
QMap<QString, std::shared_ptr<ZoneFile>> mZoneFiles;
|
||||||
|
QMap<QString, std::shared_ptr<DDSFile>> mDDSFiles;
|
||||||
|
QMap<QString, std::shared_ptr<IWIFile>> mIWIFiles;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // XTREEWIDGET_H
|
||||||
42
app/xtreewidgetitem.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "xtreewidgetitem.h"
|
||||||
|
|
||||||
|
XTreeWidgetItem::XTreeWidgetItem(QTreeWidget *parent, bool group)
|
||||||
|
: QTreeWidgetItem(parent), isGroup(group) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
XTreeWidgetItem::XTreeWidgetItem(QTreeWidgetItem *parent, bool group)
|
||||||
|
: QTreeWidgetItem(parent), isGroup(group) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XTreeWidgetItem::operator<(const QTreeWidgetItem &other) const {
|
||||||
|
// Attempt to cast the other item to our custom type.
|
||||||
|
const XTreeWidgetItem* otherItem = dynamic_cast<const XTreeWidgetItem*>(&other);
|
||||||
|
if (otherItem) {
|
||||||
|
bool thisIsGroup = this->childCount() > 0;
|
||||||
|
bool otherIsGroup = otherItem->childCount() > 0;
|
||||||
|
|
||||||
|
if (thisIsGroup != otherIsGroup) {
|
||||||
|
return otherIsGroup; // Groups should come before non-groups
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fallback to the default string comparison on the current sort column.
|
||||||
|
return QTreeWidgetItem::operator<(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XTreeWidgetItem& XTreeWidgetItem::operator=(const XTreeWidgetItem &other)
|
||||||
|
{
|
||||||
|
if (this != &other) {
|
||||||
|
// Copy text and icon for each column.
|
||||||
|
const int colCount = other.columnCount();
|
||||||
|
for (int i = 0; i < colCount; ++i) {
|
||||||
|
setText(i, other.text(i));
|
||||||
|
setIcon(i, other.icon(i));
|
||||||
|
}
|
||||||
|
// Copy custom members.
|
||||||
|
this->isGroup = other.isGroup;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
24
app/xtreewidgetitem.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef XTREEWIDGETITEM_H
|
||||||
|
#define XTREEWIDGETITEM_H
|
||||||
|
|
||||||
|
#include <QTreeWidget>
|
||||||
|
#include <QTreeWidgetItem>
|
||||||
|
|
||||||
|
// Custom item class
|
||||||
|
class XTreeWidgetItem : public QTreeWidgetItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Flag to indicate if the item is a collapsible group/header.
|
||||||
|
bool isGroup;
|
||||||
|
|
||||||
|
// Constructors: default to non-group unless specified.
|
||||||
|
XTreeWidgetItem(QTreeWidget *parent, bool group = false);
|
||||||
|
XTreeWidgetItem(QTreeWidgetItem *parent, bool group = false);
|
||||||
|
|
||||||
|
// Override the less-than operator to customize sorting.
|
||||||
|
bool operator<(const QTreeWidgetItem &other) const override;
|
||||||
|
XTreeWidgetItem &operator =(const XTreeWidgetItem &other);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XTREEWIDGETITEM_H
|
||||||
@ -3,33 +3,32 @@
|
|||||||
|
|
||||||
ZoneFileViewer::ZoneFileViewer(QWidget *parent)
|
ZoneFileViewer::ZoneFileViewer(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, ui(new Ui::ZoneFileViewer)
|
, ui(new Ui::ZoneFileViewer) {
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
aZoneFile = nullptr;
|
aZoneFile = nullptr;
|
||||||
|
|
||||||
ui->tableWidget_RecordCounts->setColumnCount(2);
|
ui->tableWidget_RecordCounts->setColumnCount(4);
|
||||||
ui->tableWidget_RecordCounts->setHorizontalHeaderLabels({ "Asset", "Count" });
|
ui->tableWidget_RecordCounts->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count", "Icon" });
|
||||||
ui->tableWidget_RecordCounts->horizontalHeader()->setStretchLastSection(true);
|
ui->tableWidget_RecordCounts->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
|
||||||
ui->tableWidget_RecordOrder->setColumnCount(2);
|
ui->tableWidget_RecordOrder->setColumnCount(4);
|
||||||
ui->tableWidget_RecordOrder->setHorizontalHeaderLabels({ "Asset", "Count" });
|
ui->tableWidget_RecordOrder->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count", "Icon" });
|
||||||
ui->tableWidget_RecordOrder->horizontalHeader()->setStretchLastSection(true);
|
ui->tableWidget_RecordOrder->horizontalHeader()->setStretchLastSection(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoneFileViewer::~ZoneFileViewer()
|
ZoneFileViewer::~ZoneFileViewer() {
|
||||||
{
|
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneFileViewer::SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile) {
|
void ZoneFileViewer::SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile) {
|
||||||
ui->tableWidget_RecordCounts->clear();
|
ui->tableWidget_RecordCounts->clearContents();
|
||||||
|
ui->tableWidget_RecordOrder->clearContents();
|
||||||
ui->listWidget_Tags->clear();
|
ui->listWidget_Tags->clear();
|
||||||
|
|
||||||
const QStringList tags = aZoneFile->GetTags();
|
const QStringList tags = aZoneFile->GetTags();
|
||||||
ui->listWidget_Tags->addItems(tags);
|
ui->listWidget_Tags->addItems(tags);
|
||||||
ui->label_Title->setText(aZoneFile->GetFileStem());
|
ui->label_Title->setText(aZoneFile->GetStem() + ".zone");
|
||||||
|
|
||||||
if (tags.isEmpty()) {
|
if (tags.isEmpty()) {
|
||||||
ui->groupBox_Tags->hide();
|
ui->groupBox_Tags->hide();
|
||||||
@ -38,74 +37,91 @@ void ZoneFileViewer::SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString lastAsset = "";
|
QString lastAsset = "";
|
||||||
|
QString lastRecord = "";
|
||||||
|
QIcon assetIcon;
|
||||||
int consecutiveCount = 1;
|
int consecutiveCount = 1;
|
||||||
int consecutiveIndex = 0;
|
int consecutiveIndex = 0;
|
||||||
const QStringList records = aZoneFile->GetRecords();
|
const QStringList records = aZoneFile->GetRecords();
|
||||||
QMap<QString, int> recordCounts = QMap<QString, int>();
|
QMap<QString, int> recordCounts = QMap<QString, int>();
|
||||||
for (const QString &record : records) {
|
for (const QString &record : records) {
|
||||||
|
lastRecord = record;
|
||||||
if (record == "ffffffff") { break; }
|
if (record == "ffffffff") { break; }
|
||||||
if (!recordCounts.contains(record)) {
|
if (!recordCounts.contains(record)) {
|
||||||
recordCounts[record] = 0;
|
recordCounts[record] = 0;
|
||||||
}
|
}
|
||||||
recordCounts[record]++;
|
recordCounts[record]++;
|
||||||
|
|
||||||
QString assetType = Utils::AssetTypeToString(record);
|
QString assetType = aZoneFile->AssetTypeToString(record);
|
||||||
|
if (assetIcon.isNull()) {
|
||||||
|
qDebug() << "Icon is null for record: " << record;
|
||||||
|
}
|
||||||
|
|
||||||
if (lastAsset.isEmpty()) {
|
if (lastAsset.isEmpty()) {
|
||||||
lastAsset = assetType;
|
lastAsset = assetType;
|
||||||
|
lastRecord = record;
|
||||||
} else if (lastAsset == assetType) {
|
} else if (lastAsset == assetType) {
|
||||||
consecutiveCount++;
|
consecutiveCount++;
|
||||||
} else {
|
} else {
|
||||||
ui->tableWidget_RecordOrder->setRowCount(consecutiveIndex + 1);
|
ui->tableWidget_RecordOrder->setRowCount(consecutiveIndex + 1);
|
||||||
|
|
||||||
|
QTableWidgetItem *recordItem = new QTableWidgetItem(lastRecord.toUpper());
|
||||||
QTableWidgetItem *recordStrItem = new QTableWidgetItem(lastAsset);
|
QTableWidgetItem *recordStrItem = new QTableWidgetItem(lastAsset);
|
||||||
QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(consecutiveCount));
|
QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(consecutiveCount));
|
||||||
|
QTableWidgetItem *recordIconItem = new QTableWidgetItem();
|
||||||
|
assetIcon = aZoneFile->AssetStrToIcon(lastAsset);
|
||||||
|
recordIconItem->setIcon(assetIcon);
|
||||||
|
|
||||||
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 0, recordStrItem);
|
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 0, recordItem);
|
||||||
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 1, recordCountItem);
|
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 1, recordStrItem);
|
||||||
|
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 2, recordCountItem);
|
||||||
|
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 3, recordIconItem);
|
||||||
|
|
||||||
consecutiveCount = 1;
|
consecutiveCount = 1;
|
||||||
consecutiveIndex++;
|
consecutiveIndex++;
|
||||||
lastAsset = assetType;
|
lastAsset = assetType;
|
||||||
|
lastRecord = record;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui->tableWidget_RecordOrder->setRowCount(consecutiveIndex + 1);
|
ui->tableWidget_RecordOrder->setRowCount(consecutiveIndex + 1);
|
||||||
|
|
||||||
|
QTableWidgetItem *recordItem = new QTableWidgetItem(lastRecord.toUpper());
|
||||||
QTableWidgetItem *recordStrItem = new QTableWidgetItem(lastAsset);
|
QTableWidgetItem *recordStrItem = new QTableWidgetItem(lastAsset);
|
||||||
QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(consecutiveCount));
|
QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(consecutiveCount));
|
||||||
|
QTableWidgetItem *recordIconItem = new QTableWidgetItem();
|
||||||
|
assetIcon = aZoneFile->AssetStrToIcon(lastAsset);
|
||||||
|
recordIconItem->setIcon(assetIcon);
|
||||||
|
|
||||||
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 0, recordStrItem);
|
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 0, recordItem);
|
||||||
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 1, recordCountItem);
|
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 1, recordStrItem);
|
||||||
|
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 2, recordCountItem);
|
||||||
|
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 3, recordIconItem);
|
||||||
|
|
||||||
int recordIndex = 0;
|
int recordIndex = 0;
|
||||||
for (const QString &record : recordCounts.keys()) {
|
for (const QString &record : recordCounts.keys()) {
|
||||||
int recordCount = recordCounts[record];
|
int recordCount = recordCounts[record];
|
||||||
QString assetType = Utils::AssetTypeToString(record);
|
|
||||||
|
QString assetType = aZoneFile->AssetTypeToString(record);
|
||||||
|
assetIcon = aZoneFile->AssetStrToIcon(assetType);
|
||||||
|
if (assetIcon.isNull()) {
|
||||||
|
qDebug() << "Icon is null for record: " << record;
|
||||||
|
}
|
||||||
|
|
||||||
ui->tableWidget_RecordCounts->setRowCount(recordIndex + 1);
|
ui->tableWidget_RecordCounts->setRowCount(recordIndex + 1);
|
||||||
|
|
||||||
QTableWidgetItem *recordCountStrItem = new QTableWidgetItem(assetType);
|
QTableWidgetItem *recordCountStrItem = new QTableWidgetItem(assetType);
|
||||||
|
QTableWidgetItem *recordItem = new QTableWidgetItem(record.toUpper());
|
||||||
QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(recordCount));
|
QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(recordCount));
|
||||||
|
QTableWidgetItem *recordIconItem = new QTableWidgetItem();
|
||||||
|
recordIconItem->setIcon(assetIcon);
|
||||||
|
|
||||||
ui->tableWidget_RecordCounts->setItem(recordIndex, 0, recordCountStrItem);
|
ui->tableWidget_RecordCounts->setItem(recordIndex, 0, recordItem);
|
||||||
ui->tableWidget_RecordCounts->setItem(recordIndex, 1, recordCountItem);
|
ui->tableWidget_RecordCounts->setItem(recordIndex, 1, recordCountStrItem);
|
||||||
|
ui->tableWidget_RecordCounts->setItem(recordIndex, 2, recordCountItem);
|
||||||
|
ui->tableWidget_RecordCounts->setItem(recordIndex, 3, recordIconItem);
|
||||||
|
|
||||||
recordIndex++;
|
recordIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto assetMap = aZoneFile->GetAssetMap();
|
ui->tableWidget_RecordOrder->resizeColumnsToContents();
|
||||||
for (LocalString localString : assetMap.localStrings) {
|
ui->tableWidget_RecordCounts->resizeColumnsToContents();
|
||||||
}
|
|
||||||
for (RawFile rawFile : assetMap.rawFiles) {
|
|
||||||
}
|
|
||||||
for (TechSet techSet : assetMap.techSets) {
|
|
||||||
}
|
|
||||||
for (Image image : assetMap.images) {
|
|
||||||
}
|
|
||||||
for (Animation animation : assetMap.animations) {
|
|
||||||
}
|
|
||||||
for (StringTable stringTable : assetMap.stringTables) {
|
|
||||||
}
|
|
||||||
for (MenuFile menuFile : assetMap.menuFiles) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
99
app/zonefileviewer.ui
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ZoneFileViewer</class>
|
||||||
|
<widget class="QWidget" name="ZoneFileViewer">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>556</width>
|
||||||
|
<height>428</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_Title">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>16</pointsize>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>ZoneFile 0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_Tags">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Roboto</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Tags</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Search:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit_TagSearch">
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Search tags...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listWidget_Tags"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_RecordCounts">
|
||||||
|
<property name="title">
|
||||||
|
<string>Record Counts</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="tableWidget_RecordCounts"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_RecordOrder">
|
||||||
|
<property name="title">
|
||||||
|
<string>Record Order</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="tableWidget_RecordOrder"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
410
compressor.h
@ -1,410 +0,0 @@
|
|||||||
#ifndef COMPRESSOR_H
|
|
||||||
#define COMPRESSOR_H
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
#include "QtZlib/zlib.h"
|
|
||||||
#include "lzokay.hpp"
|
|
||||||
#include "lzx.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <QByteArray>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QDataStream>
|
|
||||||
#include <QVector>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
EResult_LookbehindOverrun = -4,
|
|
||||||
EResult_OutputOverrun = -3,
|
|
||||||
EResult_InputOverrun = -2,
|
|
||||||
EResult_Error = -1,
|
|
||||||
EResult_Success = 0,
|
|
||||||
EResult_InputNotConsumed = 1,
|
|
||||||
} lzokay_EResult;
|
|
||||||
|
|
||||||
static_assert(EResult_LookbehindOverrun == lzokay_EResult(lzokay::EResult::LookbehindOverrun), "LookbehindOverrun mismatch");
|
|
||||||
static_assert(EResult_OutputOverrun == lzokay_EResult(lzokay::EResult::OutputOverrun), "OutputOverrun mismatch");
|
|
||||||
static_assert(EResult_InputOverrun == lzokay_EResult(lzokay::EResult::InputOverrun), "InputOverrun mismatch");
|
|
||||||
static_assert(EResult_Error == lzokay_EResult(lzokay::EResult::Error), "Error mismatch");
|
|
||||||
static_assert(EResult_Success == lzokay_EResult(lzokay::EResult::Success), "Success mismatch");
|
|
||||||
static_assert(EResult_InputNotConsumed == lzokay_EResult(lzokay::EResult::InputNotConsumed), "InputNotConsumed mismatch");
|
|
||||||
|
|
||||||
class Compressor {
|
|
||||||
public:
|
|
||||||
static QByteArray DecompressZLIB(const QByteArray &compressedData) {
|
|
||||||
if (compressedData.isEmpty())
|
|
||||||
return QByteArray();
|
|
||||||
|
|
||||||
// Set up the inflate stream.
|
|
||||||
z_stream strm;
|
|
||||||
memset(&strm, 0, sizeof(strm));
|
|
||||||
// The inflate() function needs a non-const pointer; this is safe as we never modify the input.
|
|
||||||
strm.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(compressedData.data()));
|
|
||||||
strm.avail_in = static_cast<uInt>(compressedData.size());
|
|
||||||
|
|
||||||
// Use inflateInit(); if you want to support gzip streams, see note below.
|
|
||||||
int ret = inflateInit(&strm);
|
|
||||||
if (ret != Z_OK) {
|
|
||||||
qWarning() << "inflateInit failed:" << zError(ret);
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray outArray;
|
|
||||||
char buffer[4096];
|
|
||||||
|
|
||||||
// Decompress until we reach the stream end.
|
|
||||||
do {
|
|
||||||
strm.next_out = reinterpret_cast<Bytef*>(buffer);
|
|
||||||
strm.avail_out = sizeof(buffer);
|
|
||||||
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH);
|
|
||||||
// Handle a special case: if inflate() returns Z_BUF_ERROR without
|
|
||||||
// having produced any output and with no further input, then we break out.
|
|
||||||
if (ret == Z_BUF_ERROR && strm.avail_in == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ret != Z_OK && ret != Z_STREAM_END) {
|
|
||||||
qWarning() << "Error: ZLib inflate failed:" << zError(ret);
|
|
||||||
inflateEnd(&strm);
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate number of bytes produced in this iteration.
|
|
||||||
int bytesProduced = sizeof(buffer) - strm.avail_out;
|
|
||||||
if (bytesProduced > 0)
|
|
||||||
outArray.append(buffer, bytesProduced);
|
|
||||||
|
|
||||||
} while (ret != Z_STREAM_END);
|
|
||||||
|
|
||||||
inflateEnd(&strm);
|
|
||||||
return outArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QByteArray DecompressLZO(const QByteArray& input) {
|
|
||||||
lzokay::EResult error;
|
|
||||||
|
|
||||||
// Ensure the input QByteArray is valid
|
|
||||||
if (input.isEmpty()) {
|
|
||||||
qDebug() << "Input QByteArray is empty.";
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1: Cast QByteArray to uint8_t*
|
|
||||||
const uint8_t *compressedData = reinterpret_cast<const uint8_t *>(input.constData());
|
|
||||||
std::size_t compressedSize = static_cast<std::size_t>(input.size());
|
|
||||||
|
|
||||||
// Step 2: Allocate a sufficiently large decompression buffer
|
|
||||||
// Use a large initial estimate if the decompressed size is unknown
|
|
||||||
std::size_t initialBufferSize = compressedSize * 20; // Arbitrary multiplier for decompression
|
|
||||||
std::unique_ptr<uint8_t[]> decompressed(new uint8_t[initialBufferSize]);
|
|
||||||
|
|
||||||
// Step 3: Attempt decompression
|
|
||||||
std::size_t decompressedSize = 0;
|
|
||||||
error = lzokay::decompress(
|
|
||||||
compressedData, compressedSize, // Input data and size
|
|
||||||
decompressed.get(), initialBufferSize, // Output buffer and initial size
|
|
||||||
decompressedSize // Actual decompressed size
|
|
||||||
);
|
|
||||||
|
|
||||||
// Step 4: Handle decompression errors
|
|
||||||
if (error != lzokay::EResult::Success) {
|
|
||||||
qDebug() << "Decompression failed with error code:" << static_cast<int>(error);
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 5: Return the decompressed data as a QByteArray
|
|
||||||
return QByteArray(reinterpret_cast<const char *>(decompressed.get()), decompressedSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int VECTOR_SIZE = 16; // 16 32-bit words
|
|
||||||
static const int NUM_OF_BLOCKS_PER_CHUNK = 8192;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
// Helper functions (assuming little–endian order)
|
|
||||||
|
|
||||||
static void Convert32BitTo8Bit(quint32 value, quint8* array) {
|
|
||||||
array[0] = static_cast<quint8>(value >> 0);
|
|
||||||
array[1] = static_cast<quint8>(value >> 8);
|
|
||||||
array[2] = static_cast<quint8>(value >> 16);
|
|
||||||
array[3] = static_cast<quint8>(value >> 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
static quint32 ConvertArrayTo32Bit(const QByteArray &array) {
|
|
||||||
return ((static_cast<quint32>(static_cast<uchar>(array[0])) << 0) |
|
|
||||||
(static_cast<quint32>(static_cast<uchar>(array[1])) << 8) |
|
|
||||||
(static_cast<quint32>(static_cast<uchar>(array[2])) << 16) |
|
|
||||||
(static_cast<quint32>(static_cast<uchar>(array[3])) << 24));
|
|
||||||
}
|
|
||||||
|
|
||||||
static quint32 Rotate(quint32 value, quint32 numBits) {
|
|
||||||
return (value << numBits) | (value >> (32 - numBits));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the IV table from a 0x20–byte feed. The table is 0xFB0 bytes.
|
|
||||||
static QByteArray InitIVTable(const QByteArray &feed) {
|
|
||||||
const int tableSize = 0xFB0;
|
|
||||||
QByteArray table;
|
|
||||||
table.resize(tableSize);
|
|
||||||
int ptr = 0;
|
|
||||||
for (int i = 0; i < 200; ++i) {
|
|
||||||
for (int x = 0; x < 5; ++x) {
|
|
||||||
if (static_cast<uchar>(feed.at(ptr)) == 0x00)
|
|
||||||
ptr = 0;
|
|
||||||
int base = i * 20 + x * 4;
|
|
||||||
table[base] = feed.at(ptr);
|
|
||||||
table[base + 1] = feed.at(ptr);
|
|
||||||
table[base + 2] = feed.at(ptr);
|
|
||||||
table[base + 3] = feed.at(ptr);
|
|
||||||
++ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Copy block numbers [1,0,0,0] into the last 16 bytes
|
|
||||||
QByteArray oneBlock;
|
|
||||||
oneBlock.append(char(1)); oneBlock.append(char(0)); oneBlock.append(char(0)); oneBlock.append(char(0));
|
|
||||||
table.replace(0xFA0, 4, oneBlock);
|
|
||||||
table.replace(0xFA4, 4, oneBlock);
|
|
||||||
table.replace(0xFA8, 4, oneBlock);
|
|
||||||
table.replace(0xFAC, 4, oneBlock);
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "unk" function as in the C# code.
|
|
||||||
static int unk(quint64 arg1, quint8 arg2) {
|
|
||||||
if (arg2 >= 0x40)
|
|
||||||
return 0;
|
|
||||||
return static_cast<int>(arg1 >> arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute the IV for a given section index using the IV table.
|
|
||||||
static QByteArray GetIV(const QByteArray &table, int index) {
|
|
||||||
int num1 = 0xFA0 + index;
|
|
||||||
int num2 = unk(0x51EB851FLL * num1, 0x20);
|
|
||||||
int adjust = ((num2 >> 6) + (num2 >> 31));
|
|
||||||
int startIndex = 20 * (num1 - 200 * adjust);
|
|
||||||
// Return 8 bytes from that location.
|
|
||||||
return table.mid(startIndex, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the IV table given the section's SHA1 hash.
|
|
||||||
static void UpdateIVTable(QByteArray &table, int index, const QByteArray §ionHash) {
|
|
||||||
int blockNumIndex = index % 4;
|
|
||||||
int baseOffset = 0xFA0 + blockNumIndex * 4;
|
|
||||||
quint32 blockNumVal = (static_cast<uchar>(table.at(baseOffset)) ) |
|
|
||||||
(static_cast<uchar>(table.at(baseOffset + 1)) << 8 ) |
|
|
||||||
(static_cast<uchar>(table.at(baseOffset + 2)) << 16) |
|
|
||||||
(static_cast<uchar>(table.at(baseOffset + 3)) << 24);
|
|
||||||
int blockNum = blockNumVal * 4 + index;
|
|
||||||
int num2 = unk(0x51EB851FLL * blockNum, 0x20);
|
|
||||||
int adjust = ((num2 >> 6) + (num2 >> 31));
|
|
||||||
int startIndex = 20 * (blockNum - 200 * adjust) + 1;
|
|
||||||
int hashIndex = 0;
|
|
||||||
for (int x = 0; x < 4; ++x) {
|
|
||||||
table[startIndex - 1] = table.at(startIndex - 1) ^ sectionHash.at(hashIndex);
|
|
||||||
table[startIndex] = table.at(startIndex) ^ sectionHash.at(hashIndex + 1);
|
|
||||||
table[startIndex + 1] = table.at(startIndex + 1) ^ sectionHash.at(hashIndex + 2);
|
|
||||||
table[startIndex + 2] = table.at(startIndex + 2) ^ sectionHash.at(hashIndex + 3);
|
|
||||||
table[startIndex + 3] = table.at(startIndex + 3) ^ sectionHash.at(hashIndex + 4);
|
|
||||||
startIndex += 5;
|
|
||||||
hashIndex += 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static quint32 ToUInt32(const QByteArray &data, int offset) {
|
|
||||||
// Converts 4 bytes (starting at offset) from data into a 32-bit unsigned integer (little-endian)
|
|
||||||
return ((static_cast<quint32>(static_cast<uchar>(data[offset])) ) |
|
|
||||||
(static_cast<quint32>(static_cast<uchar>(data[offset+1])) << 8 ) |
|
|
||||||
(static_cast<quint32>(static_cast<uchar>(data[offset+2])) << 16) |
|
|
||||||
(static_cast<quint32>(static_cast<uchar>(data[offset+3])) << 24));
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
// Salsa20 decryption for one section.
|
|
||||||
// This function resets the counter for each section.
|
|
||||||
static QByteArray salsa20DecryptSection(const QByteArray §ionData, const QByteArray &key, const QByteArray &iv, int blockSize = 64)
|
|
||||||
{
|
|
||||||
// Choose the appropriate constant based on key length.
|
|
||||||
QByteArray constants;
|
|
||||||
if (key.size() == 32)
|
|
||||||
constants = "expand 32-byte k";
|
|
||||||
else if (key.size() == 16)
|
|
||||||
constants = "expand 16-byte k";
|
|
||||||
else {
|
|
||||||
qWarning() << "Invalid key size:" << key.size() << "; expected 16 or 32 bytes.";
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<quint32> state(VECTOR_SIZE);
|
|
||||||
|
|
||||||
// Set state[0] using the first 4 bytes of the constant.
|
|
||||||
state[0] = ConvertArrayTo32Bit(constants.mid(0, 4));
|
|
||||||
|
|
||||||
// state[1] through state[4] come from the first 16 bytes of the key.
|
|
||||||
state[1] = ToUInt32(key, 0);
|
|
||||||
state[2] = ToUInt32(key, 4);
|
|
||||||
state[3] = ToUInt32(key, 8);
|
|
||||||
state[4] = ToUInt32(key, 12);
|
|
||||||
|
|
||||||
// state[5] comes from the next 4 bytes of the constant.
|
|
||||||
state[5] = ConvertArrayTo32Bit(constants.mid(4, 4));
|
|
||||||
|
|
||||||
// state[6] and state[7] come from the IV (which must be 8 bytes).
|
|
||||||
state[6] = ConvertArrayTo32Bit(iv.mid(0, 4));
|
|
||||||
state[7] = ConvertArrayTo32Bit(iv.mid(4, 4));
|
|
||||||
|
|
||||||
// state[8] and state[9] are the 64-bit block counter (start at 0).
|
|
||||||
state[8] = 0;
|
|
||||||
state[9] = 0;
|
|
||||||
|
|
||||||
// state[10] comes from the next 4 bytes of the constant.
|
|
||||||
state[10] = ConvertArrayTo32Bit(constants.mid(8, 4));
|
|
||||||
|
|
||||||
// For state[11] through state[14]:
|
|
||||||
// If the key is 32 bytes, use bytes 16..31; if 16 bytes, reuse the first 16 bytes.
|
|
||||||
if (key.size() == 32) {
|
|
||||||
state[11] = ToUInt32(key, 16);
|
|
||||||
state[12] = ToUInt32(key, 20);
|
|
||||||
state[13] = ToUInt32(key, 24);
|
|
||||||
state[14] = ToUInt32(key, 28);
|
|
||||||
} else { // key.size() == 16
|
|
||||||
state[11] = ToUInt32(key, 0);
|
|
||||||
state[12] = ToUInt32(key, 4);
|
|
||||||
state[13] = ToUInt32(key, 8);
|
|
||||||
state[14] = ToUInt32(key, 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
// state[15] comes from the last 4 bytes of the constant.
|
|
||||||
state[15] = ConvertArrayTo32Bit(constants.mid(12, 4));
|
|
||||||
|
|
||||||
// Prepare the output buffer.
|
|
||||||
QByteArray output(sectionData.size(), Qt::Uninitialized);
|
|
||||||
int numBlocks = sectionData.size() / blockSize;
|
|
||||||
int remainder = sectionData.size() % blockSize;
|
|
||||||
|
|
||||||
// Process each full block.
|
|
||||||
for (int blockIndex = 0; blockIndex < numBlocks; ++blockIndex) {
|
|
||||||
QVector<quint32> x = state; // make a copy of the current state for this block
|
|
||||||
|
|
||||||
// Run 20 rounds (10 iterations) of Salsa20.
|
|
||||||
for (int round = 20; round > 0; round -= 2) {
|
|
||||||
x[4] ^= Rotate(x[0] + x[12], 7);
|
|
||||||
x[8] ^= Rotate(x[4] + x[0], 9);
|
|
||||||
x[12] ^= Rotate(x[8] + x[4], 13);
|
|
||||||
x[0] ^= Rotate(x[12] + x[8], 18);
|
|
||||||
|
|
||||||
x[9] ^= Rotate(x[5] + x[1], 7);
|
|
||||||
x[13] ^= Rotate(x[9] + x[5], 9);
|
|
||||||
x[1] ^= Rotate(x[13] + x[9], 13);
|
|
||||||
x[5] ^= Rotate(x[1] + x[13], 18);
|
|
||||||
|
|
||||||
x[14] ^= Rotate(x[10] + x[6], 7);
|
|
||||||
x[2] ^= Rotate(x[14] + x[10], 9);
|
|
||||||
x[6] ^= Rotate(x[2] + x[14], 13);
|
|
||||||
x[10] ^= Rotate(x[6] + x[2], 18);
|
|
||||||
|
|
||||||
x[3] ^= Rotate(x[15] + x[11], 7);
|
|
||||||
x[7] ^= Rotate(x[3] + x[15], 9);
|
|
||||||
x[11] ^= Rotate(x[7] + x[3], 13);
|
|
||||||
x[15] ^= Rotate(x[11] + x[7], 18);
|
|
||||||
|
|
||||||
x[1] ^= Rotate(x[0] + x[3], 7);
|
|
||||||
x[2] ^= Rotate(x[1] + x[0], 9);
|
|
||||||
x[3] ^= Rotate(x[2] + x[1], 13);
|
|
||||||
x[0] ^= Rotate(x[3] + x[2], 18);
|
|
||||||
|
|
||||||
x[6] ^= Rotate(x[5] + x[4], 7);
|
|
||||||
x[7] ^= Rotate(x[6] + x[5], 9);
|
|
||||||
x[4] ^= Rotate(x[7] + x[6], 13);
|
|
||||||
x[5] ^= Rotate(x[4] + x[7], 18);
|
|
||||||
|
|
||||||
x[11] ^= Rotate(x[10] + x[9], 7);
|
|
||||||
x[8] ^= Rotate(x[11] + x[10], 9);
|
|
||||||
x[9] ^= Rotate(x[8] + x[11], 13);
|
|
||||||
x[10] ^= Rotate(x[9] + x[8], 18);
|
|
||||||
|
|
||||||
x[12] ^= Rotate(x[15] + x[14], 7);
|
|
||||||
x[13] ^= Rotate(x[12] + x[15], 9);
|
|
||||||
x[14] ^= Rotate(x[13] + x[12], 13);
|
|
||||||
x[15] ^= Rotate(x[14] + x[13], 18);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Produce the 64-byte keystream block by adding the original state.
|
|
||||||
QVector<quint8> keyStreamBlock(blockSize);
|
|
||||||
for (int i = 0; i < VECTOR_SIZE; ++i) {
|
|
||||||
x[i] += state[i];
|
|
||||||
Convert32BitTo8Bit(x[i], keyStreamBlock.data() + 4 * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// XOR the keystream block with the corresponding block of sectionData.
|
|
||||||
const uchar* inBlock = reinterpret_cast<const uchar*>(sectionData.constData()) + blockIndex * blockSize;
|
|
||||||
uchar* outBlock = reinterpret_cast<uchar*>(output.data()) + blockIndex * blockSize;
|
|
||||||
for (int j = 0; j < blockSize; ++j) {
|
|
||||||
outBlock[j] = inBlock[j] ^ keyStreamBlock[j];
|
|
||||||
}
|
|
||||||
// Increment the 64-bit block counter.
|
|
||||||
state[8]++;
|
|
||||||
if (state[8] == 0)
|
|
||||||
state[9]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process any remaining bytes.
|
|
||||||
if (remainder > 0) {
|
|
||||||
QVector<quint32> x = state;
|
|
||||||
for (int round = 20; round > 0; round -= 2) {
|
|
||||||
x[4] ^= Rotate(x[0] + x[12], 7);
|
|
||||||
x[8] ^= Rotate(x[4] + x[0], 9);
|
|
||||||
x[12] ^= Rotate(x[8] + x[4], 13);
|
|
||||||
x[0] ^= Rotate(x[12] + x[8], 18);
|
|
||||||
|
|
||||||
x[9] ^= Rotate(x[5] + x[1], 7);
|
|
||||||
x[13] ^= Rotate(x[9] + x[5], 9);
|
|
||||||
x[1] ^= Rotate(x[13] + x[9], 13);
|
|
||||||
x[5] ^= Rotate(x[1] + x[13], 18);
|
|
||||||
|
|
||||||
x[14] ^= Rotate(x[10] + x[6], 7);
|
|
||||||
x[2] ^= Rotate(x[14] + x[10], 9);
|
|
||||||
x[6] ^= Rotate(x[2] + x[14], 13);
|
|
||||||
x[10] ^= Rotate(x[6] + x[2], 18);
|
|
||||||
|
|
||||||
x[3] ^= Rotate(x[15] + x[11], 7);
|
|
||||||
x[7] ^= Rotate(x[3] + x[15], 9);
|
|
||||||
x[11] ^= Rotate(x[7] + x[3], 13);
|
|
||||||
x[15] ^= Rotate(x[11] + x[7], 18);
|
|
||||||
|
|
||||||
x[1] ^= Rotate(x[0] + x[3], 7);
|
|
||||||
x[2] ^= Rotate(x[1] + x[0], 9);
|
|
||||||
x[3] ^= Rotate(x[2] + x[1], 13);
|
|
||||||
x[0] ^= Rotate(x[3] + x[2], 18);
|
|
||||||
|
|
||||||
x[6] ^= Rotate(x[5] + x[4], 7);
|
|
||||||
x[7] ^= Rotate(x[6] + x[5], 9);
|
|
||||||
x[4] ^= Rotate(x[7] + x[6], 13);
|
|
||||||
x[5] ^= Rotate(x[4] + x[7], 18);
|
|
||||||
|
|
||||||
x[11] ^= Rotate(x[10] + x[9], 7);
|
|
||||||
x[8] ^= Rotate(x[11] + x[10], 9);
|
|
||||||
x[9] ^= Rotate(x[8] + x[11], 13);
|
|
||||||
x[10] ^= Rotate(x[9] + x[8], 18);
|
|
||||||
|
|
||||||
x[12] ^= Rotate(x[15] + x[14], 7);
|
|
||||||
x[13] ^= Rotate(x[12] + x[15], 9);
|
|
||||||
x[14] ^= Rotate(x[13] + x[12], 13);
|
|
||||||
x[15] ^= Rotate(x[14] + x[13], 18);
|
|
||||||
}
|
|
||||||
QVector<quint8> keyStreamBlock(blockSize);
|
|
||||||
for (int i = 0; i < VECTOR_SIZE; ++i) {
|
|
||||||
x[i] += state[i];
|
|
||||||
Convert32BitTo8Bit(x[i], keyStreamBlock.data() + 4 * i);
|
|
||||||
}
|
|
||||||
const uchar* inBlock = reinterpret_cast<const uchar*>(sectionData.constData()) + numBlocks * blockSize;
|
|
||||||
uchar* outBlock = reinterpret_cast<uchar*>(output.data()) + numBlocks * blockSize;
|
|
||||||
for (int j = 0; j < remainder; ++j)
|
|
||||||
outBlock[j] = inBlock[j] ^ keyStreamBlock[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // COMPRESSOR_H
|
|
||||||
@ -53,5 +53,39 @@
|
|||||||
<file>icons/Icon_WAVFile.png</file>
|
<file>icons/Icon_WAVFile.png</file>
|
||||||
<file>icons/Icon_MenuFile.png</file>
|
<file>icons/Icon_MenuFile.png</file>
|
||||||
<file>icons/Icon_Image.png</file>
|
<file>icons/Icon_Image.png</file>
|
||||||
|
<file>icons/Icon_Model.png</file>
|
||||||
|
<file>icons/Icon_StringTable.png</file>
|
||||||
|
<file>icons/Icon_Sound.png</file>
|
||||||
|
<file>icons/Icon_Pause.png</file>
|
||||||
|
<file>icons/Icon_Play.png</file>
|
||||||
|
<file>icons/Icon_SkipBack.png</file>
|
||||||
|
<file>icons/Icon_SkipForward.png</file>
|
||||||
|
<file>icons/Icon_Stop.png</file>
|
||||||
|
<file>icons/Icon_Editor.png</file>
|
||||||
|
<file>icons/Icon_Views.png</file>
|
||||||
|
<file>icons/Icon_Tree.png</file>
|
||||||
|
<file>icons/Icon_Copy.png</file>
|
||||||
|
<file>icons/Icon_Cut.png</file>
|
||||||
|
<file>icons/Icon_Find.png</file>
|
||||||
|
<file>icons/Icon_NewFile.png</file>
|
||||||
|
<file>icons/Icon_Paste.png</file>
|
||||||
|
<file>icons/Icon_Save.png</file>
|
||||||
|
<file>icons/Icon_OpenFile.png</file>
|
||||||
|
<file>icons/Icon_COD2.png</file>
|
||||||
|
<file>icons/Icon_Material.png</file>
|
||||||
|
<file>icons/Icon_Animation.png</file>
|
||||||
|
<file>icons/Icon_BSP.png</file>
|
||||||
|
<file>icons/Icon_ColMapSp.png</file>
|
||||||
|
<file>icons/Icon_Effect.png</file>
|
||||||
|
<file>icons/Icon_GameMapSp.png</file>
|
||||||
|
<file>icons/Icon_Font.png</file>
|
||||||
|
<file>icons/Icon_FXMap.png</file>
|
||||||
|
<file>icons/Icon_LightDef.png</file>
|
||||||
|
<file>icons/Icon_Weapon.png</file>
|
||||||
|
<file>icons/Icon_RawFile.png</file>
|
||||||
|
<file>icons/Icon_Destructible.png</file>
|
||||||
|
<file>icons/Icon_PhysPreset.png</file>
|
||||||
|
<file>icons/Icon_Wii.png</file>
|
||||||
|
<file>icons/Icon_WiiU.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
BIN
data/icons/Icon_Animation.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
data/icons/Icon_BSP.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
data/icons/Icon_COD2.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
data/icons/Icon_ColMapSp.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
data/icons/Icon_Copy.png
Normal file
|
After Width: | Height: | Size: 316 B |
BIN
data/icons/Icon_Cut.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
data/icons/Icon_Destructible.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
data/icons/Icon_Editor.png
Normal file
|
After Width: | Height: | Size: 210 B |
BIN
data/icons/Icon_Effect.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
data/icons/Icon_FXMap.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
data/icons/Icon_Find.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
data/icons/Icon_Font.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
data/icons/Icon_GameMapSp.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
data/icons/Icon_LightDef.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
data/icons/Icon_Material.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
data/icons/Icon_Model.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
data/icons/Icon_NewFile.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
data/icons/Icon_OpenFile.png
Normal file
|
After Width: | Height: | Size: 317 B |
BIN
data/icons/Icon_Paste.png
Normal file
|
After Width: | Height: | Size: 537 B |
BIN
data/icons/Icon_Pause.png
Normal file
|
After Width: | Height: | Size: 213 B |
BIN
data/icons/Icon_PhysPreset.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
data/icons/Icon_Play.png
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
data/icons/Icon_RawFile.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
data/icons/Icon_Save.png
Normal file
|
After Width: | Height: | Size: 371 B |
BIN
data/icons/Icon_SkipBack.png
Normal file
|
After Width: | Height: | Size: 488 B |
BIN
data/icons/Icon_SkipForward.png
Normal file
|
After Width: | Height: | Size: 532 B |
BIN
data/icons/Icon_Sound.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
data/icons/Icon_Stop.png
Normal file
|
After Width: | Height: | Size: 195 B |