From ad6eda90242a7ac23b519ab99794e1dcd220ba3f Mon Sep 17 00:00:00 2001 From: Daniel Evans Date: Sun, 8 Jun 2014 01:58:49 +0100 Subject: [PATCH] Refactor Viewer to open game data --- rwviewer/ArchiveContentsWidget.hpp | 33 ------ rwviewer/CMakeLists.txt | 3 +- rwviewer/ItemListModel.cpp | 70 ++++++++++++ rwviewer/ItemListModel.hpp | 30 +++++ ...eContentsWidget.cpp => ItemListWidget.cpp} | 30 +++-- rwviewer/ItemListWidget.hpp | 34 ++++++ rwviewer/ViewerWidget.cpp | 64 +++-------- rwviewer/ViewerWidget.hpp | 21 ++-- rwviewer/ViewerWindow.cpp | 106 ++++++++---------- rwviewer/ViewerWindow.hpp | 23 ++-- 10 files changed, 235 insertions(+), 179 deletions(-) delete mode 100644 rwviewer/ArchiveContentsWidget.hpp create mode 100644 rwviewer/ItemListModel.cpp create mode 100644 rwviewer/ItemListModel.hpp rename rwviewer/{ArchiveContentsWidget.cpp => ItemListWidget.cpp} (53%) create mode 100644 rwviewer/ItemListWidget.hpp diff --git a/rwviewer/ArchiveContentsWidget.hpp b/rwviewer/ArchiveContentsWidget.hpp deleted file mode 100644 index 78faacce..00000000 --- a/rwviewer/ArchiveContentsWidget.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#ifndef _ARCHIVECONTENTSWIDGET_HPP_ -#define _ARCHIVECONTENTSWIDGET_HPP_ -#include -#include -#include -#include -#include "IMGArchiveModel.hpp" - -class ArchiveContentsWidget : public QDockWidget -{ - Q_OBJECT - - QSortFilterProxyModel* filter; - IMGArchiveModel* model; - QListView* table; - QLineEdit* searchbox; - -public: - ArchiveContentsWidget(QWidget* parent = 0, Qt::WindowFlags flags = 0); - - void setArchive(const LoaderIMG& archive); - -signals: - void selectedFileChanged(const QString& file); - -public slots: - void selectedIndexChanged(const QModelIndex& current); - - void setFilter(const QString& f); -}; - -#endif diff --git a/rwviewer/CMakeLists.txt b/rwviewer/CMakeLists.txt index ec8048e1..b3c3a83a 100644 --- a/rwviewer/CMakeLists.txt +++ b/rwviewer/CMakeLists.txt @@ -7,8 +7,9 @@ add_executable(rwviewer main.cpp ViewerWindow.cpp ViewerWidget.cpp + ItemListModel.cpp + ItemListWidget.cpp IMGArchiveModel.cpp - ArchiveContentsWidget.cpp DFFFramesTreeModel.cpp ModelFramesWidget.cpp AnimationListModel.cpp diff --git a/rwviewer/ItemListModel.cpp b/rwviewer/ItemListModel.cpp new file mode 100644 index 00000000..0e5cfd83 --- /dev/null +++ b/rwviewer/ItemListModel.cpp @@ -0,0 +1,70 @@ +#include "ItemListModel.hpp" + +qint16 ItemListModel::getIDOf(unsigned int row) const +{ + unsigned int j = 0; + if( row < world()->objectTypes.size() ) { + auto it = world()->objectTypes.begin(); + while (j < row) { + it++; j++; + if( it == world()->objectTypes.end() ) return -1; + } + return it->first; + } + return -1; + + row -= world()->objectTypes.size(); + if( row < world()->vehicleTypes.size() ) { + auto it = world()->vehicleTypes.begin(); + while (j < row) { + it++; j++; + if( it == world()->vehicleTypes.end() ) return -1; + } + return it->first; + } + return -1; +} + +ItemListModel::ItemListModel(GameWorld *world, QObject *parent) : + QAbstractTableModel(parent), _world( world ) +{ +} + +int ItemListModel::rowCount(const QModelIndex &parent) const +{ + return _world->objectTypes.size(); +} + +int ItemListModel::columnCount(const QModelIndex &parent) const +{ + return 2; +} + +QVariant ItemListModel::data(const QModelIndex &index, int role) const +{ + if ( role == Qt::DisplayRole ) { + qint16 id = getIDOf(index.row()); + if( id == -1 ) return QVariant::Invalid; + if( index.column() == 0 ) { + return id; + } + else if ( index.column() == 1 ) { + return QString::fromStdString( + world()->objectTypes[id]->modelName); + } + } + return QVariant::Invalid; +} + +QVariant ItemListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(role == Qt::DisplayRole && orientation == Qt::Horizontal) { + if(section == 0) { + return "ID"; + } + if(section == 1) { + return "Model"; + } + } + return QVariant::Invalid; +} diff --git a/rwviewer/ItemListModel.hpp b/rwviewer/ItemListModel.hpp new file mode 100644 index 00000000..385058d7 --- /dev/null +++ b/rwviewer/ItemListModel.hpp @@ -0,0 +1,30 @@ +#ifndef ITEMLISTMODEL_HPP +#define ITEMLISTMODEL_HPP + +#include + +#include + +class ItemListModel : public QAbstractTableModel +{ + Q_OBJECT + + GameWorld* _world; + + qint16 getIDOf(unsigned int row ) const; + +public: + explicit ItemListModel(GameWorld* _world, QObject *parent = 0); + + GameWorld* world() const { return _world; } + + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; + + virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; + + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; +}; + +#endif // ITEMLISTMODEL_HPP diff --git a/rwviewer/ArchiveContentsWidget.cpp b/rwviewer/ItemListWidget.cpp similarity index 53% rename from rwviewer/ArchiveContentsWidget.cpp rename to rwviewer/ItemListWidget.cpp index f8c08b01..f045daf8 100644 --- a/rwviewer/ArchiveContentsWidget.cpp +++ b/rwviewer/ItemListWidget.cpp @@ -1,17 +1,18 @@ -#include "ArchiveContentsWidget.hpp" +#include "ItemListWidget.hpp" #include +#include -ArchiveContentsWidget::ArchiveContentsWidget(QWidget* parent, Qt::WindowFlags flags) +ItemListWidget::ItemListWidget(QWidget* parent, Qt::WindowFlags flags) : QDockWidget(parent, flags), filter(nullptr), model(nullptr) { - setWindowTitle("Archive"); + setWindowTitle("Items"); QVBoxLayout* layout = new QVBoxLayout(); QWidget* intermediate = new QWidget(); searchbox = new QLineEdit(); searchbox->setPlaceholderText("Search"); - table = new QListView(); + table = new QTableView(); layout->addWidget(searchbox); layout->addWidget(table); intermediate->setLayout(layout); @@ -19,30 +20,27 @@ ArchiveContentsWidget::ArchiveContentsWidget(QWidget* parent, Qt::WindowFlags fl filter = new QSortFilterProxyModel; table->setModel(filter); + filter->setFilterKeyColumn(-1); // Search all columns connect(table->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(selectedIndexChanged(QModelIndex))); connect(searchbox, SIGNAL(textChanged(QString)), SLOT(setFilter(QString))); } -void ArchiveContentsWidget::setArchive(const LoaderIMG& archive) +void ItemListWidget::worldLoaded(GameWorld *world) { - auto m = new IMGArchiveModel(archive); - filter->setSourceModel(m); - if(model) { - delete model; - } - model = m; + if ( model ) delete model; + model = new ItemListModel( world, this ); + filter->setSourceModel( model ); } -void ArchiveContentsWidget::selectedIndexChanged(const QModelIndex& current) +void ItemListWidget::selectedIndexChanged(const QModelIndex& current) { auto mts = filter->mapToSource(current); - if(mts.row() < model->getArchive().getAssetCount()) { - auto& f = model->getArchive().getAssetInfoByIndex(mts.row()); - emit selectedFileChanged(f.name); + if( mts.isValid() ) { + emit selectedItemChanged( current.internalId() ); } } -void ArchiveContentsWidget::setFilter(const QString &f) +void ItemListWidget::setFilter(const QString &f) { filter->setFilterRegExp(QRegExp(f, Qt::CaseInsensitive)); } diff --git a/rwviewer/ItemListWidget.hpp b/rwviewer/ItemListWidget.hpp new file mode 100644 index 00000000..0f9f0a05 --- /dev/null +++ b/rwviewer/ItemListWidget.hpp @@ -0,0 +1,34 @@ +#pragma once +#ifndef _ITEMLISTWIDGET_HPP_ +#define _ITEMLISTWIDGET_HPP_ +#include +#include +#include +#include +#include "ItemListModel.hpp" + +class ItemListWidget : public QDockWidget +{ + Q_OBJECT + + QSortFilterProxyModel* filter; + ItemListModel* model; + QTableView* table; + QLineEdit* searchbox; + +public: + ItemListWidget(QWidget* parent = 0, Qt::WindowFlags flags = 0); + +signals: + void selectedItemChanged(const qint16 id); + +public slots: + + void worldLoaded(GameWorld* world); + + void selectedIndexChanged(const QModelIndex& current); + + void setFilter(const QString& f); +}; + +#endif diff --git a/rwviewer/ViewerWidget.cpp b/rwviewer/ViewerWidget.cpp index 5d854d21..be84e6c1 100644 --- a/rwviewer/ViewerWidget.cpp +++ b/rwviewer/ViewerWidget.cpp @@ -7,8 +7,7 @@ ViewerWidget::ViewerWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) : QGLWidget(parent, shareWidget, f), gworld(nullptr), dummyObject(nullptr), - cmodel(nullptr), canimation(nullptr), viewDistance(1.f), dragging(false), - fm(ViewerWidget::UNK) + cmodel(nullptr), canimation(nullptr), viewDistance(1.f), dragging(false) { } @@ -21,8 +20,6 @@ void ViewerWidget::initializeGL() glewExperimental = 1; glewInit(); - - gworld = new GameWorld(""); } void ViewerWidget::resizeGL(int w, int h) @@ -38,6 +35,8 @@ void ViewerWidget::paintGL() glViewport(0, 0, width(), height()); + if( gworld == nullptr ) return; + auto& r = gworld->renderer; r.camera.frustum.far = 100.f; @@ -80,48 +79,9 @@ GameWorld* ViewerWidget::world() return gworld; } -void ViewerWidget::showFile(const QString& file) +void ViewerWidget::showItem(qint16 item) { - cmodel = nullptr; - currentFile = file; - QString low = file.toLower(); - if(low.endsWith("dff")) { - showDFF(file); - } - else if(low.endsWith("txd")) { - showTXD(file); - } - emit fileOpened(file); -} - -void ViewerWidget::showDFF(const QString& file) -{ - gworld->gameData.loadDFF(file.toStdString()); - QString basename(file.left(file.size()-4)); - // HACK this - gworld->gameData.loadTXD((basename+".txd").toStdString()); - auto mit = gworld->gameData.models.find(basename.toStdString()); - if(mit != gworld->gameData.models.end()) { - // TODO better error handling - if(dummyObject) delete dummyObject; - cmodel = mit->second; - dummyObject = new GameObject(gworld, glm::vec3(), glm::quat(), cmodel); - float radius = 0.f; - for(auto& g - : cmodel->model->geometries) { - radius = std::max( - radius, - glm::length(g->geometryBounds.center)+g->geometryBounds.radius); - } - radius *= 4.f; - viewDistance = (radius/2.f) / tan(gworld->renderer.camera.frustum.aspectRatio/2.f); - } - fm = ViewerWidget::DFF; -} - -void ViewerWidget::showTXD(const QString& file) -{ - fm = ViewerWidget::TXD; + // TODO: actually show items. } void ViewerWidget::showAnimation(Animation *anim) @@ -141,9 +101,19 @@ ModelHandle* ViewerWidget::currentModel() const return cmodel; } -ViewerWidget::FileMode ViewerWidget::fileMode() const +void ViewerWidget::setGamePath(const std::string &path) { - return fm; + if( gworld ) delete gworld; + gworld = new GameWorld(path); + gworld->gameData.load(); + + for(auto it = gworld->gameData.ideLocations.begin(); + it != gworld->gameData.ideLocations.end(); + ++it) { + gworld->defineItems(it->second); + } + + emit dataLoaded(gworld); } void ViewerWidget::mousePressEvent(QMouseEvent* e) diff --git a/rwviewer/ViewerWidget.hpp b/rwviewer/ViewerWidget.hpp index 19504638..8927c6d0 100644 --- a/rwviewer/ViewerWidget.hpp +++ b/rwviewer/ViewerWidget.hpp @@ -29,11 +29,7 @@ class ViewerWidget : public QGLWidget QPointF dstart; glm::vec2 dastart; public: - - enum FileMode { - TXD, DFF, UNK - }; - + ViewerWidget(QWidget* parent = 0, const QGLWidget* shareWidget = 0, Qt::WindowFlags f = 0); virtual void initializeGL(); @@ -41,23 +37,23 @@ public: virtual void resizeGL(int w, int h); virtual void paintGL(); - - FileMode fileMode() const; - + ModelHandle *currentModel() const; + // TODO: Move this into the main window or elsewhere, doesn't really belong here. + void setGamePath(const std::string& path); GameWorld* world(); public slots: - void showFile(const QString& file); - void showDFF(const QString& file); - void showTXD(const QString& file); + void showItem(qint16 item); void showAnimation(Animation* anim); signals: + void dataLoaded(GameWorld* world); + void fileOpened(const QString& file); protected: @@ -66,9 +62,6 @@ protected: virtual void mouseReleaseEvent(QMouseEvent*); virtual void mouseMoveEvent(QMouseEvent*); virtual void wheelEvent(QWheelEvent*); - -private: - FileMode fm; }; #endif diff --git a/rwviewer/ViewerWindow.cpp b/rwviewer/ViewerWindow.cpp index 530f7baf..7ca30fe6 100644 --- a/rwviewer/ViewerWindow.cpp +++ b/rwviewer/ViewerWindow.cpp @@ -1,7 +1,7 @@ #include "ViewerWindow.hpp" #include #include "ViewerWidget.hpp" -#include "ArchiveContentsWidget.hpp" +#include "ItemListWidget.hpp" #include "ModelFramesWidget.hpp" #include "AnimationListWidget.hpp" #include @@ -10,7 +10,7 @@ #include #include -static int MaxRecentArchives = 5; +static int MaxRecentGames = 5; ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags): QMainWindow(parent, flags) { @@ -19,9 +19,9 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags): QMainWindow( viewer = new ViewerWidget(); this->setCentralWidget(viewer); - archivewidget = new ArchiveContentsWidget; - archivewidget->setObjectName("archivewidget"); - this->addDockWidget(Qt::LeftDockWidgetArea, archivewidget); + itemsWidget = new ItemListWidget; + itemsWidget->setObjectName("archivewidget"); + this->addDockWidget(Qt::LeftDockWidgetArea, itemsWidget); frameswidget = new ModelFramesWidget; frameswidget->setObjectName("frameswidget"); @@ -33,13 +33,16 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags): QMainWindow( QMenuBar* mb = this->menuBar(); QMenu* file = mb->addMenu("&File"); - file->addAction("Open &Archive", this, SLOT(openArchive())); + + file->addAction("Open &Game", this, SLOT(loadGame())); + file->addSeparator(); - for(int i = 0; i < MaxRecentArchives; ++i) { + for(int i = 0; i < MaxRecentGames; ++i) { QAction* r = file->addAction(""); - recentArchives.append(r); + recentGames.append(r); connect(r, SIGNAL(triggered()), SLOT(openRecent())); } + recentSep = file->addSeparator(); auto ex = file->addAction("E&xit"); ex->setShortcut(QKeySequence::Quit); @@ -48,36 +51,11 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags): QMainWindow( QMenu* anim = mb->addMenu("&Animation"); anim->addAction("Load &Animations", this, SLOT(openAnimations())); - connect(archivewidget, SIGNAL(selectedFileChanged(QString)), viewer, SLOT(showFile(QString))); + connect(itemsWidget, SIGNAL(selectedItemChanged(qint16)), viewer, SLOT(showItem(qint16))); + connect(viewer, SIGNAL(dataLoaded(GameWorld*)), itemsWidget, SLOT(worldLoaded(GameWorld*))); connect(animationswidget, SIGNAL(selectedAnimationChanged(Animation*)), viewer, SLOT(showAnimation(Animation*))); - connect(viewer, SIGNAL(fileOpened(QString)), SLOT(openFileChanged(QString))); - updateRecentArchives(); -} - -void ViewerWindow::openArchive(const QString& name) -{ - QString rname = name; - QString lower = name.toLower(); - if(lower.endsWith(".img")) { - rname = rname.left(rname.size()-4); - } - - LoaderIMG ld; - ld.load(rname.toStdString()); - - viewer->world()->gameData.loadIMG(rname.toStdString()); - - archivewidget->setArchive(ld); - - QSettings settings("OpenRW", "rwviewer"); - QStringList recent = settings.value("recentArchives").toStringList(); - recent.removeAll(name); - recent.prepend(name); - while(recent.size() > MaxRecentArchives) recent.removeLast(); - settings.setValue("recentArchives", recent); - - updateRecentArchives(); + updateRecentGames(); } void ViewerWindow::showEvent(QShowEvent*) @@ -99,14 +77,6 @@ void ViewerWindow::closeEvent(QCloseEvent* event) QMainWindow::closeEvent(event); } -void ViewerWindow::openArchive() -{ - QFileDialog dialog(this, "Open Archive", QDir::homePath(), "IMG Archives (*.img)"); - if(dialog.exec()) { - openArchive(dialog.selectedFiles().at(0)); - } -} - void ViewerWindow::openAnimations() { QFileDialog dialog(this, "Open Animations", QDir::homePath(), "IFP Animations (*.ifp)"); @@ -136,39 +106,57 @@ void ViewerWindow::openAnimations() } } -void ViewerWindow::openFileChanged(const QString& name) +void ViewerWindow::loadGame() { - setWindowTitle(name); - if(viewer->fileMode() == ViewerWidget::DFF) { - frameswidget->setModel(viewer->currentModel()); - } - else { - frameswidget->setModel(nullptr); + QString dir = QFileDialog::getExistingDirectory( + this, tr("Open Directory"), + QDir::homePath(), + QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks); + + if( dir.size() > 0 ) loadGame( dir ); +} + +void ViewerWindow::loadGame(const QString &path) +{ + QDir gameDir( path ); + + if( gameDir.exists() && path.size() > 0 ) { + viewer->setGamePath( gameDir.absolutePath().toStdString() ); } + + QSettings settings("OpenRW", "rwviewer"); + QStringList recent = settings.value("recentGames").toStringList(); + recent.removeAll( path ); + recent.prepend( path ); + while(recent.size() > MaxRecentGames) recent.removeLast(); + settings.setValue("recentGames", recent); + + updateRecentGames(); } void ViewerWindow::openRecent() { QAction* r = qobject_cast< QAction* >(sender()); if(r) { - openArchive(r->data().toString()); + loadGame( r->data().toString() ); } } -void ViewerWindow::updateRecentArchives() +void ViewerWindow::updateRecentGames() { QSettings settings("OpenRW", "rwviewer"); - QStringList recent = settings.value("recentArchives").toStringList(); + QStringList recent = settings.value("recentGames").toStringList(); - for(int i = 0; i < MaxRecentArchives; ++i) { + for(int i = 0; i < MaxRecentGames; ++i) { if(i < recent.size()) { QString fnm(QFileInfo(recent[i]).fileName()); - recentArchives[i]->setText(tr("&%1 - %2").arg(i).arg(fnm)); - recentArchives[i]->setData(recent[i]); - recentArchives[i]->setVisible(true); + recentGames[i]->setText(tr("&%1 - %2").arg(i).arg(fnm)); + recentGames[i]->setData(recent[i]); + recentGames[i]->setVisible(true); } else { - recentArchives[i]->setVisible(false); + recentGames[i]->setVisible(false); } } diff --git a/rwviewer/ViewerWindow.hpp b/rwviewer/ViewerWindow.hpp index 0d5ad952..31702cc5 100644 --- a/rwviewer/ViewerWindow.hpp +++ b/rwviewer/ViewerWindow.hpp @@ -4,7 +4,7 @@ #include class ModelFramesWidget; -class ArchiveContentsWidget; +class ItemListWidget; class AnimationListWidget; class ViewerWidget; @@ -13,35 +13,40 @@ class ViewerWindow : public QMainWindow Q_OBJECT ViewerWidget* viewer; - ArchiveContentsWidget* archivewidget; + ItemListWidget* itemsWidget; ModelFramesWidget* frameswidget; AnimationListWidget* animationswidget; public: ViewerWindow(QWidget* parent = 0, Qt::WindowFlags flags = 0); - void openArchive(const QString& name); - + /** + * @brief openGame Loads a game's dat file. + * @param datFile + */ + void openGame(const QString& datFile); + virtual void showEvent(QShowEvent*); virtual void closeEvent(QCloseEvent*); public slots: - void openArchive(); - void openAnimations(); + void loadGame(); + + void loadGame( const QString& path ); + private slots: - void openFileChanged(const QString& name); void openRecent(); private: - QList recentArchives; + QList recentGames; QAction* recentSep; - void updateRecentArchives(); + void updateRecentGames(); }; #endif