diff --git a/app/rumblefileviewer.cpp b/app/rumblefileviewer.cpp new file mode 100644 index 0000000..a6483f2 --- /dev/null +++ b/app/rumblefileviewer.cpp @@ -0,0 +1,58 @@ +#include "rumblefileviewer.h" +#include "ui_rumblefileviewer.h" + +RumbleFileViewer::RumbleFileViewer(QWidget *parent) + : QWidget(parent) + , ui(new Ui::RumbleFileViewer) + , mPropertyCount() + , mRumbleFile(nullptr) { + ui->setupUi(this); + + ui->tableWidget_Properties->setColumnCount(2); + ui->tableWidget_Properties->setRowCount(0); + ui->tableWidget_Properties->setColumnWidth(0, 200); + ui->tableWidget_Properties->horizontalHeader()->setStretchLastSection(true); +} + +RumbleFileViewer::~RumbleFileViewer() { + delete ui; +} + +void RumbleFileViewer::SetRumbleFile(std::shared_ptr aRumbleFile) { + mRumbleFile = aRumbleFile; + + ui->tableWidget_Properties->clear(); + + const QString magic = aRumbleFile->contents.left(6); + if (magic != "RUMBLE") { + qDebug() << "Rumble file has invalid magic: " << magic; + return; + } + + int firstIndex = 0; + int secondIndex = 0; + int thirdIndex = 0; + + int startIndex = 0; + for (int i = 0; i < aRumbleFile->contents.count("\\") / 2; i++) { + ui->tableWidget_Properties->setRowCount(i + 1); + ui->spinBox_Entries->setValue(i + 1); + + firstIndex = aRumbleFile->contents.indexOf("\\", startIndex); + secondIndex = aRumbleFile->contents.indexOf("\\", firstIndex + 1); + thirdIndex = aRumbleFile->contents.indexOf("\\", secondIndex + 1); + if (thirdIndex == -1) { + thirdIndex = aRumbleFile->contents.size(); + } + + const QString keyStr = aRumbleFile->contents.mid(firstIndex + 1, secondIndex - firstIndex - 1); + QTableWidgetItem *keyItem = new QTableWidgetItem(keyStr); + ui->tableWidget_Properties->setItem(i, 0, keyItem); + + const QString valStr = aRumbleFile->contents.mid(secondIndex + 1, thirdIndex - secondIndex - 1); + QTableWidgetItem *valueItem = new QTableWidgetItem(valStr); + ui->tableWidget_Properties->setItem(i, 1, valueItem); + + startIndex = thirdIndex; + } +} diff --git a/app/rumblefileviewer.h b/app/rumblefileviewer.h new file mode 100644 index 0000000..eb21e23 --- /dev/null +++ b/app/rumblefileviewer.h @@ -0,0 +1,28 @@ +#ifndef RUMBLEFILEVIEWER_H +#define RUMBLEFILEVIEWER_H + +#include "asset_structs.h" +#include "zonefile.h" +#include + +namespace Ui { +class RumbleFileViewer; +} + +class RumbleFileViewer : public QWidget +{ + Q_OBJECT + +public: + explicit RumbleFileViewer(QWidget *parent = nullptr); + ~RumbleFileViewer(); + + void SetRumbleFile(std::shared_ptr aRumbleFile); + +private: + Ui::RumbleFileViewer *ui; + quint32 mPropertyCount; + std::shared_ptr mRumbleFile; +}; + +#endif // RUMBLEFILEVIEWER_H diff --git a/app/rumblefileviewer.ui b/app/rumblefileviewer.ui new file mode 100644 index 0000000..e9d0174 --- /dev/null +++ b/app/rumblefileviewer.ui @@ -0,0 +1,153 @@ + + + RumbleFileViewer + + + + 0 + 0 + 841 + 457 + + + + + 841 + 457 + + + + Form + + + + + + + Roboto + 16 + true + + + + Rumble File Viewer + + + + + + + + + + + + 325 + 398 + + + + + 325 + 16777215 + + + + + Roboto + 9 + + + + Header + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + false + + + 10000 + + + 1 + + + + + + + Entries: + + + + + + + + + + + + + 400 + 400 + + + + + Roboto + 9 + + + + Properties + + + + + + + 0 + 0 + + + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 0 + + + + + + + + + diff --git a/app/rumblegraphviewer.cpp b/app/rumblegraphviewer.cpp new file mode 100644 index 0000000..ca3dc8e --- /dev/null +++ b/app/rumblegraphviewer.cpp @@ -0,0 +1,54 @@ +#include "rumblegraphviewer.h" +#include "ui_rumblegraphviewer.h" + +RumbleGraphViewer::RumbleGraphViewer(QWidget *parent) + : QWidget(parent) + , ui(new Ui::RumbleGraphViewer), + mEntryCount(), + mRumbleGraphFile(nullptr) { + ui->setupUi(this); + + ui->tableWidget_Entries->setColumnCount(2); + ui->tableWidget_Entries->setHorizontalHeaderLabels({ "X", "Y" }); + ui->tableWidget_Entries->setRowCount(0); + ui->tableWidget_Entries->setColumnWidth(0, 200); + ui->tableWidget_Entries->horizontalHeader()->setStretchLastSection(true); +} + +RumbleGraphViewer::~RumbleGraphViewer() { + delete ui; +} + +void RumbleGraphViewer::SetRumbleGraphFile(const std::shared_ptr aRawFile) { + mRumbleGraphFile = aRawFile; + + QDataStream rawFileStream(mRumbleGraphFile->contents.toLatin1()); + + QByteArray magic(15, Qt::Uninitialized); + rawFileStream.readRawData(magic.data(), 15); + + rawFileStream.skipRawData(4); + + char sectionChar; + rawFileStream >> sectionChar; + int sectionCount = sectionChar - '0'; + ui->tableWidget_Entries->setRowCount(sectionCount); + ui->spinBox_Entries->setValue(sectionCount); + ui->groupBox_LocalStrViewer->setTitle(QString("Entries (%1)").arg(sectionCount)); + + rawFileStream.skipRawData(2); + + for (int i = 0; i < sectionCount; i++) { + QByteArray xVal(6, Qt::Uninitialized), yVal(6, Qt::Uninitialized); + rawFileStream.readRawData(xVal.data(), 6); + rawFileStream.skipRawData(1); + rawFileStream.readRawData(yVal.data(), 6); + rawFileStream.skipRawData(2); + + QTableWidgetItem *xItem = new QTableWidgetItem(xVal); + QTableWidgetItem *yItem = new QTableWidgetItem(yVal); + + ui->tableWidget_Entries->setItem(i, 0, xItem); + ui->tableWidget_Entries->setItem(i, 1, yItem); + } +} diff --git a/app/rumblegraphviewer.h b/app/rumblegraphviewer.h new file mode 100644 index 0000000..6f8e498 --- /dev/null +++ b/app/rumblegraphviewer.h @@ -0,0 +1,30 @@ +#ifndef RUMBLEGRAPHVIEWER_H +#define RUMBLEGRAPHVIEWER_H + +#include "asset_structs.h" +#include "zonefile.h" +#include + +namespace Ui { +class RumbleGraphViewer; +} + +class RumbleGraphViewer : public QWidget +{ + Q_OBJECT + +public: + explicit RumbleGraphViewer(QWidget *parent = nullptr); + ~RumbleGraphViewer(); + + void SetEntryCount(quint32 aCount); + void SetRumbleGraphFile(const std::shared_ptr aRawFile); + void SetZoneFile(std::shared_ptr aZoneFile); + +private: + Ui::RumbleGraphViewer *ui; + quint32 mEntryCount; + std::shared_ptr mRumbleGraphFile; +}; + +#endif // RUMBLEGRAPHVIEWER_H diff --git a/app/rumblegraphviewer.ui b/app/rumblegraphviewer.ui new file mode 100644 index 0000000..36ab973 --- /dev/null +++ b/app/rumblegraphviewer.ui @@ -0,0 +1,153 @@ + + + RumbleGraphViewer + + + + 0 + 0 + 841 + 457 + + + + + 841 + 457 + + + + Form + + + + + + + Roboto + 16 + true + + + + Rumble Graph File + + + + + + + + + + + + 325 + 398 + + + + + 325 + 16777215 + + + + + Roboto + 9 + + + + Header + + + + + + Entry Count: + + + + + + + false + + + 10000 + + + 0 + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + 400 + 400 + + + + + Roboto + 9 + + + + Entries + + + + + + + 0 + 0 + + + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 0 + + + + + + + + + diff --git a/libs/core/highlighter_rumble.cpp b/libs/core/highlighter_rumble.cpp new file mode 100644 index 0000000..4bbb45c --- /dev/null +++ b/libs/core/highlighter_rumble.cpp @@ -0,0 +1,37 @@ +#include "highlighter_rumble.h" + +Highlighter_Rumble::Highlighter_Rumble(QTextDocument *parent) + : QSyntaxHighlighter(parent) { + HighlightingRule rule; + + // Format for the "RUMBLEGRAPHFILE" header + headerFormat.setForeground(QColor("#569CD6")); + headerFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression(QStringLiteral("^RUMBLEGRAPHFILE\\b")); + rule.format = headerFormat; + highlightingRules.append(rule); + + // Format for line count (second line, typically a single integer) + countFormat.setForeground(QColor("#C586C0")); + rule.pattern = QRegularExpression(QStringLiteral("^\\d+$")); + rule.format = countFormat; + highlightingRules.append(rule); + + // Format for floating-point number pairs (e.g. 0.0000 0.4701) + floatPairFormat.setForeground(QColor("#B5CEA8")); + rule.pattern = QRegularExpression(QStringLiteral("^\\s*-?\\d+\\.\\d+\\s+-?\\d+\\.\\d+\\s*$")); + rule.format = floatPairFormat; + highlightingRules.append(rule); +} + +void Highlighter_Rumble::highlightBlock(const QString &text) { + for (const HighlightingRule &rule : std::as_const(highlightingRules)) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + + setCurrentBlockState(0); +} diff --git a/libs/core/highlighter_rumble.h b/libs/core/highlighter_rumble.h new file mode 100644 index 0000000..2f45664 --- /dev/null +++ b/libs/core/highlighter_rumble.h @@ -0,0 +1,29 @@ +#ifndef HIGHLIGHTER_RUMBLE_H +#define HIGHLIGHTER_RUMBLE_H + +#include +#include + +class Highlighter_Rumble : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + Highlighter_Rumble(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule { + QRegularExpression pattern; + QTextCharFormat format; + }; + QVector highlightingRules; + + QTextCharFormat headerFormat; + QTextCharFormat countFormat; + QTextCharFormat floatPairFormat; +}; + +#endif // HIGHLIGHTER_RUMBLE_H