1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 03:12:36 +01:00

Refactor Viewer to open game data

This commit is contained in:
Daniel Evans 2014-06-08 01:58:49 +01:00
parent 62d2658c2d
commit ad6eda9024
10 changed files with 235 additions and 179 deletions

View File

@ -1,33 +0,0 @@
#pragma once
#ifndef _ARCHIVECONTENTSWIDGET_HPP_
#define _ARCHIVECONTENTSWIDGET_HPP_
#include <QDockWidget>
#include <QListView>
#include <QLineEdit>
#include <QSortFilterProxyModel>
#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

View File

@ -7,8 +7,9 @@ add_executable(rwviewer
main.cpp main.cpp
ViewerWindow.cpp ViewerWindow.cpp
ViewerWidget.cpp ViewerWidget.cpp
ItemListModel.cpp
ItemListWidget.cpp
IMGArchiveModel.cpp IMGArchiveModel.cpp
ArchiveContentsWidget.cpp
DFFFramesTreeModel.cpp DFFFramesTreeModel.cpp
ModelFramesWidget.cpp ModelFramesWidget.cpp
AnimationListModel.cpp AnimationListModel.cpp

View File

@ -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;
}

View File

@ -0,0 +1,30 @@
#ifndef ITEMLISTMODEL_HPP
#define ITEMLISTMODEL_HPP
#include <QAbstractItemModel>
#include <engine/GameWorld.hpp>
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

View File

@ -1,17 +1,18 @@
#include "ArchiveContentsWidget.hpp" #include "ItemListWidget.hpp"
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QHeaderView>
ArchiveContentsWidget::ArchiveContentsWidget(QWidget* parent, Qt::WindowFlags flags) ItemListWidget::ItemListWidget(QWidget* parent, Qt::WindowFlags flags)
: QDockWidget(parent, flags), filter(nullptr), model(nullptr) : QDockWidget(parent, flags), filter(nullptr), model(nullptr)
{ {
setWindowTitle("Archive"); setWindowTitle("Items");
QVBoxLayout* layout = new QVBoxLayout(); QVBoxLayout* layout = new QVBoxLayout();
QWidget* intermediate = new QWidget(); QWidget* intermediate = new QWidget();
searchbox = new QLineEdit(); searchbox = new QLineEdit();
searchbox->setPlaceholderText("Search"); searchbox->setPlaceholderText("Search");
table = new QListView(); table = new QTableView();
layout->addWidget(searchbox); layout->addWidget(searchbox);
layout->addWidget(table); layout->addWidget(table);
intermediate->setLayout(layout); intermediate->setLayout(layout);
@ -19,30 +20,27 @@ ArchiveContentsWidget::ArchiveContentsWidget(QWidget* parent, Qt::WindowFlags fl
filter = new QSortFilterProxyModel; filter = new QSortFilterProxyModel;
table->setModel(filter); table->setModel(filter);
filter->setFilterKeyColumn(-1); // Search all columns
connect(table->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(selectedIndexChanged(QModelIndex))); connect(table->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(selectedIndexChanged(QModelIndex)));
connect(searchbox, SIGNAL(textChanged(QString)), SLOT(setFilter(QString))); connect(searchbox, SIGNAL(textChanged(QString)), SLOT(setFilter(QString)));
} }
void ArchiveContentsWidget::setArchive(const LoaderIMG& archive) void ItemListWidget::worldLoaded(GameWorld *world)
{ {
auto m = new IMGArchiveModel(archive); if ( model ) delete model;
filter->setSourceModel(m); model = new ItemListModel( world, this );
if(model) { filter->setSourceModel( model );
delete model;
}
model = m;
} }
void ArchiveContentsWidget::selectedIndexChanged(const QModelIndex& current) void ItemListWidget::selectedIndexChanged(const QModelIndex& current)
{ {
auto mts = filter->mapToSource(current); auto mts = filter->mapToSource(current);
if(mts.row() < model->getArchive().getAssetCount()) { if( mts.isValid() ) {
auto& f = model->getArchive().getAssetInfoByIndex(mts.row()); emit selectedItemChanged( current.internalId() );
emit selectedFileChanged(f.name);
} }
} }
void ArchiveContentsWidget::setFilter(const QString &f) void ItemListWidget::setFilter(const QString &f)
{ {
filter->setFilterRegExp(QRegExp(f, Qt::CaseInsensitive)); filter->setFilterRegExp(QRegExp(f, Qt::CaseInsensitive));
} }

View File

@ -0,0 +1,34 @@
#pragma once
#ifndef _ITEMLISTWIDGET_HPP_
#define _ITEMLISTWIDGET_HPP_
#include <QDockWidget>
#include <QTableView>
#include <QLineEdit>
#include <QSortFilterProxyModel>
#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

View File

@ -7,8 +7,7 @@
ViewerWidget::ViewerWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) ViewerWidget::ViewerWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
: QGLWidget(parent, shareWidget, f), gworld(nullptr), dummyObject(nullptr), : QGLWidget(parent, shareWidget, f), gworld(nullptr), dummyObject(nullptr),
cmodel(nullptr), canimation(nullptr), viewDistance(1.f), dragging(false), cmodel(nullptr), canimation(nullptr), viewDistance(1.f), dragging(false)
fm(ViewerWidget::UNK)
{ {
} }
@ -21,8 +20,6 @@ void ViewerWidget::initializeGL()
glewExperimental = 1; glewExperimental = 1;
glewInit(); glewInit();
gworld = new GameWorld("");
} }
void ViewerWidget::resizeGL(int w, int h) void ViewerWidget::resizeGL(int w, int h)
@ -38,6 +35,8 @@ void ViewerWidget::paintGL()
glViewport(0, 0, width(), height()); glViewport(0, 0, width(), height());
if( gworld == nullptr ) return;
auto& r = gworld->renderer; auto& r = gworld->renderer;
r.camera.frustum.far = 100.f; r.camera.frustum.far = 100.f;
@ -80,48 +79,9 @@ GameWorld* ViewerWidget::world()
return gworld; return gworld;
} }
void ViewerWidget::showFile(const QString& file) void ViewerWidget::showItem(qint16 item)
{ {
cmodel = nullptr; // TODO: actually show items.
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;
} }
void ViewerWidget::showAnimation(Animation *anim) void ViewerWidget::showAnimation(Animation *anim)
@ -141,9 +101,19 @@ ModelHandle* ViewerWidget::currentModel() const
return cmodel; 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) void ViewerWidget::mousePressEvent(QMouseEvent* e)

