1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-03 00:59:47 +02: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
ViewerWindow.cpp
ViewerWidget.cpp
ItemListModel.cpp
ItemListWidget.cpp
IMGArchiveModel.cpp
ArchiveContentsWidget.cpp
DFFFramesTreeModel.cpp
ModelFramesWidget.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 <QHeaderView>
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));
}

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)
: 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)

View File

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

View File

@ -1,7 +1,7 @@
#include "ViewerWindow.hpp"
#include <engine/GameWorld.hpp>
#include "ViewerWidget.hpp"
#include "ArchiveContentsWidget.hpp"
#include "ItemListWidget.hpp"
#include "ModelFramesWidget.hpp"
#include "AnimationListWidget.hpp"
#include <QMenuBar>
@ -10,7 +10,7 @@
#include <QSettings>
#include <fstream>
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);
}
}

View File

@ -4,7 +4,7 @@
#include <QMainWindow>
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<QAction*> recentArchives;
QList<QAction*> recentGames;
QAction* recentSep;
void updateRecentArchives();
void updateRecentGames();
};
#endif