diff --git a/aufgabe/proposal.pdf b/aufgabe/proposal.pdf index f8c478a..30d755e 100644 Binary files a/aufgabe/proposal.pdf and b/aufgabe/proposal.pdf differ diff --git a/src/field3d.cpp b/src/field3d.cpp index 2c0bccd..b77b2d8 100644 --- a/src/field3d.cpp +++ b/src/field3d.cpp @@ -20,17 +20,39 @@ #include "field3d.h" #include +#include +#include #include +#include + #include +template +static T clip(T min, T max, T val) { + if (val < min) return min; + if (val > max) return max; + return val; +} + +template +static T rotate(T angle, T bound = 360) { + while (angle < 0) angle += bound; + while (angle > bound) angle -= bound; + return angle; +} + namespace toruschess { Field3D::Field3D(Game *game, QWidget *parent) : QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba), parent), m_game(game), m_lib(new PieceLibrary(this)), + m_boardMode(PLANE), m_figureMode(FIG3D), m_textureBuffer(0), m_textureID(0), - m_camDist(10) ,m_camRotX(45), m_camRotY(0), m_camRotZ(0) { + m_camDist(5) ,m_camRotX(45), m_camRotY(0), m_camRotZ(0), + m_originX(0), m_originY(0), m_mouseLastX(0), m_mouseLastY(0), + m_skySphere(0), m_skyTextureID(0), + m_pickTextureID(0) { qDebug("Field3d::Field3D"); for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) m_marked[x][y] = false; m_lib->setSize(m_textureSize / 8, m_textureSize / 8); @@ -39,6 +61,8 @@ namespace toruschess { Field3D::~Field3D() { qDebug("Field3d::~Field3D"); freeTexture(); + + if (m_skySphere) gluDeleteQuadric(m_skySphere); } void Field3D::markMoves(const QList &moves) { @@ -57,11 +81,33 @@ namespace toruschess { void Field3D::initializeGL() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); +// glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_COLOR_MATERIAL); + { + const GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 }, + inv[] = { 0.0, 0.0, 0.0, 0.0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, white); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, inv); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, inv); + glLightfv(GL_LIGHT0, GL_AMBIENT, white); + glLightfv(GL_LIGHT0, GL_DIFFUSE, inv); + } + + glFogi(GL_FOG_MODE, GL_EXP2); + glFogf(GL_FOG_DENSITY, 1/50.0); + + m_skySphere = gluNewQuadric(); + gluQuadricTexture(m_skySphere, GL_TRUE); + createTexture(); + connect(m_game, SIGNAL(updated()), this, SLOT(fieldUpdated())); + + m_pickBuffer = new QGLPixelBuffer(QSize(1024, 1024)); } void Field3D::resizeGL(int w, int h) { @@ -69,59 +115,137 @@ namespace toruschess { glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluPerspective(90.0, double(w)/h, 1, 1000); + gluPerspective(90.0, double(w)/h, 0.01, 1000); updateCam(); } void Field3D::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - + glEnable(GL_TEXTURE_2D); // m_lib->paint_pawn(); // return; - glBindTexture(GL_TEXTURE_2D, m_textureID); - glEnable(GL_TEXTURE_2D); - { - const int numc = 16, numt = 16; - const double rad1 = 4.0, rad2 = 2.0; - int i, j, k; - double s, t, x, y, z, twopi; + if (m_boardMode == TORUS) { + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glBindTexture(GL_TEXTURE_2D, m_skyTextureID); + gluSphere(m_skySphere, 256, 64, 64); + glEnable(GL_LIGHTING); - twopi = 2 * M_PI; - for (i = 0; i < numc; i++) { - glBegin(GL_QUAD_STRIP); - for (j = 0; j <= numt; j++) { - for (k = 1; k >= 0; k--) { - s = (i + k) % numc + 0.5; - t = j % numt; - - x = (rad1+rad2*cos(s*twopi/numc))*cos(t*twopi/numt); - y = (rad1+rad2*cos(s*twopi/numc))*sin(t*twopi/numt); - z = rad2 * sin(s * twopi / numc); - glTexCoord2f(double(i+k)/numc, double(j)/numt); - glVertex3f(x, z, y); + double ox = 2.0*(m_originX/(double)m_textureSize), oy = 2.0*(m_originY/(double)m_textureSize); + glBindTexture(GL_TEXTURE_2D, m_textureID); + { + const int numc = 64, numt = 64; + const double rad1 = 4.0, rad2 = 2.0; + int i, j, k; + double s, t, x, y, z, twopi; + + twopi = 2 * M_PI; + for (i = 0; i < numc; i++) { + glBegin(GL_QUAD_STRIP); + for (j = 0; j <= numt; j++) { + for (k = 1; k >= 0; k--) { + s = (i + k) % numc + 0.5; + t = j % numt; + + x = (rad1+rad2*cos(s*twopi/numc))*cos(t*twopi/numt); + y = (rad1+rad2*cos(s*twopi/numc))*sin(t*twopi/numt); + z = rad2 * sin(s * twopi / numc); + glTexCoord2f(oy+double(i+k)/numc, ox+double(j)/numt); + glVertex3f(x, z, y); + } } + glEnd(); } - glEnd(); } + } else { + const int repeat = 10; + double ox = -2.0*(m_originX/(double)m_textureSize), oy = 2.0*(m_originY/(double)m_textureSize); + glEnable(GL_FOG); + glBindTexture(GL_TEXTURE_2D, m_textureID); + glBegin(GL_QUADS); + glTexCoord2f(-repeat+ox, repeat+oy); glVertex3f(-10*repeat, 0, -10*repeat); + glTexCoord2f(-repeat+ox, -repeat+oy); glVertex3f(-10*repeat, 0, 10*repeat); + glTexCoord2f( repeat+ox, -repeat+oy); glVertex3f( 10*repeat, 0, 10*repeat); + glTexCoord2f( repeat+ox, repeat+oy); glVertex3f( 10*repeat, 0, -10*repeat); + glEnd(); } glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); - return; + } + + Pos Field3D::findPos(int mx, int my) { + m_pickBuffer->makeCurrent(); - glBindTexture(GL_TEXTURE_2D, m_textureID); + glClearColor(0.0, 0.0, 0.0, 0.0); + glEnable(GL_DEPTH_TEST); + + glViewport(0, 0, 1024, 1024); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(90.0, double(width())/height(), 0.01, 1000); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - glTexCoord2f(0, 1); glVertex3f(-10, 0, -10); - glTexCoord2f(0, 0); glVertex3f(-10, 0, 10); - glTexCoord2f(1, 0); glVertex3f( 10, 0, 10); - glTexCoord2f(1, 1); glVertex3f( 10, 0, -10); - glEnd(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glTranslatef(0, 0, -m_camDist); + glRotatef(m_camRotX,1,0,0); + glRotatef(m_camRotY,0,1,0); + glRotatef(m_camRotZ,0,0,1); + + if (m_boardMode == TORUS) { + double ox = 2.0*(m_originX/(double)m_textureSize), oy = 2.0*(m_originY/(double)m_textureSize); + glBindTexture(GL_TEXTURE_2D, m_pickTextureID); + { + const int numc = 64, numt = 64; + const double rad1 = 4.0, rad2 = 2.0; + int i, j, k; + double s, t, x, y, z, twopi; + + twopi = 2 * M_PI; + for (i = 0; i < numc; i++) { + glBegin(GL_QUAD_STRIP); + for (j = 0; j <= numt; j++) { + for (k = 1; k >= 0; k--) { + s = (i + k) % numc + 0.5; + t = j % numt; + + x = (rad1+rad2*cos(s*twopi/numc))*cos(t*twopi/numt); + y = (rad1+rad2*cos(s*twopi/numc))*sin(t*twopi/numt); + z = rad2 * sin(s * twopi / numc); + glTexCoord2f(oy+double(i+k)/numc, ox+double(j)/numt); + glVertex3f(x, z, y); + } + } + glEnd(); + } + } + } else { + const int repeat = 10; + double ox = -2.0*(m_originX/(double)m_textureSize), oy = 2.0*(m_originY/(double)m_textureSize); + glBindTexture(GL_TEXTURE_2D, m_pickTextureID); + glBegin(GL_QUADS); + glTexCoord2f(-repeat+ox, repeat+oy); glVertex3f(-10*repeat, 0, -10*repeat); + glTexCoord2f(-repeat+ox, -repeat+oy); glVertex3f(-10*repeat, 0, 10*repeat); + glTexCoord2f( repeat+ox, -repeat+oy); glVertex3f( 10*repeat, 0, 10*repeat); + glTexCoord2f( repeat+ox, repeat+oy); glVertex3f( 10*repeat, 0, -10*repeat); + glEnd(); + } glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); + + m_pickBuffer->doneCurrent(); + QImage i = m_pickBuffer->toImage(); + QRgb col = i.pixel((1024*mx)/width(), (1024*my)/height()); + qDebug << QColor(col); + return Pos(qRed(col), qGreen(col)); } + void Field3D::updateCam() { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -130,24 +254,45 @@ namespace toruschess { glRotatef(m_camRotX,1,0,0); glRotatef(m_camRotY,0,1,0); glRotatef(m_camRotZ,0,0,1); - + updateGL(); } void Field3D::createTexture() { freeTexture(); +// m_textureBuffer = new QGLPixelBuffer(QSize(m_textureSize, m_textureSize), QGLFormat::defaultFormat(), this); m_textureBuffer = new QImage(QSize(m_textureSize, m_textureSize), QImage::Format_ARGB32_Premultiplied); - m_textureBuffer->fill(Qt::black); - - glBindTexture(GL_TEXTURE_2D, m_textureID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +// m_textureID = m_textureBuffer->generateDynamicTexture(); updateTexture(); - - m_textureID = bindTexture(*m_textureBuffer); + + { + QImage *pickimage = new QImage(QSize(m_textureSize, m_textureSize), QImage::Format_ARGB32_Premultiplied); + pickimage->fill(Qt::black); + QPainter pt(pickimage); + int pieceSize = m_textureSize / 8; + for (int x = 0; x < 8; x++) + for (int y = 0; y < 8; y++) { + QRect prect(x * pieceSize, y * pieceSize, pieceSize - 1, pieceSize - 1); + pt.fillRect(prect, QBrush(QColor(x,y,0))); + } + m_pickTextureID = bindTexture(*pickimage); + } + +/* glBindTexture(GL_TEXTURE_2D, m_textureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);*/ + + QImage *skyimg = new QImage(":/media/skybox.jpg"); + m_skyTextureID = bindTexture(*skyimg); + delete skyimg; + +/* glBindTexture(GL_TEXTURE_2D, m_skyTextureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);*/ } void Field3D::freeTexture() { @@ -155,14 +300,24 @@ namespace toruschess { deleteTexture(m_textureID); m_textureID = 0; } + if (m_skyTextureID != 0) { + deleteTexture(m_skyTextureID); + m_skyTextureID = 0; + } + if (m_pickTextureID != 0) { + deleteTexture(m_pickTextureID); + m_textureID = 0; + } if (m_textureBuffer) { - delete m_textureBuffer; +// delete m_textureBuffer; m_textureBuffer = 0; } } void Field3D::updateTexture() { +// m_textureBuffer->fill(Qt::black); QPainter pt(m_textureBuffer); + pt.fillRect(QRect(0, 0, m_textureSize, m_textureSize), Qt::black); int pieceSize = m_textureSize / 8; for (int x = 0; x < 8; x++) @@ -180,7 +335,70 @@ namespace toruschess { pt.drawEllipse(QPoint(prect.x() + pieceSize / 2, prect.y() + pieceSize / 2), r, r); } } + pt.setCompositionMode(QPainter::CompositionMode_Plus); + pt.fillRect(0, 0, m_textureSize, m_textureSize, Qt::black); + pt.setCompositionMode(QPainter::CompositionMode_SourceOver); +// m_textureBuffer->updateDynamicTexture(m_textureID); + if (m_textureID) deleteTexture(m_textureID); + m_textureID = bindTexture(*m_textureBuffer); } + void Field3D::mousePressEvent(QMouseEvent *event) { + if (event->button() == Qt::LeftButton) { + QList moves; + Pos p = findPos(event->x(), event->y()); + moves = m_game->field()->validMoves(p); + markMoves(moves); + updateTexture(); + updateGL(); + } + m_mouseLastX = event->x(); + m_mouseLastY = event->y(); + } + void Field3D::mouseMoveEvent(QMouseEvent *event) { + if (event->buttons() & Qt::RightButton) { + m_originX = rotate(m_originX + event->x() - m_mouseLastX, m_textureSize); + m_originY = rotate(m_originY + event->y() - m_mouseLastY, m_textureSize); + updateCam(); + } else if (event->buttons() & Qt::MidButton) { + m_camRotY = rotate(m_camRotY + 0.5*(event->x() - m_mouseLastX)); +// m_camRotX = clip(10, 170, m_camRotX + 0.5*(event->y() - m_mouseLastY)); + m_camRotX = rotate(m_camRotX + 0.5*(event->y() - m_mouseLastY)); + updateCam(); + } + m_mouseLastX = event->x(); + m_mouseLastY = event->y(); + } + + void Field3D::mouseReleaseEvent(QMouseEvent *event) { + m_mouseLastX = event->x(); + m_mouseLastY = event->y(); + if (event->button() == Qt::LeftButton) { +/* if (m_markedMoves.size() == 0) return; + Pos from = m_markedMoves[0].from(); + QList moves; + markMoves(QList()); + Pos p = findPos(event->x(), event->y()); + Move m(m_game->field(), from, p); + m_game->move(m);*/ + } + } + + void Field3D::wheelEvent(QWheelEvent *event) { + double zoom = pow(1.2, - event->delta() / 120); + m_camDist = clip(1.0, 40.0, m_camDist * zoom); + updateCam(); + } + + void Field3D::fieldUpdated() { + updateTexture(); + updateGL(); + } + + void Field3D::setFigureMode(FigureMode m) { + m_figureMode = m; + updateTexture(); + updateGL(); + } } diff --git a/src/field3d.h b/src/field3d.h index 65299f4..ef180c7 100644 --- a/src/field3d.h +++ b/src/field3d.h @@ -21,6 +21,7 @@ #define TORUSCHESSFIELD3D_H #include +#include #include "toruschess.h" #include "piecelibrary.h" @@ -33,6 +34,9 @@ namespace toruschess { class Field3D : public QGLWidget { Q_OBJECT public: + typedef enum { PLANE, TORUS } BoardMode; + typedef enum { FIG2D, FIG3D } FigureMode; + Field3D(Game *game, QWidget *parent = 0); virtual ~Field3D(); @@ -40,11 +44,25 @@ namespace toruschess { virtual QSize sizeHint() const; + BoardMode boardMode() const { return m_boardMode; } + void setBoardMode(BoardMode m) { m_boardMode = m; updateGL(); } + + FigureMode figureMode() const { return m_figureMode; } + void setFigureMode(FigureMode m); + protected: virtual void initializeGL(); virtual void resizeGL(int w, int h); virtual void paintGL(); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void wheelEvent(QWheelEvent *event); + + protected slots: + void fieldUpdated(); + private: void updateCam(); @@ -52,18 +70,33 @@ namespace toruschess { void freeTexture(); void updateTexture(); + Pos findPos(int mx, int my); + Game *m_game; PieceLibrary *m_lib; bool m_marked[8][8]; QList m_markedMoves; + BoardMode m_boardMode; + FigureMode m_figureMode; + /* Texture data */ QImage *m_textureBuffer; GLuint m_textureID; /* Cam data */ double m_camDist, m_camRotX, m_camRotY, m_camRotZ; + int m_originX, m_originY; + int m_mouseLastX, m_mouseLastY; + + /* skybox */ + GLUquadric *m_skySphere; + GLuint m_skyTextureID; + + /* Pick */ + GLuint m_pickTextureID; + QGLPixelBuffer *m_pickBuffer; static const int m_textureSize = 1024; }; diff --git a/src/media.qrc b/src/media.qrc index d27351a..cdbf236 100644 --- a/src/media.qrc +++ b/src/media.qrc @@ -17,5 +17,6 @@ ../media/board1_white.png ../media/board2_dark.png ../media/board2_white.png + ../media/skybox.jpg diff --git a/src/optiondlg.ui b/src/optiondlg.ui index 919d64a..b8c7789 100644 --- a/src/optiondlg.ui +++ b/src/optiondlg.ui @@ -9,7 +9,7 @@ 0 0 373 - 227 + 294 @@ -102,13 +102,43 @@ - + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset + + + + View + + + + + + Torus + + + + + + + 3D + + + + + + + 2D + + + + + + diff --git a/src/testgame.cpp b/src/testgame.cpp index 55e3db8..d1875e2 100644 --- a/src/testgame.cpp +++ b/src/testgame.cpp @@ -27,39 +27,62 @@ #include #include - -#include "field2d.h" -#include "field3d.h" +#include +#include #include "ai.h" namespace toruschess { - TestGame::TestGame(QWidget *parent) : QMainWindow(parent), m_game(new Game()), m_optionDlg(new OptionDlg(m_game, this)) { + static QAction *makeAction(QObject *parent, const QString &text, const QObject * receiver, const char * member, const QKeySequence &shortcut = QKeySequence(), QActionGroup *group = NULL) { + QAction *a = new QAction(text, parent); + a->setShortcut(shortcut); + if (group) a->setActionGroup(group); + QObject::connect(a, SIGNAL(triggered(bool)), receiver, member); + return a; + } + + TestGame::TestGame(QWidget *parent) + : QMainWindow(parent), m_game(new Game()), m_optionDlg(new OptionDlg(m_game, this)), m_viewMode((ViewMode) -1) { setWindowTitle("Torus Chess"); -// PieceLibrary *lib = new PieceLibrary(this); -// setCentralWidget(new TestField(this, lib, m_game)); - setCentralWidget(new Field2D(m_game, this)); + + QWidget *centralWidget = new QWidget(this); + m_fieldsLayout = new QStackedLayout(centralWidget); + m_field2d = new Field2D(m_game, centralWidget); + m_field3d = new Field3D(m_game, centralWidget); + m_fieldsLayout->addWidget(m_field2d); + m_fieldsLayout->addWidget(m_field3d); + centralWidget->setLayout(m_fieldsLayout); + setCentralWidget(centralWidget); + statusBar()->show(); - connect(m_game, SIGNAL(updated()), this, SLOT(gameUpdated())); connect(m_game, SIGNAL(changed(GameState)), this, SLOT(gameChanged(GameState))); m_game->restart(); + QAction + *act_game_newGame = makeAction(this, "&New Game", this, SLOT(menuRestart()), Qt::Key_F2), + *act_game_options = makeAction(this, "&Options", this, SLOT(menuOptions()), Qt::CTRL + Qt::Key_O), + *act_game_quit = makeAction(this, "&Quit", this, SLOT(close())); + + QActionGroup *viewGroup = new QActionGroup(this); + m_act_view_2d = makeAction(this, "&2D-View", this, SLOT(menuView2d()), Qt::CTRL + Qt::Key_2, viewGroup); + m_act_view_3d = makeAction(this, "&3D-View", this, SLOT(menuView3d()), Qt::CTRL + Qt::Key_3, viewGroup); + m_act_view_torus = makeAction(this, "&Torus-View", this, SLOT(menuViewTorus()), Qt::CTRL + Qt::Key_4, viewGroup); + + act_game_quit->setMenuRole(QAction::QuitRole); + QMenuBar *menuBar = new QMenuBar(this); - QMenu *menuGame = menuBar->addMenu("Game"); - menuGame->addAction("New Game", this, SLOT(menuRestart())); - menuGame->addAction("Options", this, SLOT(menuOptions())); + QMenu *menuGame = menuBar->addMenu("&Game"); + menuGame->addAction(act_game_newGame); + menuGame->addAction(act_game_options); menuGame->addSeparator(); - menuGame->addAction("Quit", this, SLOT(close())); + menuGame->addAction(act_game_quit); + QMenu *menuView = menuBar->addMenu("&View"); + menuView->addActions(viewGroup->actions()); setMenuBar(menuBar); - } - - void TestGame::gameUpdated() { -/* if (m_game->state() == TURN_BLACK) { - Move m = ai::getMove(m_game); - if (m.valid()) m_game->move(m); - }*/ + setViewMode(VIEW_2D); + updateGeometry(); } void TestGame::gameChanged(GameState state) { @@ -74,4 +97,36 @@ namespace toruschess { m_optionDlg->exec(); } + void TestGame::setViewMode(ViewMode viewMode) { + if (m_viewMode == viewMode) return; + m_viewMode = viewMode; + switch (m_viewMode) { + case VIEW_2D: + m_fieldsLayout->setCurrentIndex(0); + m_act_view_2d->setChecked(true); + break; + case VIEW_3D: + m_fieldsLayout->setCurrentIndex(1); + m_act_view_3d->setChecked(true); + m_field3d->setBoardMode(Field3D::PLANE); + break; + case VIEW_TORUS: + m_fieldsLayout->setCurrentIndex(1); + m_act_view_torus->setChecked(true); + m_field3d->setBoardMode(Field3D::TORUS); + break; + } + emit changedViewMode(viewMode); + } + + void TestGame::menuView2d() { + setViewMode(VIEW_2D); + } + void TestGame::menuView3d() { + setViewMode(VIEW_3D); + } + void TestGame::menuViewTorus() { + setViewMode(VIEW_TORUS); + } + } diff --git a/src/testgame.h b/src/testgame.h index 5181966..ce1858f 100644 --- a/src/testgame.h +++ b/src/testgame.h @@ -24,32 +24,56 @@ #include #include #include +#include #include "toruschess.h" #include "piecelibrary.h" #include "optiondlg.h" +#include "field2d.h" +#include "field3d.h" + /** @author Stefan Bühler */ namespace toruschess { + typedef enum { VIEW_2D, VIEW_3D, VIEW_TORUS } ViewMode; + class TestGame : public QMainWindow { Q_OBJECT public: TestGame(QWidget *parent = 0); - + + ViewMode viewMode() const { return m_viewMode; } + + public slots: + void setViewMode(ViewMode viewMode); + + signals: + void changedViewMode(ViewMode viewMode); + private slots: - void gameUpdated(); void gameChanged(GameState state); void menuRestart(); void menuOptions(); - + + void menuView2d(); + void menuView3d(); + void menuViewTorus(); + private: Game *m_game; OptionDlg *m_optionDlg; + ViewMode m_viewMode; + + QStackedLayout *m_fieldsLayout; + Field2D *m_field2d; + Field3D *m_field3d; + + QAction *m_act_view_2d, *m_act_view_3d, *m_act_view_torus; }; }