View File

@ -30,10 +30,6 @@ class ViewerWidget : public QGLWidget
glm::vec2 dastart; glm::vec2 dastart;
public: public:
enum FileMode {
TXD, DFF, UNK
};
ViewerWidget(QWidget* parent = 0, const QGLWidget* shareWidget = 0, Qt::WindowFlags f = 0); ViewerWidget(QWidget* parent = 0, const QGLWidget* shareWidget = 0, Qt::WindowFlags f = 0);
virtual void initializeGL(); virtual void initializeGL();
@ -42,22 +38,22 @@ public:
virtual void paintGL(); virtual void paintGL();
FileMode fileMode() const;
ModelHandle *currentModel() 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(); GameWorld* world();
public slots: public slots:
void showFile(const QString& file); void showItem(qint16 item);
void showDFF(const QString& file);
void showTXD(const QString& file);
void showAnimation(Animation* anim); void showAnimation(Animation* anim);
signals: signals:
void dataLoaded(GameWorld* world);
void fileOpened(const QString& file); void fileOpened(const QString& file);
protected: protected:
@ -66,9 +62,6 @@ protected:
virtual void mouseReleaseEvent(QMouseEvent*); virtual void mouseReleaseEvent(QMouseEvent*);
virtual void mouseMoveEvent(QMouseEvent*); virtual void mouseMoveEvent(QMouseEvent*);
virtual void wheelEvent(QWheelEvent*); virtual void wheelEvent(QWheelEvent*);
private:
FileMode fm;
}; };
#endif #endif

View File

