summaryrefslogtreecommitdiffstats
path: root/Tools/QtBiomeVisualiser
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/QtBiomeVisualiser')
-rw-r--r--Tools/QtBiomeVisualiser/BiomeView.cpp185
-rw-r--r--Tools/QtBiomeVisualiser/BiomeView.h41
-rw-r--r--Tools/QtBiomeVisualiser/ChunkCache.cpp16
-rw-r--r--Tools/QtBiomeVisualiser/ChunkCache.h6
-rw-r--r--Tools/QtBiomeVisualiser/ChunkLoader.h2
-rw-r--r--Tools/QtBiomeVisualiser/ChunkSource.cpp40
-rw-r--r--Tools/QtBiomeVisualiser/ChunkSource.h24
-rw-r--r--Tools/QtBiomeVisualiser/MainWindow.cpp27
-rw-r--r--Tools/QtBiomeVisualiser/MainWindow.h1
-rw-r--r--Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro4
10 files changed, 307 insertions, 39 deletions
diff --git a/Tools/QtBiomeVisualiser/BiomeView.cpp b/Tools/QtBiomeVisualiser/BiomeView.cpp
index be01fd104..bbaccb369 100644
--- a/Tools/QtBiomeVisualiser/BiomeView.cpp
+++ b/Tools/QtBiomeVisualiser/BiomeView.cpp
@@ -8,11 +8,19 @@
+static const int DELTA_STEP = 120; // The normal per-notch wheel delta
+
+
+
+
+
BiomeView::BiomeView(QWidget * parent) :
super(parent),
m_X(0),
m_Z(0),
- m_Zoom(1)
+ m_Zoom(1),
+ m_IsMouseDragging(false),
+ m_MouseWheelDelta(0)
{
// Create the image used for undefined chunks:
int offset = 0;
@@ -33,6 +41,9 @@ BiomeView::BiomeView(QWidget * parent) :
// Add a chunk-update callback mechanism:
connect(&m_Cache, SIGNAL(chunkAvailable(int, int)), this, SLOT(chunkAvailable(int, int)));
+
+ // Allow keyboard interaction:
+ setFocusPolicy(Qt::StrongFocus);
}
@@ -120,6 +131,21 @@ void BiomeView::chunkAvailable(int a_ChunkX, int a_ChunkZ)
+void BiomeView::reload()
+{
+ if (!hasData())
+ {
+ return;
+ }
+ m_Cache.reload();
+
+ redraw();
+}
+
+
+
+
+
void BiomeView::drawChunk(int a_ChunkX, int a_ChunkZ)
{
if (!hasData())
@@ -236,9 +262,164 @@ void BiomeView::paintEvent(QPaintEvent * a_Event)
-void BiomeView::queueChunkRender(ChunkPtr a_Chunk)
+void BiomeView::mousePressEvent(QMouseEvent * a_Event)
+{
+ m_LastX = a_Event->x();
+ m_LastY = a_Event->y();
+ m_IsMouseDragging = true;
+}
+
+
+
+
+
+void BiomeView::mouseMoveEvent(QMouseEvent * a_Event)
+{
+ if (m_IsMouseDragging)
+ {
+ // The user is dragging the mouse, move the view around:
+ m_X += (m_LastX - a_Event->x()) / m_Zoom;
+ m_Z += (m_LastY - a_Event->y()) / m_Zoom;
+ m_LastX = a_Event->x();
+ m_LastY = a_Event->y();
+ redraw();
+ return;
+ }
+
+ // TODO: Update the status bar info for the biome currently pointed at
+}
+
+
+
+
+
+void BiomeView::mouseReleaseEvent(QMouseEvent *)
+{
+ m_IsMouseDragging = false;
+}
+
+
+
+
+
+void BiomeView::wheelEvent(QWheelEvent * a_Event)
+{
+ m_MouseWheelDelta += a_Event->delta();
+ while (m_MouseWheelDelta >= DELTA_STEP)
+ {
+ increaseZoom();
+ m_MouseWheelDelta -= DELTA_STEP;
+ }
+ while (m_MouseWheelDelta <= -DELTA_STEP)
+ {
+ decreaseZoom();
+ m_MouseWheelDelta += DELTA_STEP;
+ }
+}
+
+
+
+
+
+void BiomeView::keyPressEvent(QKeyEvent * a_Event)
+{
+ switch (a_Event->key())
+ {
+ case Qt::Key_Up:
+ case Qt::Key_W:
+ {
+ m_Z -= 10.0 / m_Zoom;
+ redraw();
+ break;
+ }
+
+ case Qt::Key_Down:
+ case Qt::Key_S:
+ {
+ m_Z += 10.0 / m_Zoom;
+ redraw();
+ break;
+ }
+
+ case Qt::Key_Left:
+ case Qt::Key_A:
+ {
+ m_X -= 10.0 / m_Zoom;
+ redraw();
+ break;
+ }
+
+ case Qt::Key_Right:
+ case Qt::Key_D:
+ {
+ m_X += 10.0 / m_Zoom;
+ redraw();
+ break;
+ }
+
+ case Qt::Key_PageUp:
+ case Qt::Key_Q:
+ {
+ increaseZoom();
+ break;
+ }
+
+ case Qt::Key_PageDown:
+ case Qt::Key_E:
+ {
+ decreaseZoom();
+ break;
+ }
+ }
+}
+
+
+
+
+
+void BiomeView::decreaseZoom()
{
+ if (m_Zoom > 1.001)
+ {
+ m_Zoom--;
+ if (m_Zoom < 1.0)
+ {
+ // Just crossed the 100%, fixate the 100% threshold:
+ m_Zoom = 1.0;
+ }
+ }
+ else if (m_Zoom > 0.01)
+ {
+ m_Zoom = m_Zoom / 2;
+ }
+ redraw();
+}
+
+
+
+
+void BiomeView::increaseZoom()
+{
+ if (m_Zoom > 0.99)
+ {
+ if (m_Zoom > 20.0)
+ {
+ // Zoom too large
+ return;
+ }
+ m_Zoom++;
+ }
+ else
+ {
+ m_Zoom = m_Zoom * 2;
+ if (m_Zoom > 1.0)
+ {
+ // Just crossed the 100%, fixate the 100% threshold:
+ m_Zoom = 1.0;
+ }
+ }
+ redraw();
}
diff --git a/Tools/QtBiomeVisualiser/BiomeView.h b/Tools/QtBiomeVisualiser/BiomeView.h
index c54c66491..f0521571d 100644
--- a/Tools/QtBiomeVisualiser/BiomeView.h
+++ b/Tools/QtBiomeVisualiser/BiomeView.h
@@ -1,6 +1,7 @@
#pragma once
#include <QWidget>
+#include <memory>
#include "ChunkCache.h"
#include "ChunkSource.h"
@@ -33,12 +34,28 @@ public slots:
/** A specified chunk has become available, redraw it. */
void chunkAvailable(int a_ChunkX, int a_ChunkZ);
+ /** Reloads the current chunk source and redraws the entire workspace. */
+ void reload();
+
protected:
double m_X, m_Z;
- int m_Zoom;
+ double m_Zoom;
+
+ /** Cache for the loaded chunk data. */
ChunkCache m_Cache;
+
+ /** The entire view's contents in an offscreen image. */
QImage m_Image;
+ /** Coords of the mouse for the previous position, used while dragging. */
+ int m_LastX, m_LastY;
+
+ /** Set to true when the user has a mouse button depressed, and is dragging the view. */
+ bool m_IsMouseDragging;
+
+ /** Accumulator for the mouse wheel's delta. When the accumulator hits a threshold, the view zooms. */
+ int m_MouseWheelDelta;
+
/** Data used for rendering a chunk that hasn't been loaded yet */
uchar m_EmptyChunkImage[16 * 16 * 4];
@@ -55,8 +72,26 @@ protected:
/** Paints the entire widget */
virtual void paintEvent(QPaintEvent *) override;
- /** Queues the chunk for rendering. */
- void queueChunkRender(ChunkPtr a_Chunk);
+ /** Called when the user presses any mouse button. */
+ virtual void mousePressEvent(QMouseEvent * a_Event);
+
+ /** Called when the user moves the mouse. */
+ virtual void mouseMoveEvent(QMouseEvent * a_Event);
+
+ /** Called when the user releases a previously held mouse button. */
+ virtual void mouseReleaseEvent(QMouseEvent * a_Event) override;
+
+ /** Called when the user rotates the mouse wheel. */
+ virtual void wheelEvent(QWheelEvent * a_Event) override;
+
+ /** Called when the user presses a key. */
+ virtual void keyPressEvent(QKeyEvent * a_Event) override;
+
+ /** Decreases the zoom level and queues a redraw. */
+ void decreaseZoom();
+
+ /** Increases the zoom level and queues a redraw. */
+ void increaseZoom();
};
diff --git a/Tools/QtBiomeVisualiser/ChunkCache.cpp b/Tools/QtBiomeVisualiser/ChunkCache.cpp
index b2230def0..05c267d30 100644
--- a/Tools/QtBiomeVisualiser/ChunkCache.cpp
+++ b/Tools/QtBiomeVisualiser/ChunkCache.cpp
@@ -76,6 +76,22 @@ void ChunkCache::setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource)
+void ChunkCache::reload()
+{
+ assert(m_ChunkSource.get() != nullptr);
+
+ // Reload the chunk source:
+ m_ChunkSource->reload();
+
+ // Clear the cache:
+ QMutexLocker lock(&m_Mtx);
+ m_Cache.clear();
+}
+
+
+
+
+
void ChunkCache::gotChunk(int a_ChunkX, int a_ChunkZ)
{
emit chunkAvailable(a_ChunkX, a_ChunkZ);
diff --git a/Tools/QtBiomeVisualiser/ChunkCache.h b/Tools/QtBiomeVisualiser/ChunkCache.h
index 0efa7fc39..8d198f02f 100644
--- a/Tools/QtBiomeVisualiser/ChunkCache.h
+++ b/Tools/QtBiomeVisualiser/ChunkCache.h
@@ -3,6 +3,7 @@
#include <QObject>
#include <QCache>
#include <QMutex>
+#include <memory>
@@ -36,7 +37,10 @@ public:
void setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource);
/** Returns true iff the chunk source has been initialized. */
- bool hasData(void) const { return (m_ChunkSource.get() != nullptr); }
+ bool hasData() const { return (m_ChunkSource.get() != nullptr); }
+
+ /** Reloads the current chunk source. */
+ void reload();
signals:
void chunkAvailable(int a_ChunkX, int a_ChunkZ);
diff --git a/Tools/QtBiomeVisualiser/ChunkLoader.h b/Tools/QtBiomeVisualiser/ChunkLoader.h
index 3565434b9..4d026a45e 100644
--- a/Tools/QtBiomeVisualiser/ChunkLoader.h
+++ b/Tools/QtBiomeVisualiser/ChunkLoader.h
@@ -1,6 +1,8 @@
#pragma once
+
#include <QObject>
#include <QRunnable>
+#include <memory>
diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp
index 44dcf1fa7..2235816bc 100644
--- a/Tools/QtBiomeVisualiser/ChunkSource.cpp
+++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp
@@ -1,6 +1,8 @@
#include "Globals.h"
#include "ChunkSource.h"
+#include <QThread>
#include "Generating/BioGen.h"
+#include "inifile/iniFile.h"
@@ -101,9 +103,9 @@ public:
for (size_t i = 0; i < ARRAYCOUNT(biomeColors); i++)
{
uchar * color = &biomeToColor[4 * biomeColors[i].m_Biome];
- color[0] = biomeColors[i].m_Color[0];
+ color[0] = biomeColors[i].m_Color[2];
color[1] = biomeColors[i].m_Color[1];
- color[2] = biomeColors[i].m_Color[2];
+ color[2] = biomeColors[i].m_Color[0];
color[3] = 0xff;
}
}
@@ -118,8 +120,8 @@ static void biomesToImage(cChunkDef::BiomeMap & a_Biomes, Chunk::Image & a_Image
{
// Make sure the two arrays are of the same size, compile-time.
// Note that a_Image is actually 4 items per pixel, so the array is 4 times bigger:
- static const char Check1[4 * ARRAYCOUNT(a_Biomes) - ARRAYCOUNT(a_Image) + 1];
- static const char Check2[ARRAYCOUNT(a_Image) - 4 * ARRAYCOUNT(a_Biomes) + 1];
+ static const char Check1[4 * ARRAYCOUNT(a_Biomes) - ARRAYCOUNT(a_Image) + 1] = {};
+ static const char Check2[ARRAYCOUNT(a_Image) - 4 * ARRAYCOUNT(a_Biomes) + 1] = {};
// Convert the biomes into color:
for (size_t i = 0; i < ARRAYCOUNT(a_Biomes); i++)
@@ -138,9 +140,11 @@ static void biomesToImage(cChunkDef::BiomeMap & a_Biomes, Chunk::Image & a_Image
////////////////////////////////////////////////////////////////////////////////
// BioGenSource:
-BioGenSource::BioGenSource(cBiomeGen * a_BiomeGen) :
- m_BiomeGen(a_BiomeGen)
+BioGenSource::BioGenSource(QString a_WorldIniPath) :
+ m_WorldIniPath(a_WorldIniPath),
+ m_Mtx(QMutex::Recursive)
{
+ reload();
}
@@ -149,11 +153,11 @@ BioGenSource::BioGenSource(cBiomeGen * a_BiomeGen) :
void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk)
{
- // TODO: To make use of multicore machines, we need multiple copies of the biomegen
- // Right now we have only one, so we can let only one thread use it (hence the mutex)
- QMutexLocker lock(&m_Mtx);
cChunkDef::BiomeMap biomes;
- m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, biomes);
+ {
+ QMutexLocker lock(&m_Mtx);
+ m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, biomes);
+ }
Chunk::Image img;
biomesToImage(biomes, img);
a_DestChunk->setImage(img);
@@ -162,3 +166,19 @@ void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChu
+
+void BioGenSource::reload()
+{
+ cIniFile ini;
+ ini.ReadFile(m_WorldIniPath.toStdString());
+ int seed = ini.GetValueSetI("Seed", "Seed", 0);
+ bool unused = false;
+ QMutexLocker lock(&m_Mtx);
+ m_BiomeGen.reset(cBiomeGen::CreateBiomeGen(ini, seed, unused));
+ lock.unlock();
+ ini.WriteFile(m_WorldIniPath.toStdString());
+}
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/ChunkSource.h b/Tools/QtBiomeVisualiser/ChunkSource.h
index d6eb2e3cb..868e4a144 100644
--- a/Tools/QtBiomeVisualiser/ChunkSource.h
+++ b/Tools/QtBiomeVisualiser/ChunkSource.h
@@ -1,4 +1,6 @@
#pragma once
+#include <QString>
+#include <QMutex>
#include "Chunk.h"
@@ -7,6 +9,8 @@
// fwd:
class cBiomeGen;
+typedef std::shared_ptr<cBiomeGen> cBiomeGenPtr;
+class cIniFile;
@@ -21,6 +25,9 @@ public:
/** Fills the a_DestChunk with the biomes for the specified coords.
It is expected to be thread-safe and re-entrant. Usually QThread::idealThreadCount() threads are used. */
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) = 0;
+
+ /** Forces a fresh reload of the source. Useful mainly for the generator, whose underlying definition file may have been changed. */
+ virtual void reload() = 0;
};
@@ -32,14 +39,21 @@ class BioGenSource :
public ChunkSource
{
public:
- /** Constructs a new BioGenSource based on the biome generator given.
- Takes ownership of a_BiomeGen */
- BioGenSource(cBiomeGen * a_BiomeGen);
+ /** Constructs a new BioGenSource based on the biome generator that is defined in the specified world.ini file. */
+ BioGenSource(QString a_WorldIniPath);
+ // ChunkSource overrides:
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override;
+ virtual void reload(void) override;
protected:
- std::shared_ptr<cBiomeGen> m_BiomeGen;
+ /** Path to the world.ini file from which the m_WorldIni is regenerated on reload requests. */
+ QString m_WorldIniPath;
+
+ /** The generator used for generating biomes. */
+ std::unique_ptr<cBiomeGen> m_BiomeGen;
+
+ /** Guards m_BiomeGen against multithreaded access. */
QMutex m_Mtx;
};
@@ -52,7 +66,9 @@ class AnvilSource :
public:
// TODO
+ // ChunkSource overrides:
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override;
+ virtual void reload() override {}
};
diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp
index 8b98c0b0e..65d0ccf5e 100644
--- a/Tools/QtBiomeVisualiser/MainWindow.cpp
+++ b/Tools/QtBiomeVisualiser/MainWindow.cpp
@@ -16,11 +16,11 @@
MainWindow::MainWindow(QWidget * parent) :
QMainWindow(parent)
{
- createActions();
- createMenus();
-
m_BiomeView = new BiomeView(this);
setCentralWidget(m_BiomeView);
+
+ createActions();
+ createMenus();
}
@@ -39,19 +39,7 @@ MainWindow::~MainWindow()
void MainWindow::generate()
{
QString worldIni = QFileDialog::getOpenFileName(this, tr("Open world.ini"), QString(), tr("world.ini (world.ini)"));
- cIniFile ini;
- if (!ini.ReadFile(worldIni.toStdString()))
- {
- return;
- }
- int seed = ini.GetValueSetI("Seed", "Seed", 0);
- bool unused = false;
- cBiomeGen * biomeGen = cBiomeGen::CreateBiomeGen(ini, seed, unused);
- if (biomeGen == nullptr)
- {
- return;
- }
- m_BiomeView->setChunkSource(std::shared_ptr<BioGenSource>(new BioGenSource(biomeGen)));
+ m_BiomeView->setChunkSource(std::shared_ptr<BioGenSource>(new BioGenSource(worldIni)));
m_BiomeView->redraw();
}
@@ -80,6 +68,11 @@ void MainWindow::createActions()
m_actOpen->setStatusTip(tr("Open an existing world and display its biomes"));
connect(m_actOpen, SIGNAL(triggered()), this, SLOT(open()));
+ m_actReload = new QAction(tr("&Reload"), this);
+ m_actReload->setShortcut(tr("F5"));
+ m_actReload->setStatusTip(tr("Open an existing world and display its biomes"));
+ connect(m_actReload, SIGNAL(triggered()), m_BiomeView, SLOT(reload()));
+
m_actExit = new QAction(tr("E&xit"), this);
m_actExit->setShortcut(tr("Alt+X"));
m_actExit->setStatusTip(tr("Exit %1").arg(QApplication::instance()->applicationName()));
@@ -96,6 +89,8 @@ void MainWindow::createMenus()
mFile->addAction(m_actGen);
mFile->addAction(m_actOpen);
mFile->addSeparator();
+ mFile->addAction(m_actReload);
+ mFile->addSeparator();
mFile->addAction(m_actExit);
}
diff --git a/Tools/QtBiomeVisualiser/MainWindow.h b/Tools/QtBiomeVisualiser/MainWindow.h
index f6028aff1..b37bf4120 100644
--- a/Tools/QtBiomeVisualiser/MainWindow.h
+++ b/Tools/QtBiomeVisualiser/MainWindow.h
@@ -29,6 +29,7 @@ protected:
// Actions:
QAction * m_actGen;
QAction * m_actOpen;
+ QAction * m_actReload;
QAction * m_actExit;
diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro
index 0329d5607..e6b65e628 100644
--- a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro
+++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro
@@ -55,8 +55,6 @@ INCLUDEPATH += $$_PRO_FILE_PWD_ \
$$_PRO_FILE_PWD_/../../lib
-CONFIG += STATIC
-
-
+CONFIG += C++11