@ -1,7 +1,7 @@
#include "ViewerWindow.hpp" #include "ViewerWindow.hpp"
#include <engine/GameWorld.hpp> #include <engine/GameWorld.hpp>
#include "ViewerWidget.hpp" #include "ViewerWidget.hpp"
#include "ArchiveContentsWidget.hpp" #include "ItemListWidget.hpp"
#include "ModelFramesWidget.hpp" #include "ModelFramesWidget.hpp"
#include "AnimationListWidget.hpp" #include "AnimationListWidget.hpp"
#include <QMenuBar> #include <QMenuBar>
@ -10,7 +10,7 @@
#include <QSettings> #include <QSettings>
#include <fstream> #include <fstream>
static int MaxRecentArchives = 5; static int MaxRecentGames = 5;
ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags): QMainWindow(parent, flags) 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(); viewer = new ViewerWidget();
this->setCentralWidget(viewer); this->setCentralWidget(viewer);
archivewidget = new ArchiveContentsWidget; itemsWidget = new ItemListWidget;
archivewidget->setObjectName("archivewidget"); itemsWidget->setObjectName("archivewidget");
this->addDockWidget(Qt::LeftDockWidgetArea, archivewidget); this->addDockWidget(Qt::LeftDockWidgetArea, itemsWidget);
frameswidget = new ModelFramesWidget; frameswidget = new ModelFramesWidget;
frameswidget->setObjectName("frameswidget"); frameswidget->setObjectName("frameswidget");
@ -33,13 +33,16 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags): QMainWindow(
QMenuBar* mb = this->menuBar(); QMenuBar* mb = this->menuBar();
QMenu* file = mb->addMenu("&File"); QMenu* file = mb->addMenu("&File");
file->addAction("Open &Archive", this, SLOT(openArchive()));
file->addAction("Open &Game", this, SLOT(loadGame()));
file->addSeparator(); file->addSeparator();
for(int i = 0; i < MaxRecentArchives; ++i) { for(int i = 0; i < MaxRecentGames; ++i) {
QAction* r = file->addAction(""); QAction* r = file->addAction("");
recentArchives.append(r); recentGames.append(r);
connect(r, SIGNAL(triggered()), SLOT(openRecent())); connect(r, SIGNAL(triggered()), SLOT(openRecent()));
} }
recentSep = file->addSeparator(); recentSep = file->addSeparator();
auto ex = file->addAction("E&xit"); auto ex = file->addAction("E&xit");
ex->setShortcut(QKeySequence::Quit); ex->setShortcut(QKeySequence::Quit);
@ -48,36 +51,11 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags): QMainWindow(
QMenu* anim = mb->addMenu("&Animation"); QMenu* anim = mb->addMenu("&Animation");
anim->addAction("Load &Animations", this, SLOT(openAnimations())); 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(animationswidget, SIGNAL(selectedAnimationChanged(Animation*)), viewer, SLOT(showAnimation(Animation*)));
connect(viewer, SIGNAL(fileOpened(QString)), SLOT(openFileChanged(QString)));
updateRecentArchives(); updateRecentGames();
}
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();
} }
void ViewerWindow::showEvent(QShowEvent*) void ViewerWindow::showEvent(QShowEvent*)
@ -99,14 +77,6 @@ void ViewerWindow::closeEvent(QCloseEvent* event)
QMainWindow::closeEvent(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() void ViewerWindow::openAnimations()
{ {
QFileDialog dialog(this, "Open Animations", QDir::homePath(), "IFP Animations (*.ifp)"); 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); QString dir = QFileDialog::getExistingDirectory(
if(viewer->fileMode() == ViewerWidget::DFF) { this, tr("Open Directory"),
frameswidget->setModel(viewer->currentModel()); QDir::homePath(),
} QFileDialog::ShowDirsOnly
else { | QFileDialog::DontResolveSymlinks);
frameswidget->setModel(nullptr);
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() void ViewerWindow::openRecent()
{ {
QAction* r = qobject_cast< QAction* >(sender()); QAction* r = qobject_cast< QAction* >(sender());
if(r) { if(r) {
openArchive(r->data().toString()); loadGame( r->data().toString() );
} }
} }
void ViewerWindow::updateRecentArchives() void ViewerWindow::updateRecentGames()
{ {
QSettings settings("OpenRW", "rwviewer"); 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()) { if(i < recent.size()) {
QString fnm(QFileInfo(recent[i]).fileName()); QString fnm(QFileInfo(recent[i]).fileName());
recentArchives[i]->setText(tr("&%1 - %2").arg(i).arg(fnm)); recentGames[i]->setText(tr("&%1 - %2").arg(i).arg(fnm));
recentArchives[i]->setData(recent[i]); recentGames[i]->setData(recent[i]);
recentArchives[i]->setVisible(true); recentGames[i]->setVisible(true);
} }
else { else {
recentArchives[i]->setVisible(false); recentGames[i]->setVisible(false);
} }
} }

View File

@ -4,7 +4,7 @@
#include <QMainWindow> #include <QMainWindow>
class ModelFramesWidget; class ModelFramesWidget;
class ArchiveContentsWidget; class ItemListWidget;
class AnimationListWidget; class AnimationListWidget;
class ViewerWidget; class ViewerWidget;
@ -13,14 +13,18 @@ class ViewerWindow : public QMainWindow
Q_OBJECT Q_OBJECT
ViewerWidget* viewer; ViewerWidget* viewer;
ArchiveContentsWidget* archivewidget; ItemListWidget* itemsWidget;
ModelFramesWidget* frameswidget; ModelFramesWidget* frameswidget;
AnimationListWidget* animationswidget; AnimationListWidget* animationswidget;
public: public:
ViewerWindow(QWidget* parent = 0, Qt::WindowFlags flags = 0); 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 showEvent(QShowEvent*);
@ -28,20 +32,21 @@ public:
public slots: public slots:
void openArchive();
void openAnimations(); void openAnimations();
void loadGame();
void loadGame( const QString& path );
private slots: private slots:
void openFileChanged(const QString& name);
void openRecent(); void openRecent();
private: private:
QList<QAction*> recentArchives; QList<QAction*> recentGames;
QAction* recentSep; QAction* recentSep;
void updateRecentArchives(); void updateRecentGames();
}; };
#endif #endif