summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Tools/.gitignore1
-rw-r--r--Tools/BiomeVisualiser/.gitignore4
-rw-r--r--Tools/BiomeVisualiser/BiomeCache.cpp338
-rw-r--r--Tools/BiomeVisualiser/BiomeCache.h96
-rw-r--r--Tools/BiomeVisualiser/BiomeColors.cpp114
-rw-r--r--Tools/BiomeVisualiser/BiomeColors.h15
-rw-r--r--Tools/BiomeVisualiser/BiomeRenderer.cpp119
-rw-r--r--Tools/BiomeVisualiser/BiomeRenderer.h55
-rw-r--r--Tools/BiomeVisualiser/BiomeSource.h37
-rw-r--r--Tools/BiomeVisualiser/BiomeViewWnd.cpp247
-rw-r--r--Tools/BiomeVisualiser/BiomeViewWnd.h69
-rw-r--r--Tools/BiomeVisualiser/BiomeVisualiser.cpp52
-rw-r--r--Tools/BiomeVisualiser/BiomeVisualiser.h31
-rw-r--r--Tools/BiomeVisualiser/BiomeVisualiser.sln23
-rw-r--r--Tools/BiomeVisualiser/BiomeVisualiser.vcproj527
-rw-r--r--Tools/BiomeVisualiser/GeneratorBiomeSource.h42
-rw-r--r--Tools/BiomeVisualiser/Pixmap.cpp120
-rw-r--r--Tools/BiomeVisualiser/Pixmap.h39
-rw-r--r--Tools/BiomeVisualiser/Timer.h40
-rw-r--r--Tools/BiomeVisualiser/WndProcThunk.h143
-rw-r--r--Tools/BiomeVisualiser/profile_run.cmd70
-rw-r--r--Tools/QtBiomeVisualiser/.gitignore2
-rw-r--r--Tools/QtBiomeVisualiser/BiomeView.cpp427
-rw-r--r--Tools/QtBiomeVisualiser/BiomeView.h100
-rw-r--r--Tools/QtBiomeVisualiser/Chunk.cpp36
-rw-r--r--Tools/QtBiomeVisualiser/Chunk.h40
-rw-r--r--Tools/QtBiomeVisualiser/ChunkCache.cpp126
-rw-r--r--Tools/QtBiomeVisualiser/ChunkCache.h72
-rw-r--r--Tools/QtBiomeVisualiser/ChunkLoader.cpp29
-rw-r--r--Tools/QtBiomeVisualiser/ChunkLoader.h45
-rw-r--r--Tools/QtBiomeVisualiser/ChunkSource.cpp421
-rw-r--r--Tools/QtBiomeVisualiser/ChunkSource.h107
-rw-r--r--Tools/QtBiomeVisualiser/GeneratorSetup.cpp159
-rw-r--r--Tools/QtBiomeVisualiser/GeneratorSetup.h64
-rw-r--r--Tools/QtBiomeVisualiser/Globals.h386
-rw-r--r--Tools/QtBiomeVisualiser/MainWindow.cpp310
-rw-r--r--Tools/QtBiomeVisualiser/MainWindow.h96
-rw-r--r--Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro94
-rw-r--r--Tools/QtBiomeVisualiser/main.cpp20
39 files changed, 2535 insertions, 2181 deletions
diff --git a/Tools/.gitignore b/Tools/.gitignore
new file mode 100644
index 000000000..f240e723e
--- /dev/null
+++ b/Tools/.gitignore
@@ -0,0 +1 @@
+Debug/
diff --git a/Tools/BiomeVisualiser/.gitignore b/Tools/BiomeVisualiser/.gitignore
deleted file mode 100644
index cfbc9164c..000000000
--- a/Tools/BiomeVisualiser/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-Debug/
-logs/
-Release/
-Release profiled/
diff --git a/Tools/BiomeVisualiser/BiomeCache.cpp b/Tools/BiomeVisualiser/BiomeCache.cpp
deleted file mode 100644
index 7d9301d8f..000000000
--- a/Tools/BiomeVisualiser/BiomeCache.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-
-// BiomeCache.cpp
-
-// Implements the cBiomeCache class representing a biome source that caches data from the underlying biome source
-
-#include "Globals.h"
-#include "BiomeCache.h"
-#include "Timer.h"
-
-
-
-
-
-static int GetNumCores(void)
-{
- // Get number of cores by querying the system process affinity mask
- DWORD Affinity, ProcAffinity;
- GetProcessAffinityMask(GetCurrentProcess(), &ProcAffinity, &Affinity);
- int NumCores = 0;
- while (Affinity > 0)
- {
- if ((Affinity & 1) == 1)
- {
- NumCores++;
- }
- Affinity >>= 1;
- } // while (Affinity > 0)
- return NumCores;
-}
-
-
-
-
-
-cBiomeCache::cBiomeCache(void) :
- m_Source(NULL),
- m_BaseX(-100000),
- m_BaseZ(-100000),
- m_Available(NULL),
- m_IsTerminatingThreads(false)
-{
- int NumThreads = GetNumCores();
- NumThreads--; // One core should be left for the system to run on ;)
- for (int i = NumThreads; i > 0; i--)
- {
- cThread * Thread = new cThread(*this);
- m_Threads.push_back(Thread);
- Thread->Start();
- }
-}
-
-
-
-
-cBiomeCache::~cBiomeCache()
-{
- m_IsTerminatingThreads = true;
- for (cThreads::iterator itr = m_Threads.begin(), end = m_Threads.end(); itr != end; ++itr)
- {
- m_evtQueued.Set();
- }
- for (cThreads::iterator itr = m_Threads.begin(), end = m_Threads.end(); itr != end; ++itr)
- {
- delete *itr;
- }
- m_Threads.clear();
-
- SetSource(NULL);
-}
-
-
-
-
-
-cBiomeSource::eAvailability cBiomeCache::GetBiome(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes)
-{
- if (m_Source == NULL)
- {
- return baNever;
- }
-
- // Look up using the cache:
- int x = a_ChunkX - m_BaseX;
- int z = a_ChunkZ - m_BaseZ;
- if ((x < 0) || (x >= m_Width) || (z < 0) || (z >= m_Height))
- {
- // Outside the cached region
- return baNever;
- }
-
- cCSLock Lock(m_CS);
- cItem * Item = m_Available[x + m_Width * z];
- if (Item == NULL)
- {
- // Item hasn't been processed yet
- return baLater;
- }
- if (Item->m_IsValid)
- {
- memcpy(a_Biomes, Item->m_Biomes, sizeof(a_Biomes));
- return baNow;
- }
-
- // Item has been processed, but the underlying source refused to give the data to us
- return baNever;
-}
-
-
-
-
-
-void cBiomeCache::HintViewArea(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ)
-{
- cTimer Timer("Cache: HintViewArea");
-
- if (
- (a_MinChunkX == m_BaseX) &&
- (a_MaxChunkX == m_BaseX + m_Width - 1) &&
- (a_MinChunkZ == m_BaseZ) &&
- (a_MaxChunkZ == m_BaseZ + m_Height - 1)
- )
- {
- // The same set of parameters, bail out
- return;
- }
-
- if (m_Source != NULL)
- {
- m_Source->HintViewArea(a_MinChunkX, a_MaxChunkX, a_MinChunkZ, a_MaxChunkZ);
- }
-
- int NewWidth = a_MaxChunkX - a_MinChunkX + 1;
- int NewHeight = a_MaxChunkZ - a_MinChunkZ + 1;
-
- // Make a new empty cache table:
- pItem * NewAvailable = new pItem[NewWidth * NewHeight];
- for (int i = NewWidth * NewHeight - 1; i >= 0; --i)
- {
- NewAvailable[i] = NULL;
- }
-
- // Move the common contents of the old table into the new table:
- cCSLock Lock(m_CS);
- for (int z = 0; z < NewHeight; z++)
- {
- int OldZ = z + a_MinChunkZ - m_BaseZ;
- if ((OldZ < 0) || (OldZ >= m_Height))
- {
- continue;
- }
- for (int x = 0; x < NewWidth; x++)
- {
- int OldX = x + a_MinChunkX - m_BaseX;
- if ((OldX < 0) || (OldX >= m_Width))
- {
- continue;
- }
- NewAvailable[x + NewWidth * z] = m_Available[OldX + m_Width * OldZ];
- m_Available[OldX + m_Width * OldZ] = NULL;
- } // for x
- } // for z
-
- // All items that aren't common go into the pool:
- for (int idx = 0, z = 0; z < m_Height; z++)
- {
- for (int x = 0; x < m_Width; ++x, ++idx)
- {
- if (m_Available[idx] != NULL)
- {
- m_Pool.push_back(m_Available[idx]);
- m_Available[idx] = NULL;
- }
- }
- }
-
- // Replace the cache table:
- delete m_Available;
- m_Available = NewAvailable;
- m_Width = NewWidth;
- m_Height = NewHeight;
- m_BaseX = a_MinChunkX;
- m_BaseZ = a_MinChunkZ;
-
- // Remove all items outside the coords:
- FilterOutItems(m_Queue, a_MinChunkX, a_MaxChunkX, a_MinChunkZ, a_MaxChunkZ);
-
- // Queue all items from inside the coords into m_Queue:
- for (int z = 0; z < NewHeight; z++)
- {
- for (int x = 0; x < NewWidth; x++)
- {
- if (m_Available[x + m_Width * z] != NULL)
- {
- // Already calculated, skip
- continue;
- }
-
- if (m_Pool.empty())
- {
- m_Pool.push_back(new cItem(x + a_MinChunkX, z + a_MinChunkZ));
- }
- ASSERT(!m_Pool.empty());
- m_Pool.back()->m_ChunkX = x + a_MinChunkX;
- m_Pool.back()->m_ChunkZ = z + a_MinChunkZ;
- m_Queue.push_back(m_Pool.back());
- m_Pool.pop_back();
- m_evtQueued.Set();
- } // for x
- } // for z
-}
-
-
-
-
-
-void cBiomeCache::SetSource(cBiomeSource * a_Source)
-{
- // TODO: Stop all threads, so that they don't use the source anymore!
-
- delete m_Source;
- m_Source = a_Source;
-
- // Invalidate cache contents:
- cCSLock Lock(m_CS);
- m_BaseX = -10000;
- m_BaseZ = -10000;
- m_Pool.splice(m_Pool.end(), m_Queue);
-}
-
-
-
-
-
-void cBiomeCache::FilterOutItems(cItems & a_Items, int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ)
-{
- for (cItems::iterator itr = a_Items.begin(); itr != a_Items.end();)
- {
- if (
- ((*itr)->m_ChunkX < a_MinChunkX) ||
- ((*itr)->m_ChunkX > a_MaxChunkX) ||
- ((*itr)->m_ChunkX < a_MinChunkX) ||
- ((*itr)->m_ChunkX > a_MaxChunkX)
- )
- {
- m_Pool.push_back(*itr);
- itr = a_Items.erase(itr);
- }
- else
- {
- ++itr;
- }
- }
-}
-
-
-
-
-
-void cBiomeCache::thrProcessQueueItem(void)
-{
- if (m_Source == NULL)
- {
- return;
- }
-
- cItem * Item = NULL;
- {
- cCSLock Lock(m_CS);
- if (m_Queue.empty())
- {
- cCSUnlock Unlock(Lock);
- m_evtQueued.Wait();
- }
- if (m_IsTerminatingThreads || m_Queue.empty())
- {
- // We've been woken up only to die / spurious wakeup
- return;
- }
- Item = m_Queue.back();
- m_Queue.pop_back();
- }
-
- // Process the item:
- Item->m_IsValid = (m_Source->GetBiome(Item->m_ChunkX, Item->m_ChunkZ, Item->m_Biomes) == baNow);
-
- // Store result:
- cCSLock Lock(m_CS);
- int x = Item->m_ChunkX - m_BaseX;
- int z = Item->m_ChunkZ - m_BaseZ;
- if ((x < 0) || (x >= m_Width) || (z < 0) || (z >= m_Height))
- {
- // The cache rectangle has changed under our fingers, drop this chunk
- return;
- }
- m_Available[x + m_Width * z] = Item;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cBiomeCache::cItem:
-
-cBiomeCache::cItem::cItem(int a_ChunkX, int a_ChunkZ) :
- m_ChunkX(a_ChunkX),
- m_ChunkZ(a_ChunkZ)
-{
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cBiomeCache::cThread:
-
-cBiomeCache::cThread::cThread(cBiomeCache & a_Parent) :
- super("Biome cache thread"),
- m_Parent(a_Parent)
-{
-}
-
-
-
-
-
-void cBiomeCache::cThread::Execute(void)
-{
- while (!m_ShouldTerminate && !m_Parent.m_IsTerminatingThreads)
- {
- m_Parent.thrProcessQueueItem();
- }
-}
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeCache.h b/Tools/BiomeVisualiser/BiomeCache.h
deleted file mode 100644
index da4d6c761..000000000
--- a/Tools/BiomeVisualiser/BiomeCache.h
+++ /dev/null
@@ -1,96 +0,0 @@
-
-// BiomeCache.h
-
-// Declares the cBiomeCache class representing a biome source that caches data from the underlying biome source
-
-/*
-This cache works a bit differently than regular caches.
-It first receives the hint of area that it will need to provide.
-The Cache uses several threads to request biomes from the underlying source to fill that area.
-While the area is being filled, requests for biomes may already come, such requests are answered with baLater if no data yet.
-*/
-
-#pragma once
-
-
-
-
-
-#include "BiomeSource.h"
-#include "../src/OSSupport/IsThread.h"
-
-
-
-
-
-class cBiomeCache :
- public cBiomeSource
-{
-public:
- cBiomeCache(void);
- ~cBiomeCache();
-
- // cBiomeSource overrides:
- virtual eAvailability GetBiome(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) override;
- virtual void HintViewArea(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ) override;
-
- void SetSource(cBiomeSource * a_Source); // Takes ownership of the source ptr
-
-protected:
- class cItem
- {
- public:
- cItem(int a_ChunkX, int a_ChunkZ);
-
- int m_ChunkX;
- int m_ChunkZ;
- bool m_IsValid;
- cChunkDef::BiomeMap m_Biomes;
- } ;
-
- typedef cItem * pItem;
- typedef std::list<pItem> cItems;
-
- class cThread :
- public cIsThread
- {
- typedef cIsThread super;
-
- public:
- cThread(cBiomeCache & a_Parent);
-
- // cIsThread overrides:
- virtual void Execute(void) override;
-
- protected:
- cBiomeCache & m_Parent;
- } ;
-
- typedef std::list<cThread *> cThreads;
-
- cBiomeSource * m_Source;
-
- cCriticalSection m_CS;
- int m_BaseX; ///< MinChunkX for the m_Available rectangle
- int m_BaseZ; ///< MinChunkZ for the m_Available rectangle
- int m_Width; ///< Width of the m_Available rectangle
- int m_Height; ///< Height of the m_Available rectangle
- pItem * m_Available; ///< Items that have already been processed (baNow or baNever), [x + m_Width * z]
- cItems m_Queue; ///< Items that are queued for processing (baLater)
- cItems m_Pool; ///< Items that are not needed anymore, can be reused for other coords
-
- cEvent m_evtQueued; // Triggerred when an item is added to m_Queue
-
- cThreads m_Threads; // Threads that update the cache.
- bool m_IsTerminatingThreads; // Set to true to indicate to all threads that they should exit
-
- /// Removes from a_Items all items that are outside of the given coords, moves those into m_Pool
- void FilterOutItems(cItems & a_Items, int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ);
-
- /// Processes one item from m_Queue into m_Available. Blocks if m_Queue is empty; respects m_IsTerminatingThreads
- void thrProcessQueueItem(void);
-} ;
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeColors.cpp b/Tools/BiomeVisualiser/BiomeColors.cpp
deleted file mode 100644
index 1fd0cb7a0..000000000
--- a/Tools/BiomeVisualiser/BiomeColors.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-
-// BiomeColors.cpp
-
-// Implements the g_BiomeColors[] array preparation based on a stored biome-to-color map
-
-#include "Globals.h"
-#include "BiomeColors.h"
-
-
-
-
-
-int g_BiomeColors[256];
-
-
-
-
-
-static struct
-{
- EMCSBiome Biome;
- int Color;
-} g_BiomeColorMap[] =
-{
- { biOcean, 0x000070 },
- { biPlains, 0x8db360 },
- { biDesert, 0xfa9418 },
- { biExtremeHills, 0x606060 },
- { biForest, 0x056621 },
- { biTaiga, 0x0b6659 },
- { biSwampland, 0x2fffda },
- { biRiver, 0x3030af },
- { biHell, 0x7f0000 },
- { biSky, 0x007fff },
- { biFrozenOcean, 0xa0a0df },
- { biFrozenRiver, 0xa0a0ff },
- { biIcePlains, 0xffffff },
- { biIceMountains, 0xa0a0a0 },
- { biMushroomIsland, 0xff00ff },
- { biMushroomShore, 0xa000ff },
- { biBeach, 0xfade55 },
- { biDesertHills, 0xd25f12 },
- { biForestHills, 0x22551c },
- { biTaigaHills, 0x163933 },
- { biExtremeHillsEdge, 0x7f8f7f },
- { biJungle, 0x537b09 },
- { biJungleHills, 0x2c4205 },
-
- { biJungleEdge, 0x628b17 },
- { biDeepOcean, 0x000030 },
- { biStoneBeach, 0xa2a284 },
- { biColdBeach, 0xfaf0c0 },
- { biBirchForest, 0x307444 },
- { biBirchForestHills, 0x1f5f32 },
- { biRoofedForest, 0x40511a },
- { biColdTaiga, 0x31554a },
- { biColdTaigaHills, 0x597d72 },
- { biMegaTaiga, 0x596651 },
- { biMegaTaigaHills, 0x596659 },
- { biExtremeHillsPlus, 0x507050 },
- { biSavanna, 0xbdb25f },
- { biSavannaPlateau, 0xa79d64 },
- { biMesa, 0xd94515 },
- { biMesaPlateauF, 0xb09765 },
- { biMesaPlateau, 0xca8c65 },
-
- // M variants:
- { biSunflowerPlains, 0xb5db88 },
- { biDesertM, 0xffbc40 },
- { biExtremeHillsM, 0x888888 },
- { biFlowerForest, 0x2d8e49 },
- { biTaigaM, 0x338e81 },
- { biSwamplandM, 0x07f9b2 },
- { biIcePlainsSpikes, 0xb4dcdc },
- { biJungleM, 0x7ba331 },
- { biJungleEdgeM, 0x628b17 },
- { biBirchForestM, 0x589c6c },
- { biBirchForestHillsM, 0x47875a },
- { biRoofedForestM, 0x687942 },
- { biColdTaigaM, 0x243f36 },
- { biMegaSpruceTaiga, 0x454f3e },
- { biMegaSpruceTaigaHills, 0x454f4e },
- { biExtremeHillsPlusM, 0x789878 },
- { biSavannaM, 0xe5da87 },
- { biSavannaPlateauM, 0xa79d74 },
- { biMesaBryce, 0xff6d3d },
- { biMesaPlateauFM, 0xd8bf8d },
- { biMesaPlateauM, 0xf2b48d },
-} ;
-
-
-
-
-
-static class cBiomeColorsInitializer
-{
-public:
- cBiomeColorsInitializer(void)
- {
- // Reset all colors to gray:
- for (size_t i = 0; i < ARRAYCOUNT(g_BiomeColors); i++)
- {
- g_BiomeColors[i] = 0x7f7f7f;
- }
- for (size_t i = 0; i < ARRAYCOUNT(g_BiomeColorMap); i++)
- {
- g_BiomeColors[g_BiomeColorMap[i].Biome] = g_BiomeColorMap[i].Color;
- }
- }
-} g_Initializer;
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeColors.h b/Tools/BiomeVisualiser/BiomeColors.h
deleted file mode 100644
index 0cb0f578c..000000000
--- a/Tools/BiomeVisualiser/BiomeColors.h
+++ /dev/null
@@ -1,15 +0,0 @@
-
-// BiomeColors.h
-
-// Declares the g_BiomeColors[] array used for biome color lookup
-
-
-
-
-
-extern int g_BiomeColors[256];
-
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeRenderer.cpp b/Tools/BiomeVisualiser/BiomeRenderer.cpp
deleted file mode 100644
index c0123c08a..000000000
--- a/Tools/BiomeVisualiser/BiomeRenderer.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-
-// BiomeRenderer.cpp
-
-// Implements the cBiomeRenderer class representing the rendering engine
-
-#include "Globals.h"
-#include "BiomeRenderer.h"
-#include "Pixmap.h"
-#include "Timer.h"
-#include "BiomeColors.h"
-
-
-
-
-
-cBiomeRenderer::cBiomeRenderer(void) :
- m_OriginX(160),
- m_OriginY(160),
- m_Zoom(1)
-{
-}
-
-
-
-
-void cBiomeRenderer::SetSource(cBiomeSource * a_Source)
-{
- m_Cache.SetSource(a_Source);
-}
-
-
-
-
-
-bool cBiomeRenderer::Render(cPixmap & a_Pixmap)
-{
- cTimer Timer("cBiomeRenderer::Render");
-
- int Wid = a_Pixmap.GetWidth();
- int Hei = a_Pixmap.GetHeight();
-
- // Hint the approximate view area to the biome source so that it can adjust its caches:
- int MinBlockX = ( - m_OriginX) * m_Zoom;
- int MaxBlockX = (Wid - m_OriginX) * m_Zoom;
- int MinBlockZ = ( - m_OriginY) * m_Zoom;
- int MaxBlockZ = (Hei - m_OriginY) * m_Zoom;
- m_Cache.HintViewArea(MinBlockX / 16 - 1, MaxBlockX / 16 + 1, MinBlockZ / 16 - 1, MaxBlockZ / 16 + 1);
-
- // Hold one current chunk of biome data:
- int CurChunkX = -10000;
- int CurChunkZ = -10000;
- cChunkDef::BiomeMap CurBiomes;
-
- bool res = false;
-
- for (int y = 0; y < Hei; y++)
- {
- int BlockZ = (y - m_OriginY) * m_Zoom;
- int ChunkZ = (BlockZ >= 0) ? (BlockZ / 16) : ((BlockZ + 1) / 16 - 1);
- int RelZ = BlockZ - ChunkZ * 16;
- for (int x = 0; x < Wid; x++)
- {
- int BlockX = (x - m_OriginX) * m_Zoom;
- int ChunkX = (BlockX >= 0) ? (BlockX / 16) : ((BlockX + 1) / 16 - 1);
- int RelX = BlockX - ChunkX * 16;
- if ((ChunkZ != CurChunkZ) || (ChunkX != CurChunkX))
- {
- CurChunkX = ChunkX;
- CurChunkZ = ChunkZ;
- switch (m_Cache.GetBiome(CurChunkX, CurChunkZ, CurBiomes))
- {
- case cBiomeSource::baLater:
- {
- res = true;
- // fallthrough:
- }
- case cBiomeSource::baNever:
- {
- for (int i = 0; i < ARRAYCOUNT(CurBiomes); i++)
- {
- CurBiomes[i] = biInvalidBiome;
- }
- break;
- }
- } // switch (Biome availability)
- }
- EMCSBiome Biome = cChunkDef::GetBiome(CurBiomes, RelX, RelZ);
- a_Pixmap.SetPixel(x, y, GetBiomeColor(Biome));
- } // for x
- } // for y
- return res;
-}
-
-
-
-
-
-int cBiomeRenderer::GetBiomeColor(EMCSBiome a_Biome)
-{
- if ((a_Biome < 0) || (a_Biome >= ARRAYCOUNT(g_BiomeColors)))
- {
- return 0xff0000;
- }
- return g_BiomeColors[a_Biome];
-}
-
-
-
-
-
-void cBiomeRenderer::MoveViewBy(int a_OffsX, int a_OffsY)
-{
- m_OriginX += a_OffsX;
- m_OriginY += a_OffsY;
-}
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeRenderer.h b/Tools/BiomeVisualiser/BiomeRenderer.h
deleted file mode 100644
index 752b61811..000000000
--- a/Tools/BiomeVisualiser/BiomeRenderer.h
+++ /dev/null
@@ -1,55 +0,0 @@
-
-// BiomeRenderer.h
-
-// Declares the cBiomeRenderer class representing the rendering engine
-
-
-
-
-
-#pragma once
-
-#include "BiomeCache.h"
-
-
-
-
-
-// fwd: Pixmap.h
-class cPixmap;
-
-
-
-
-
-class cBiomeRenderer
-{
-public:
- cBiomeRenderer(void);
-
- void SetSource(cBiomeSource * a_Source); // Takes ownership of the source
-
- /// Renders the biomes into the given pixmap. Returns true if some biome data was missing and can be retrieved later
- bool Render(cPixmap & a_Pixmap);
-
- /// Returns the RGB color value for the specified biome
- int GetBiomeColor(EMCSBiome a_Biome);
-
- void MoveViewBy(int a_OffsX, int a_OffsY);
-
- void SetZoom(int a_NewZoom)
- {
- m_Zoom = a_NewZoom;
- }
-
-protected:
- cBiomeCache m_Cache;
-
- int m_OriginX;
- int m_OriginY;
- int m_Zoom;
-} ;
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeSource.h b/Tools/BiomeVisualiser/BiomeSource.h
deleted file mode 100644
index 4a5153457..000000000
--- a/Tools/BiomeVisualiser/BiomeSource.h
+++ /dev/null
@@ -1,37 +0,0 @@
-
-// BiomeSource.h
-
-// Declares the cBiomeSource abstract class used as an interface for getting biomes from any source
-
-#pragma once
-
-
-
-
-
-#include "ChunkDef.h"
-
-
-
-
-
-class cBiomeSource abstract
-{
-public:
- enum eAvailability
- {
- baNow, // Data returned now
- baLater, // Data not returned, but will be available later, try again after a while
- baNever, // Data not returned, will not be available at all
- } ;
-
- /// Fills a_Biomes with the biomes for the chunk specified
- virtual eAvailability GetBiome(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) = 0;
-
- /// Used to inform the source about the view area that will be queried in the near future.
- virtual void HintViewArea(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ) = 0;
-} ;
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeViewWnd.cpp b/Tools/BiomeVisualiser/BiomeViewWnd.cpp
deleted file mode 100644
index 7fb61c062..000000000
--- a/Tools/BiomeVisualiser/BiomeViewWnd.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-
-// BiomeViewWnd.cpp
-
-// Implements the cBiomeViewWnd class representing the window that displays biomes
-
-#include "Globals.h"
-#include "BiomeViewWnd.h"
-#include "BiomeCache.h"
-#include "GeneratorBiomeSource.h"
-#include "iniFile/iniFile.h"
-
-
-
-
-
-const int TIMER_RERENDER = 1200;
-
-
-
-
-
-cBiomeViewWnd::cBiomeViewWnd(void) :
- m_Wnd(NULL),
- m_Thunk(&cBiomeViewWnd::WndProc, this),
- m_IsLButtonDown(false)
-{
-}
-
-
-
-
-
-bool cBiomeViewWnd::Create(HWND a_ParentWnd, LPCTSTR a_Title)
-{
- ASSERT(m_Wnd == NULL);
-
- InitBiomeView();
-
- // Create a regular STATIC window, then override its window procedure with our own. No need for obnoxious RegisterWindowClass() stuff.
- m_Wnd = CreateWindow("STATIC", a_Title, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 400, 300, a_ParentWnd, NULL, GetModuleHandle(NULL), NULL);
- if (m_Wnd == NULL)
- {
- LOGERROR("Cannot create main window: %d", GetLastError());
- return false;
- }
- SetWindowLongPtr(m_Wnd, GWLP_WNDPROC, m_Thunk);
-
- return true;
-}
-
-
-
-
-
-void cBiomeViewWnd::InitBiomeView(void)
-{
- cIniFile IniFile;
- IniFile.ReadFile("world.ini");
- int Seed = IniFile.GetValueSetI("Generator", "Seed", 0);
- bool CacheOffByDefault = false;
- m_BiomeGen = cBiomeGen::CreateBiomeGen(IniFile, Seed, CacheOffByDefault);
- m_Renderer.SetSource(new cGeneratorBiomeSource(m_BiomeGen));
- IniFile.WriteFile("world.ini");
-}
-
-
-
-
-
-void cBiomeViewWnd::SetZoom(int a_NewZoom)
-{
- m_Renderer.SetZoom(a_NewZoom);
- Redraw();
-}
-
-
-
-
-
-void cBiomeViewWnd::Redraw(void)
-{
- if (m_Renderer.Render(m_Pixmap))
- {
- SetTimer(m_Wnd, TIMER_RERENDER, 200, NULL);
- }
- InvalidateRect(m_Wnd, NULL, FALSE);
-}
-
-
-
-
-
-LRESULT cBiomeViewWnd::WndProc(HWND a_Wnd, UINT a_Msg, WPARAM wParam, LPARAM lParam)
-{
- switch (a_Msg)
- {
- case WM_CHAR: return OnChar (wParam, lParam);
- case WM_CLOSE: return OnClose ();
- case WM_COMMAND: return OnCommand (wParam, lParam);
- case WM_LBUTTONDOWN: return OnLButtonDown(wParam, lParam);
- case WM_LBUTTONUP: return OnLButtonUp (wParam, lParam);
- case WM_MOUSEMOVE: return OnMouseMove (wParam, lParam);
- case WM_PAINT: return OnPaint ();
- case WM_TIMER: return OnTimer (wParam);
- }
- return ::DefWindowProc(a_Wnd, a_Msg, wParam, lParam);
-}
-
-
-
-
-
-LRESULT cBiomeViewWnd::OnChar(WPARAM wParam, LPARAM lParam)
-{
- switch (wParam)
- {
- case '1': SetZoom(1); break;
- case '2': SetZoom(2); break;
- case '3': SetZoom(3); break;
- case '4': SetZoom(4); break;
- case '5': SetZoom(5); break;
- case '6': SetZoom(6); break;
- case '7': SetZoom(7); break;
- case '8': SetZoom(8); break;
- case 27:
- {
- // Esc pressed, exit
- PostQuitMessage(0);
- break;
- }
- }
- return 0;
-}
-
-
-
-
-
-LRESULT cBiomeViewWnd::OnClose(void)
-{
- PostQuitMessage(0);
- return 0;
-}
-
-
-
-
-
-LRESULT cBiomeViewWnd::OnCommand(WPARAM wParam, LPARAM lParam)
-{
- // TODO: Handle menu commands, when we get menu
- return 0;
-}
-
-
-
-
-
-LRESULT cBiomeViewWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam)
-{
- m_IsLButtonDown = true;
- GetCursorPos(&m_MouseDown);
- return 0;
-}
-
-
-
-
-
-LRESULT cBiomeViewWnd::OnMouseMove(WPARAM wParam, LPARAM lParam)
-{
- if (!m_IsLButtonDown)
- {
- return 0;
- }
- POINT pnt;
- GetCursorPos(&pnt);
- m_Renderer.MoveViewBy(pnt.x - m_MouseDown.x, pnt.y - m_MouseDown.y);
- m_MouseDown = pnt;
- Redraw();
- return 0;
-}
-
-
-
-
-
-LRESULT cBiomeViewWnd::OnLButtonUp(WPARAM wParam, LPARAM lParam)
-{
- OnMouseMove(wParam, lParam); // Last movement - if the mouse move hasn't been reported due to speed
- m_IsLButtonDown = false;
- InvalidateRect(m_Wnd, NULL, FALSE);
- return 0;
-}
-
-
-
-
-
-LRESULT cBiomeViewWnd::OnPaint(void)
-{
- PAINTSTRUCT ps;
- HDC DC = BeginPaint(m_Wnd, &ps);
-
- RECT rc;
- GetClientRect(m_Wnd, &rc);
- int Wid = rc.right - rc.left;
- int Hei = rc.bottom - rc.top;
- if ((m_Pixmap.GetWidth() != Wid) || (m_Pixmap.GetHeight() != Hei))
- {
- m_Pixmap.SetSize(Wid, Hei);
- if (m_Renderer.Render(m_Pixmap))
- {
- SetTimer(m_Wnd, TIMER_RERENDER, 200, NULL);
- }
- }
-
- m_Pixmap.DrawToDC(DC, 0, 0);
-
- EndPaint(m_Wnd, &ps);
- return 0;
-}
-
-
-
-
-
-LRESULT cBiomeViewWnd::OnTimer(WPARAM wParam)
-{
- switch (wParam)
- {
- case TIMER_RERENDER:
- {
- if (!m_Renderer.Render(m_Pixmap))
- {
- KillTimer(m_Wnd, TIMER_RERENDER);
- }
- InvalidateRect(m_Wnd, NULL, FALSE);
- break;
- }
- }
- return 0;
-}
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeViewWnd.h b/Tools/BiomeVisualiser/BiomeViewWnd.h
deleted file mode 100644
index 70c5e38f2..000000000
--- a/Tools/BiomeVisualiser/BiomeViewWnd.h
+++ /dev/null
@@ -1,69 +0,0 @@
-
-// BiomeViewWnd.h
-
-// Declares the cBiomeViewWnd class representing the window that displays biomes
-
-
-
-
-
-#pragma once
-
-#include "WndProcThunk.h"
-#include "BiomeRenderer.h"
-#include "BiomeCache.h"
-#include "Pixmap.h"
-
-
-
-
-
-// fwd:
-class cBiomeGen;
-
-
-
-
-
-class cBiomeViewWnd
-{
-public:
- cBiomeViewWnd(void);
-
- bool Create(HWND a_ParentWnd, LPCTSTR a_Title);
-
-protected:
- HWND m_Wnd;
- CWndProcThunk<cBiomeViewWnd> m_Thunk;
-
- cBiomeRenderer m_Renderer;
- cPixmap m_Pixmap;
-
- /// The generator that is to be visualised
- cBiomeGen * m_BiomeGen;
-
- bool m_IsLButtonDown;
- POINT m_MouseDown;
-
-
- void InitBiomeView(void);
-
- void SetZoom(int a_NewZoom);
- void Redraw(void);
-
- LRESULT WndProc(HWND a_Wnd, UINT a_Msg, WPARAM wParam, LPARAM lParam);
-
- // Message handlers:
- LRESULT OnChar (WPARAM wParam, LPARAM lParam);
- LRESULT OnClose (void);
- LRESULT OnCommand (WPARAM wParam, LPARAM lParam);
- LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);
- LRESULT OnMouseMove (WPARAM wParam, LPARAM lParam);
- LRESULT OnLButtonUp (WPARAM wParam, LPARAM lParam);
- LRESULT OnPaint (void);
- LRESULT OnTimer (WPARAM wParam);
-} ;
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeVisualiser.cpp b/Tools/BiomeVisualiser/BiomeVisualiser.cpp
deleted file mode 100644
index a36111d77..000000000
--- a/Tools/BiomeVisualiser/BiomeVisualiser.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-
-// BiomeVisualiser.cpp
-
-// Implements the cBiomeVisualiser class representing the entire app. Also implements the WinMain() entrypoint
-
-#include "Globals.h"
-#include "time.h"
-#include "BiomeVisualiser.h"
-
-
-
-
-
-int WINAPI WinMain(HINSTANCE a_Instance, HINSTANCE a_PrevInstance, LPSTR a_CmdLine, int a_ShowCmd)
-{
- cBiomeVisualiser App;
- return App.Run();
-}
-
-
-
-
-
-cBiomeVisualiser::cBiomeVisualiser(void) :
- m_Logger(new cMCLogger(Printf("BiomeVisualiser_%08x.log", time(NULL))))
-{
-}
-
-
-
-
-
-int cBiomeVisualiser::Run(void)
-{
- if (!m_MainWnd.Create(GetDesktopWindow(), TEXT("BiomeVisualiser")))
- {
- LOGERROR("Cannot create main window: %d", GetLastError());
- return 1;
- }
-
- MSG msg;
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- } // while (GetMessage)
- return msg.lParam;
-}
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeVisualiser.h b/Tools/BiomeVisualiser/BiomeVisualiser.h
deleted file mode 100644
index 4f8ce7513..000000000
--- a/Tools/BiomeVisualiser/BiomeVisualiser.h
+++ /dev/null
@@ -1,31 +0,0 @@
-
-// BiomeVisualiser.h
-
-// Declares the cBiomeVisualiser class representing the entire application
-
-
-
-
-
-#include "BiomeViewWnd.h"
-
-
-
-
-
-class cBiomeVisualiser
-{
-public:
- cBiomeVisualiser(void);
-
- int Run(void);
-
-protected:
- cBiomeViewWnd m_MainWnd;
-
- cMCLogger * m_Logger;
-} ;
-
-
-
-
diff --git a/Tools/BiomeVisualiser/BiomeVisualiser.sln b/Tools/BiomeVisualiser/BiomeVisualiser.sln
deleted file mode 100644
index bdfb586b1..000000000
--- a/Tools/BiomeVisualiser/BiomeVisualiser.sln
+++ /dev/null
@@ -1,23 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual C++ Express 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BiomeVisualiser", "BiomeVisualiser.vcproj", "{6DF3D88B-AD47-45B6-B831-1BDE74F86B5C}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release profiled|Win32 = Release profiled|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {6DF3D88B-AD47-45B6-B831-1BDE74F86B5C}.Debug|Win32.ActiveCfg = Debug|Win32
- {6DF3D88B-AD47-45B6-B831-1BDE74F86B5C}.Debug|Win32.Build.0 = Debug|Win32
- {6DF3D88B-AD47-45B6-B831-1BDE74F86B5C}.Release profiled|Win32.ActiveCfg = Release profiled|Win32
- {6DF3D88B-AD47-45B6-B831-1BDE74F86B5C}.Release profiled|Win32.Build.0 = Release profiled|Win32
- {6DF3D88B-AD47-45B6-B831-1BDE74F86B5C}.Release|Win32.ActiveCfg = Release|Win32
- {6DF3D88B-AD47-45B6-B831-1BDE74F86B5C}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/Tools/BiomeVisualiser/BiomeVisualiser.vcproj b/Tools/BiomeVisualiser/BiomeVisualiser.vcproj
deleted file mode 100644
index 3de564ad4..000000000
--- a/Tools/BiomeVisualiser/BiomeVisualiser.vcproj
+++ /dev/null
@@ -1,527 +0,0 @@
-<?xml version="1.0" encoding="windows-1250"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9,00"
- Name="BiomeVisualiser"
- ProjectGUID="{6DF3D88B-AD47-45B6-B831-1BDE74F86B5C}"
- RootNamespace="BiomeVisualiser"
- Keyword="Win32Proj"
- TargetFrameworkVersion="196613"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="../../src;../../lib"
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- UsePrecompiledHeader="2"
- PrecompiledHeaderThrough="Globals.h"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="2"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="2"
- EnableIntrinsicFunctions="true"
- FavorSizeOrSpeed="1"
- AdditionalIncludeDirectories="../../src;../../lib"
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- EnableEnhancedInstructionSet="2"
- UsePrecompiledHeader="2"
- PrecompiledHeaderThrough="Globals.h"
- WarningLevel="3"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib"
- LinkIncremental="1"
- GenerateDebugInformation="true"
- SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release profiled|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="2"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="2"
- EnableIntrinsicFunctions="true"
- FavorSizeOrSpeed="1"
- AdditionalIncludeDirectories="../../src;../../lib"
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- EnableEnhancedInstructionSet="2"
- UsePrecompiledHeader="2"
- PrecompiledHeaderThrough="Globals.h"
- WarningLevel="3"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib"
- LinkIncremental="1"
- GenerateDebugInformation="true"
- SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- Profile="true"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath=".\BiomeCache.cpp"
- >
- </File>
- <File
- RelativePath=".\BiomeCache.h"
- >
- </File>
- <File
- RelativePath=".\BiomeColors.cpp"
- >
- </File>
- <File
- RelativePath=".\BiomeColors.h"
- >
- </File>
- <File
- RelativePath=".\BiomeRenderer.cpp"
- >
- </File>
- <File
- RelativePath=".\BiomeRenderer.h"
- >
- </File>
- <File
- RelativePath=".\BiomeSource.h"
- >
- </File>
- <File
- RelativePath=".\BiomeViewWnd.cpp"
- >
- </File>
- <File
- RelativePath=".\BiomeViewWnd.h"
- >
- </File>
- <File
- RelativePath=".\BiomeVisualiser.cpp"
- >
- </File>
- <File
- RelativePath=".\BiomeVisualiser.h"
- >
- </File>
- <File
- RelativePath=".\GeneratorBiomeSource.h"
- >
- </File>
- <File
- RelativePath=".\Pixmap.cpp"
- >
- </File>
- <File
- RelativePath=".\Pixmap.h"
- >
- </File>
- <File
- RelativePath=".\Timer.h"
- >
- </File>
- <File
- RelativePath=".\WndProcThunk.h"
- >
- </File>
- <Filter
- Name="Shared"
- >
- <File
- RelativePath="..\..\src\BiomeDef.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\BiomeDef.h"
- >
- </File>
- <File
- RelativePath="..\..\src\BlockID.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\BlockID.h"
- >
- </File>
- <File
- RelativePath="..\..\src\ChunkDef.h"
- >
- </File>
- <File
- RelativePath="..\..\src\Enchantments.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\Enchantments.h"
- >
- </File>
- <File
- RelativePath="..\..\src\WorldStorage\FastNBT.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\WorldStorage\FastNBT.h"
- >
- </File>
- <File
- RelativePath="..\..\src\FastRandom.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\FastRandom.h"
- >
- </File>
- <File
- RelativePath="..\..\src\Globals.cpp"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- UsePrecompiledHeader="1"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- UsePrecompiledHeader="1"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release profiled|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- UsePrecompiledHeader="1"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\..\src\Globals.h"
- >
- </File>
- <File
- RelativePath="..\..\src\Item.h"
- >
- </File>
- <File
- RelativePath="..\..\src\Log.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\Log.h"
- >
- </File>
- <File
- RelativePath="..\..\src\MCLogger.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\MCLogger.h"
- >
- </File>
- <File
- RelativePath="..\..\src\Noise.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\Noise.h"
- >
- </File>
- <File
- RelativePath="..\..\src\Noise.inc"
- >
- </File>
- <File
- RelativePath="..\..\src\StringUtils.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\StringUtils.h"
- >
- </File>
- <File
- RelativePath="..\..\src\VoronoiMap.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\VoronoiMap.h"
- >
- </File>
- <Filter
- Name="OSSupport"
- >
- <File
- RelativePath="..\..\src\OSSupport\CriticalSection.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\CriticalSection.h"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\Event.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\Event.h"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\File.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\File.h"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\IsThread.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\IsThread.h"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\Sleep.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Generating"
- >
- <File
- RelativePath="..\..\src\Generating\BioGen.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\Generating\BioGen.h"
- >
- </File>
- <File
- RelativePath="..\..\src\Generating\ComposableGenerator.h"
- >
- </File>
- </Filter>
- <Filter
- Name="iniFile"
- >
- <File
- RelativePath="..\..\lib\iniFile\iniFile.cpp"
- >
- </File>
- <File
- RelativePath="..\..\lib\iniFile\iniFile.h"
- >
- </File>
- </Filter>
- </Filter>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/Tools/BiomeVisualiser/GeneratorBiomeSource.h b/Tools/BiomeVisualiser/GeneratorBiomeSource.h
deleted file mode 100644
index 751aed245..000000000
--- a/Tools/BiomeVisualiser/GeneratorBiomeSource.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-// GeneratorBiomeSource.h
-
-// Declares the cGeneratorBiomeSource that adapts a cBiomeGen into a cBiomeSource
-
-#include "../src/Generating/BioGen.h"
-#include "BiomeSource.h"
-
-
-
-
-
-class cGeneratorBiomeSource :
- public cBiomeSource
-{
-public:
- cGeneratorBiomeSource(cBiomeGen * a_Generator) : m_Generator(a_Generator) {} // Takes ownership of the generator ptr
-
- ~cGeneratorBiomeSource()
- {
- delete m_Generator;
- }
-
- // cBiomeSource overrides:
- virtual eAvailability GetBiome(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) override
- {
- m_Generator->GenBiomes(a_ChunkX, a_ChunkZ, a_Biomes);
- return baNow;
- }
-
- virtual void HintViewArea(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ) override
- {
- // Nothing needed
- }
-
-protected:
- cBiomeGen * m_Generator;
-} ;
-
-
-
-
diff --git a/Tools/BiomeVisualiser/Pixmap.cpp b/Tools/BiomeVisualiser/Pixmap.cpp
deleted file mode 100644
index 1a80cf465..000000000
--- a/Tools/BiomeVisualiser/Pixmap.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-
-// Pixmap.cpp
-
-// Implements the cPixmap class that represents a RGB pixmap and allows simple operations on it
-
-#include "Globals.h"
-#include "Pixmap.h"
-
-
-
-
-
-cPixmap::cPixmap(void) :
- m_Width(0),
- m_Height(0),
- m_Stride(0),
- m_Pixels(NULL)
-{
-}
-
-
-
-
-
-cPixmap::cPixmap(int a_Width, int a_Height) :
- m_Width(0),
- m_Height(0),
- m_Stride(0),
- m_Pixels(NULL)
-{
- SetSize(a_Width, a_Height);
-}
-
-
-
-
-
-cPixmap::~cPixmap()
-{
- delete m_Pixels;
-}
-
-
-
-
-
-void cPixmap::SetSize(int a_Width, int a_Height)
-{
- delete m_Pixels;
- m_Pixels = new int[a_Width * a_Height];
- m_Width = a_Width;
- m_Height = a_Height;
- m_Stride = m_Width; // Currently we don't need a special stride value, but let's support it for the future :)
-}
-
-
-
-
-
-void cPixmap::SetPixel(int a_X, int a_Y, int a_Color)
-{
- ASSERT(a_X >= 0);
- ASSERT(a_X < m_Width);
- ASSERT(a_Y >= 0);
- ASSERT(a_Y < m_Height);
-
- m_Pixels[a_X + a_Y * m_Stride] = a_Color;
-}
-
-
-
-
-
-int cPixmap::GetPixel(int a_X, int a_Y) const
-{
- ASSERT(a_X >= 0);
- ASSERT(a_X < m_Width);
- ASSERT(a_Y >= 0);
- ASSERT(a_Y < m_Height);
-
- return m_Pixels[a_X + a_Y * m_Stride];
-}
-
-
-
-
-
-void cPixmap::Fill(int a_Color)
-{
- int NumElements = m_Height * m_Stride;
- for (int i = 0; i < NumElements; i++)
- {
- m_Pixels[i] = a_Color;
- }
-}
-
-
-
-
-
-void cPixmap::DrawToDC(HDC a_DC, int a_OriginX, int a_OriginY)
-{
- BITMAPINFO bmi;
- bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
- bmi.bmiHeader.biWidth = m_Width;
- bmi.bmiHeader.biHeight = -m_Height; // Negative, we are top-down, unlike BMPs
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = m_Stride * m_Height * 4;
- bmi.bmiHeader.biXPelsPerMeter = 1440;
- bmi.bmiHeader.biYPelsPerMeter = 1440;
- bmi.bmiHeader.biClrUsed = 0;
- bmi.bmiHeader.biClrImportant = 0;
- SetDIBitsToDevice(a_DC, a_OriginX, a_OriginY, m_Width, m_Height, 0, 0, 0, m_Height, m_Pixels, &bmi, DIB_RGB_COLORS);
-}
-
-
-
-
diff --git a/Tools/BiomeVisualiser/Pixmap.h b/Tools/BiomeVisualiser/Pixmap.h
deleted file mode 100644
index e50f6e946..000000000
--- a/Tools/BiomeVisualiser/Pixmap.h
+++ /dev/null
@@ -1,39 +0,0 @@
-
-// Pixmap.h
-
-// Declares a cPixmap class that represents a RGB pixmap and allows simple operations on it
-
-#pragma once
-
-
-
-
-
-class cPixmap
-{
-public:
- cPixmap(void);
- cPixmap(int a_Width, int a_Height);
- ~cPixmap();
-
- void SetSize(int a_Width, int a_Height);
-
- int GetWidth (void) const { return m_Width; }
- int GetHeight(void) const { return m_Height; }
-
- void SetPixel(int a_X, int a_Y, int a_Color);
- int GetPixel(int a_X, int a_Y) const;
- void Fill(int a_Color);
-
- void DrawToDC(HDC a_DC, int a_OriginX, int a_OriginY);
-
-protected:
- int m_Width;
- int m_Height;
- int m_Stride;
- int * m_Pixels;
-} ;
-
-
-
-
diff --git a/Tools/BiomeVisualiser/Timer.h b/Tools/BiomeVisualiser/Timer.h
deleted file mode 100644
index 78c4b42c7..000000000
--- a/Tools/BiomeVisualiser/Timer.h
+++ /dev/null
@@ -1,40 +0,0 @@
-
-// Timer.h
-
-// Declares the cTimer class representing a RAII class that measures time from its creation till its destruction
-
-
-
-
-
-#pragma once
-
-#include "time.h"
-
-
-
-
-
-class cTimer
-{
-public:
- cTimer(const AString & a_Title) :
- m_Title(a_Title),
- m_StartTime(clock())
- {
- }
-
- ~cTimer()
- {
- clock_t NumTicks = clock() - m_StartTime;
- LOG("%s took %d ticks (%.02f sec)", m_Title.c_str(), NumTicks, (double)NumTicks / CLOCKS_PER_SEC);
- }
-
-protected:
- AString m_Title;
- clock_t m_StartTime;
-} ;
-
-
-
-
diff --git a/Tools/BiomeVisualiser/WndProcThunk.h b/Tools/BiomeVisualiser/WndProcThunk.h
deleted file mode 100644
index da995eb5f..000000000
--- a/Tools/BiomeVisualiser/WndProcThunk.h
+++ /dev/null
@@ -1,143 +0,0 @@
-
-// WndProcThunk.h
-
-// Interfaces to the CWndProcThunk class responsible for WNDPROC class-thunking
-// For details, see http://www.hackcraft.net/cpp/windowsThunk/thiscall/
-// Also available is a CDlgProcThunk class doing the same work for DIALOGPROC
-
-// MD: Made NX-compat by allocating the code structure using VirtualAlloc(..., PAGE_EXECUTE_READWRITE)
-
-
-
-
-
-// fwd:
-template <class W> class CWndProcThunk;
-
-
-
-
-
-#ifndef WNDPROCTHUNK_H_INCLUDED
-#define WNDPROCTHUNK_H_INCLUDED
-
-
-
-
-template<typename To, typename From> inline To union_cast(From fr) throw()
-{
- union
- {
- From f;
- To t;
- } uc;
- uc.f = fr;
- return uc.t;
-}
-
-
-
-
-
-#pragma warning(push)
-#pragma warning(disable : 4355)
-
-#if defined(_M_IX86)
-
-#pragma pack(push,1)
-
-template <class W> class CWndProcThunk
-{
- typedef ::LRESULT (W::* WndProc)(::HWND, ::UINT, ::WPARAM, ::LPARAM);
- typedef CWndProcThunk ThisClass;
-
- struct SCode
- {
- BYTE m_mov; // mov ECX, m_this
- W * m_this; //
- BYTE m_jmp; // jmp m_relproc
- ptrdiff_t m_relproc; // relative jmp
- };
-
- SCode * Code;
-
-public:
- ThisClass(WndProc proc, W * obj)
- {
- Code = (SCode *)VirtualAlloc(NULL, sizeof(SCode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- Code->m_mov = 0xB9,
- Code->m_this = obj,
- Code->m_jmp = 0xE9,
- Code->m_relproc = union_cast<char *>(proc) - reinterpret_cast<char *>(Code) - sizeof(*Code);
- ::FlushInstructionCache(::GetCurrentProcess(), Code, sizeof(*Code));
- }
-
- virtual ~CWndProcThunk()
- {
- VirtualFree(Code, sizeof(*Code), MEM_RELEASE);
- Code = NULL;
- }
-
- operator ::WNDPROC() const {return reinterpret_cast<::WNDPROC>(Code); }
- operator ::LONG_PTR() const {return reinterpret_cast<::LONG_PTR>(Code); }
-} ;
-
-
-
-
-
-template <class W> class CDlgProcThunk
-{
- typedef ::BOOL (W::* DlgProc)(::HWND, ::UINT, ::WPARAM, ::LPARAM);
- typedef CDlgProcThunk ThisClass;
-
- struct SCode
- {
- BYTE m_mov; // mov ECX, m_this
- W * m_this; //
- BYTE m_jmp; // jmp m_relproc
- ptrdiff_t m_relproc; // relative jmp
- };
-
- SCode * Code;
-
-public:
- CDlgProcThunk(DlgProc proc, W * obj)
- {
- Code = (SCode *)VirtualAlloc(NULL, sizeof(SCode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- Code->m_mov = 0xB9,
- Code->m_this = obj,
- Code->m_jmp = 0xE9,
- Code->m_relproc = union_cast<char *>(proc) - reinterpret_cast<char *>(Code) - sizeof(*Code);
- ::FlushInstructionCache(::GetCurrentProcess(), Code, sizeof(*Code));
- }
-
- virtual ~CDlgProcThunk()
- {
- VirtualFree(Code, sizeof(*Code), MEM_RELEASE);
- Code = NULL;
- }
-
- operator ::DLGPROC() const {return reinterpret_cast<::DLGPROC>(Code); }
- operator ::LONG_PTR() const {return reinterpret_cast<::LONG_PTR>(Code); }
-} ;
-
-
-
-
-
- #pragma pack(pop)
-
-#else // _M_IX86
- #error Only X86 supported
-#endif
-
-
-
-
-
-#endif // WNDPROCTHUNK_H_INCLUDED
-
-
-
-
diff --git a/Tools/BiomeVisualiser/profile_run.cmd b/Tools/BiomeVisualiser/profile_run.cmd
deleted file mode 100644
index d4826d06a..000000000
--- a/Tools/BiomeVisualiser/profile_run.cmd
+++ /dev/null
@@ -1,70 +0,0 @@
-@echo off
-::
-:: Profiling using a MSVC standalone profiler
-::
-:: See http://www.codeproject.com/Articles/144643/Profiling-of-C-Applications-in-Visual-Studio-for-F for details
-::
-
-
-
-
-set pt="C:\Program Files\Microsoft Visual Studio 9.0\Team Tools\Performance Tools"
-set appdir="Release profiled"
-set app="Release profiled\BiomeVisualiser.exe"
-set args=""
-
-:: outputdir is relative to appdir!
-set outputdir=Profiling
-set output=profile.vsp
-
-
-
-
-
-::Create the output directory, if it didn't exist
-mkdir %outputdir%
-
-
-
-
-
-:: Start the profiler
-%pt%\vsperfcmd /start:sample /output:%outputdir%\%output%
-if errorlevel 1 goto haderror
-
-:: Launch the application via the profiler
-%pt%\vsperfcmd /launch:%app% /args:%args%
-if errorlevel 1 goto haderror
-
-:: Shut down the profiler (this command waits, until the application is terminated)
-%pt%\vsperfcmd /shutdown
-if errorlevel 1 goto haderror
-
-
-
-
-
-:: cd to outputdir, so that the reports are generated there
-cd %outputdir%
-
-:: generate the report files (.csv)
-%pt%\vsperfreport /summary:all %output% /symbolpath:"srv*C:\Programovani\Symbols*http://msdl.microsoft.com/download/symbols"
-if errorlevel 1 goto haderror
-
-
-
-
-
-goto finished
-
-
-
-
-:haderror
-echo An error was encountered
-pause
-
-
-
-
-:finished
diff --git a/Tools/QtBiomeVisualiser/.gitignore b/Tools/QtBiomeVisualiser/.gitignore
new file mode 100644
index 000000000..c1b62a8a7
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/.gitignore
@@ -0,0 +1,2 @@
+*.pro.user
+*.pro.user.*
diff --git a/Tools/QtBiomeVisualiser/BiomeView.cpp b/Tools/QtBiomeVisualiser/BiomeView.cpp
new file mode 100644
index 000000000..bbaccb369
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/BiomeView.cpp
@@ -0,0 +1,427 @@
+#include "Globals.h"
+#include "BiomeView.h"
+#include "Chunk.h"
+#include <QPainter>
+#include <QResizeEvent>
+
+
+
+
+
+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_IsMouseDragging(false),
+ m_MouseWheelDelta(0)
+{
+ // Create the image used for undefined chunks:
+ int offset = 0;
+ for (int y = 0; y < 16; y++)
+ {
+ for (int x = 0; x < 16; x++)
+ {
+ uchar color = (((x & 8) ^ (y & 8)) == 0) ? 0x44 : 0x88;
+ m_EmptyChunkImage[offset++] = color;
+ m_EmptyChunkImage[offset++] = color;
+ m_EmptyChunkImage[offset++] = color;
+ m_EmptyChunkImage[offset++] = 0xff;
+ }
+ }
+
+ // Create the startup image:
+ redraw();
+
+ // Add a chunk-update callback mechanism:
+ connect(&m_Cache, SIGNAL(chunkAvailable(int, int)), this, SLOT(chunkAvailable(int, int)));
+
+ // Allow keyboard interaction:
+ setFocusPolicy(Qt::StrongFocus);
+}
+
+
+
+
+QSize BiomeView::minimumSizeHint() const
+{
+ return QSize(300, 300);
+}
+
+
+
+
+
+QSize BiomeView::sizeHint() const
+{
+ return QSize(800, 600);
+}
+
+
+
+
+
+void BiomeView::setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource)
+{
+ // Replace the source in the cache:
+ m_Cache.setChunkSource(a_ChunkSource);
+
+ // Redraw with the new source:
+ redraw();
+}
+
+
+
+
+
+void BiomeView::redraw()
+{
+ if (!hasData())
+ {
+ // No data means no image is displayed, no need to compose:
+ update();
+ return;
+ }
+
+ int chunksize = 16 * m_Zoom;
+
+ // first find the center block position
+ int centerchunkx = floor(m_X / 16);
+ int centerchunkz = floor(m_Z / 16);
+ // and the center of the screen
+ int centerx = m_Image.width() / 2;
+ int centery = m_Image.height() / 2;
+ // and align for panning
+ centerx -= (m_X - centerchunkx * 16) * m_Zoom;
+ centery -= (m_Z - centerchunkz * 16) * m_Zoom;
+ // now calculate the topleft block on the screen
+ int startx = centerchunkx - centerx / chunksize - 1;
+ int startz = centerchunkz - centery / chunksize - 1;
+ // and the dimensions of the screen in blocks
+ int blockswide = m_Image.width() / chunksize + 3;
+ int blockstall = m_Image.height() / chunksize + 3;
+
+ for (int z = startz; z < startz + blockstall; z++)
+ {
+ for (int x = startx; x < startx + blockswide; x++)
+ {
+ drawChunk(x, z);
+ }
+ }
+ update();
+}
+
+
+
+
+
+void BiomeView::chunkAvailable(int a_ChunkX, int a_ChunkZ)
+{
+ drawChunk(a_ChunkX, a_ChunkZ);
+ update();
+}
+
+
+
+
+
+void BiomeView::reload()
+{
+ if (!hasData())
+ {
+ return;
+ }
+ m_Cache.reload();
+
+ redraw();
+}
+
+
+
+
+
+void BiomeView::drawChunk(int a_ChunkX, int a_ChunkZ)
+{
+ if (!hasData())
+ {
+ return;
+ }
+
+ //fetch the chunk:
+ ChunkPtr chunk = m_Cache.fetch(a_ChunkX, a_ChunkZ);
+
+ // Figure out where on the screen this chunk should be drawn:
+ // first find the center chunk
+ int centerchunkx = floor(m_X / 16);
+ int centerchunkz = floor(m_Z / 16);
+ // and the center chunk screen coordinates
+ int centerx = m_Image.width() / 2;
+ int centery = m_Image.height() / 2;
+ // which need to be shifted to account for panning inside that chunk
+ centerx -= (m_X - centerchunkx * 16) * m_Zoom;
+ centery -= (m_Z - centerchunkz * 16) * m_Zoom;
+ // centerx,y now points to the top left corner of the center chunk
+ // so now calculate our x,y in relation
+ double chunksize = 16 * m_Zoom;
+ centerx += (a_ChunkX - centerchunkx) * chunksize;
+ centery += (a_ChunkZ - centerchunkz) * chunksize;
+
+ int srcoffset = 0;
+ uchar * bits = m_Image.bits();
+ int imgstride = m_Image.bytesPerLine();
+
+ int skipx = 0,skipy = 0;
+ int blockwidth = chunksize, blockheight = chunksize;
+ // now if we're off the screen we need to crop
+ if (centerx < 0)
+ {
+ skipx = -centerx;
+ centerx = 0;
+ }
+ if (centery < 0)
+ {
+ skipy = -centery;
+ centery = 0;
+ }
+ // or the other side, we need to trim
+ if (centerx + blockwidth > m_Image.width())
+ {
+ blockwidth = m_Image.width() - centerx;
+ }
+ if (centery + blockheight > m_Image.height())
+ {
+ blockheight = m_Image.height() - centery;
+ }
+ if ((blockwidth <= 0) || (skipx >= blockwidth))
+ {
+ return;
+ }
+ int imgoffset = centerx * 4 + centery * imgstride;
+
+ // If the chunk is valid, use its data; otherwise use the empty placeholder:
+ const uchar * src = m_EmptyChunkImage;
+ if (chunk.get() != nullptr)
+ {
+ src = chunk->getImage();
+ }
+
+ // Blit or scale-blit the image:
+ for (int z = skipy; z < blockheight; z++, imgoffset += imgstride)
+ {
+ srcoffset = floor((double)z / m_Zoom) * 16 * 4;
+ if (m_Zoom == 1.0)
+ {
+ memcpy(bits + imgoffset, src + srcoffset + skipx * 4, (blockwidth - skipx) * 4);
+ }
+ else
+ {
+ int xofs = 0;
+ for (int x = skipx; x < blockwidth; x++, xofs +=4)
+ {
+ memcpy(bits + imgoffset + xofs, src + srcoffset + (int)floor((double)x / m_Zoom) * 4, 4);
+ }
+ }
+ }
+}
+
+
+
+
+
+void BiomeView::resizeEvent(QResizeEvent * a_Event)
+{
+ m_Image = QImage(a_Event->size(), QImage::Format_RGB32);
+ redraw();
+}
+
+
+
+
+
+void BiomeView::paintEvent(QPaintEvent * a_Event)
+{
+ QPainter p(this);
+ if (hasData())
+ {
+ p.drawImage(QPoint(0, 0), m_Image);
+ }
+ else
+ {
+ p.drawText(a_Event->rect(), Qt::AlignCenter, "No chunk source selected");
+ }
+ p.end();
+}
+
+
+
+
+
+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
new file mode 100644
index 000000000..f0521571d
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/BiomeView.h
@@ -0,0 +1,100 @@
+#pragma once
+
+#include <QWidget>
+#include <memory>
+#include "ChunkCache.h"
+#include "ChunkSource.h"
+
+
+
+
+
+class BiomeView :
+ public QWidget
+{
+ typedef QWidget super;
+ Q_OBJECT
+
+public:
+ explicit BiomeView(QWidget * parent = NULL);
+
+ QSize minimumSizeHint() const;
+ QSize sizeHint() const;
+
+ /** Replaces the chunk source used by the biome view to get the chunk biome data.
+ The entire view is then invalidated and regenerated. */
+ void setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource);
+
+signals:
+
+public slots:
+ /** Redraw the entire widget area. */
+ void redraw();
+
+ /** 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;
+ 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];
+
+
+ /** Draws the specified chunk into m_Image */
+ void drawChunk(int a_ChunkX, int a_ChunkZ);
+
+ /** Returns true iff the biome view has been initialized to contain proper biome data. */
+ bool hasData(void) const { return m_Cache.hasData(); }
+
+ /** Called when the widget is resized */
+ virtual void resizeEvent(QResizeEvent *) override;
+
+ /** Paints the entire widget */
+ virtual void paintEvent(QPaintEvent *) override;
+
+ /** 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/Chunk.cpp b/Tools/QtBiomeVisualiser/Chunk.cpp
new file mode 100644
index 000000000..d3419af9c
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/Chunk.cpp
@@ -0,0 +1,36 @@
+#include "Globals.h"
+#include "Globals.h"
+#include "Chunk.h"
+
+
+
+
+
+Chunk::Chunk() :
+ m_IsValid(false)
+{
+}
+
+
+
+
+
+const uchar * Chunk::getImage(void) const
+{
+ ASSERT(m_IsValid);
+ return m_Image;
+}
+
+
+
+
+
+void Chunk::setImage(const Image & a_Image)
+{
+ memcpy(m_Image, a_Image, sizeof(a_Image));
+ m_IsValid = true;
+}
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/Chunk.h b/Tools/QtBiomeVisualiser/Chunk.h
new file mode 100644
index 000000000..03e7bd1b3
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/Chunk.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <qglobal.h>
+
+
+
+
+
+class Chunk
+{
+public:
+ /** The type used for storing image data for a chunk. */
+ typedef uchar Image[16 * 16 * 4];
+
+
+ Chunk(void);
+
+ /** Returns true iff the chunk data is valid - loaded or generated. */
+ bool isValid(void) const { return m_IsValid; }
+
+ /** Returns the image of the chunk's biomes. Assumes that the chunk is valid. */
+ const uchar * getImage(void) const;
+
+ /** Sets the image data for this chunk. */
+ void setImage(const Image & a_Image);
+
+protected:
+ /** Flag that specifies if the chunk data is valid - loaded or generated. */
+ bool m_IsValid;
+
+ /** Cached rendered image of this chunk's biomes. Updated in render(). */
+ Image m_Image;
+};
+
+typedef std::shared_ptr<Chunk> ChunkPtr;
+
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/ChunkCache.cpp b/Tools/QtBiomeVisualiser/ChunkCache.cpp
new file mode 100644
index 000000000..05c267d30
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/ChunkCache.cpp
@@ -0,0 +1,126 @@
+#include "Globals.h"
+#include "ChunkCache.h"
+#include <QMutexLocker>
+#include <QThreadPool>
+#include "ChunkSource.h"
+#include "ChunkLoader.h"
+
+
+
+
+
+ChunkCache::ChunkCache(QObject * parent) :
+ super(parent)
+{
+ m_Cache.setMaxCost(1024 * 1024 * 1024); // 1 GiB of memory for the cache
+}
+
+
+
+
+
+ChunkPtr ChunkCache::fetch(int a_ChunkX, int a_ChunkZ)
+{
+ // Retrieve from the cache:
+ quint32 hash = getChunkHash(a_ChunkX, a_ChunkZ);
+ ChunkPtr * res;
+ {
+ QMutexLocker lock(&m_Mtx);
+ res = m_Cache[hash];
+ // If succesful and chunk loaded, return the retrieved value:
+ if ((res != nullptr) && (*res)->isValid())
+ {
+ return *res;
+ }
+ }
+
+ // If the chunk is in cache but not valid, it means it has been already queued for rendering, do nothing now:
+ if (res != nullptr)
+ {
+ return ChunkPtr(nullptr);
+ }
+
+ // There's no such item in the cache, create it now:
+ res = new ChunkPtr(new Chunk);
+ if (res == nullptr)
+ {
+ return ChunkPtr(nullptr);
+ }
+ {
+ QMutexLocker lock(&m_Mtx);
+ m_Cache.insert(hash, res, sizeof(Chunk));
+ }
+
+ // Queue the chunk for rendering:
+ queueChunkRender(a_ChunkX, a_ChunkZ, *res);
+
+ // Return failure, the chunk is not yet rendered:
+ return ChunkPtr(nullptr);
+}
+
+
+
+
+
+void ChunkCache::setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource)
+{
+ // Replace the chunk source:
+ m_ChunkSource = a_ChunkSource;
+
+ // Clear the cache:
+ QMutexLocker lock(&m_Mtx);
+ m_Cache.clear();
+}
+
+
+
+
+
+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);
+}
+
+
+
+
+
+quint32 ChunkCache::getChunkHash(int a_ChunkX, int a_ChunkZ)
+{
+ // Simply join the two coords into a single int
+ // The coords will never be larger than 16-bits, so we can do this safely
+ return (((static_cast<quint32>(a_ChunkX) & 0xffff) << 16) | (static_cast<quint32>(a_ChunkZ) & 0xffff));
+}
+
+
+
+
+
+void ChunkCache::queueChunkRender(int a_ChunkX, int a_ChunkZ, ChunkPtr & a_Chunk)
+{
+ // Create a new loader task:
+ ChunkLoader * loader = new ChunkLoader(a_ChunkX, a_ChunkZ, a_Chunk, m_ChunkSource);
+ connect(loader, SIGNAL(loaded(int, int)), this, SLOT(gotChunk(int, int)));
+
+ QThreadPool::globalInstance()->start(loader);
+}
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/ChunkCache.h b/Tools/QtBiomeVisualiser/ChunkCache.h
new file mode 100644
index 000000000..8d198f02f
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/ChunkCache.h
@@ -0,0 +1,72 @@
+#pragma once
+
+#include <QObject>
+#include <QCache>
+#include <QMutex>
+#include <memory>
+
+
+
+
+
+class Chunk;
+typedef std::shared_ptr<Chunk> ChunkPtr;
+
+class ChunkSource;
+
+
+
+
+
+/** Caches chunk data for reuse */
+class ChunkCache :
+ public QObject
+{
+ typedef QObject super;
+ Q_OBJECT
+
+public:
+ explicit ChunkCache(QObject * parent = NULL);
+
+ /** Retrieves the specified chunk from the cache.
+ Only returns valid chunks; if the chunk is invalid, queues it for rendering and returns an empty ptr. */
+ ChunkPtr fetch(int a_ChunkX, int a_ChunkZ);
+
+ /** Replaces the chunk source used by the biome view to get the chunk biome data.
+ The cache is then invalidated. */
+ void setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource);
+
+ /** Returns true iff the chunk source has been initialized. */
+ bool hasData() const { return (m_ChunkSource.get() != nullptr); }
+
+ /** Reloads the current chunk source. */
+ void reload();
+
+signals:
+ void chunkAvailable(int a_ChunkX, int a_ChunkZ);
+
+protected slots:
+ void gotChunk(int a_ChunkX, int a_ChunkZ);
+
+protected:
+ /** The cache of the chunks */
+ QCache<quint32, ChunkPtr> m_Cache;
+
+ /** Locks te cache against multithreaded access */
+ QMutex m_Mtx;
+
+ /** The source used to get the biome data. */
+ std::shared_ptr<ChunkSource> m_ChunkSource;
+
+
+ /** Returns the hash used by the chunk in the cache */
+ quint32 getChunkHash(int a_ChunkX, int a_ChunkZ);
+
+ /** Queues the specified chunk for rendering by m_ChunkSource. */
+ void queueChunkRender(int a_ChunkX, int a_ChunkZ, ChunkPtr & a_Chunk);
+};
+
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/ChunkLoader.cpp b/Tools/QtBiomeVisualiser/ChunkLoader.cpp
new file mode 100644
index 000000000..3d0123b23
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/ChunkLoader.cpp
@@ -0,0 +1,29 @@
+#include "Globals.h"
+#include "ChunkLoader.h"
+#include "ChunkSource.h"
+
+
+
+
+
+ChunkLoader::ChunkLoader(int a_ChunkX, int a_ChunkZ, ChunkPtr a_Chunk, ChunkSourcePtr a_ChunkSource) :
+ m_ChunkX(a_ChunkX),
+ m_ChunkZ(a_ChunkZ),
+ m_Chunk(a_Chunk),
+ m_ChunkSource(a_ChunkSource)
+{
+}
+
+
+
+
+
+void ChunkLoader::run()
+{
+ m_ChunkSource->getChunkBiomes(m_ChunkX, m_ChunkZ, m_Chunk);
+ emit loaded(m_ChunkX, m_ChunkZ);
+}
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/ChunkLoader.h b/Tools/QtBiomeVisualiser/ChunkLoader.h
new file mode 100644
index 000000000..4d026a45e
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/ChunkLoader.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <QObject>
+#include <QRunnable>
+#include <memory>
+
+
+
+
+// fwd:
+class Chunk;
+typedef std::shared_ptr<Chunk> ChunkPtr;
+
+class ChunkSource;
+typedef std::shared_ptr<ChunkSource> ChunkSourcePtr;
+
+
+
+
+
+class ChunkLoader :
+ public QObject,
+ public QRunnable
+{
+ Q_OBJECT
+
+public:
+ ChunkLoader(int a_ChunkX, int a_ChunkZ, ChunkPtr a_Chunk, ChunkSourcePtr a_ChunkSource);
+ virtual ~ChunkLoader() {}
+
+signals:
+ void loaded(int a_ChunkX, int a_ChunkZ);
+
+protected:
+ virtual void run() override;
+
+private:
+ int m_ChunkX, m_ChunkZ;
+ ChunkPtr m_Chunk;
+ ChunkSourcePtr m_ChunkSource;
+};
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp
new file mode 100644
index 000000000..28d184615
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp
@@ -0,0 +1,421 @@
+#include "Globals.h"
+#include "ChunkSource.h"
+#include <QThread>
+#include "src/Generating/BioGen.h"
+#include "inifile/iniFile.h"
+#include "src/StringCompression.h"
+#include "src/WorldStorage/FastNBT.h"
+
+
+
+
+
+/** Map for converting biome values to colors. Initialized from biomeColors[]. */
+static uchar biomeToColor[256 * 4];
+
+/** Map for converting biome values to colors. Used to initialize biomeToColor[].*/
+static struct
+{
+ EMCSBiome m_Biome;
+ uchar m_Color[3];
+} biomeColors[] =
+{
+ { biOcean, { 0x00, 0x00, 0x70 }, },
+ { biPlains, { 0x8d, 0xb3, 0x60 }, },
+ { biDesert, { 0xfa, 0x94, 0x18 }, },
+ { biExtremeHills, { 0x60, 0x60, 0x60 }, },
+ { biForest, { 0x05, 0x66, 0x21 }, },
+ { biTaiga, { 0x0b, 0x66, 0x59 }, },
+ { biSwampland, { 0x2f, 0xff, 0xda }, },
+ { biRiver, { 0x30, 0x30, 0xaf }, },
+ { biHell, { 0x7f, 0x00, 0x00 }, },
+ { biSky, { 0x00, 0x7f, 0xff }, },
+ { biFrozenOcean, { 0xa0, 0xa0, 0xdf }, },
+ { biFrozenRiver, { 0xa0, 0xa0, 0xff }, },
+ { biIcePlains, { 0xff, 0xff, 0xff }, },
+ { biIceMountains, { 0xa0, 0xa0, 0xa0 }, },
+ { biMushroomIsland, { 0xff, 0x00, 0xff }, },
+ { biMushroomShore, { 0xa0, 0x00, 0xff }, },
+ { biBeach, { 0xfa, 0xde, 0x55 }, },
+ { biDesertHills, { 0xd2, 0x5f, 0x12 }, },
+ { biForestHills, { 0x22, 0x55, 0x1c }, },
+ { biTaigaHills, { 0x16, 0x39, 0x33 }, },
+ { biExtremeHillsEdge, { 0x7f, 0x8f, 0x7f }, },
+ { biJungle, { 0x53, 0x7b, 0x09 }, },
+ { biJungleHills, { 0x2c, 0x42, 0x05 }, },
+
+ { biJungleEdge, { 0x62, 0x8b, 0x17 }, },
+ { biDeepOcean, { 0x00, 0x00, 0x30 }, },
+ { biStoneBeach, { 0xa2, 0xa2, 0x84 }, },
+ { biColdBeach, { 0xfa, 0xf0, 0xc0 }, },
+ { biBirchForest, { 0x30, 0x74, 0x44 }, },
+ { biBirchForestHills, { 0x1f, 0x5f, 0x32 }, },
+ { biRoofedForest, { 0x40, 0x51, 0x1a }, },
+ { biColdTaiga, { 0x31, 0x55, 0x4a }, },
+ { biColdTaigaHills, { 0x59, 0x7d, 0x72 }, },
+ { biMegaTaiga, { 0x59, 0x66, 0x51 }, },
+ { biMegaTaigaHills, { 0x59, 0x66, 0x59 }, },
+ { biExtremeHillsPlus, { 0x50, 0x70, 0x50 }, },
+ { biSavanna, { 0xbd, 0xb2, 0x5f }, },
+ { biSavannaPlateau, { 0xa7, 0x9d, 0x64 }, },
+ { biMesa, { 0xd9, 0x45, 0x15 }, },
+ { biMesaPlateauF, { 0xb0, 0x97, 0x65 }, },
+ { biMesaPlateau, { 0xca, 0x8c, 0x65 }, },
+
+ // M variants:
+ { biSunflowerPlains, { 0xb5, 0xdb, 0x88 }, },
+ { biDesertM, { 0xff, 0xbc, 0x40 }, },
+ { biExtremeHillsM, { 0x88, 0x88, 0x88 }, },
+ { biFlowerForest, { 0x2d, 0x8e, 0x49 }, },
+ { biTaigaM, { 0x33, 0x8e, 0x81 }, },
+ { biSwamplandM, { 0x07, 0xf9, 0xb2 }, },
+ { biIcePlainsSpikes, { 0xb4, 0xdc, 0xdc }, },
+ { biJungleM, { 0x7b, 0xa3, 0x31 }, },
+ { biJungleEdgeM, { 0x62, 0x8b, 0x17 }, },
+ { biBirchForestM, { 0x58, 0x9c, 0x6c }, },
+ { biBirchForestHillsM, { 0x47, 0x87, 0x5a }, },
+ { biRoofedForestM, { 0x68, 0x79, 0x42 }, },
+ { biColdTaigaM, { 0x24, 0x3f, 0x36 }, },
+ { biMegaSpruceTaiga, { 0x45, 0x4f, 0x3e }, },
+ { biMegaSpruceTaigaHills, { 0x45, 0x4f, 0x4e }, },
+ { biExtremeHillsPlusM, { 0x78, 0x98, 0x78 }, },
+ { biSavannaM, { 0xe5, 0xda, 0x87 }, },
+ { biSavannaPlateauM, { 0xa7, 0x9d, 0x74 }, },
+ { biMesaBryce, { 0xff, 0x6d, 0x3d }, },
+ { biMesaPlateauFM, { 0xd8, 0xbf, 0x8d }, },
+ { biMesaPlateauM, { 0xf2, 0xb4, 0x8d }, },
+} ;
+
+
+
+
+
+static class BiomeColorsInitializer
+{
+public:
+ BiomeColorsInitializer(void)
+ {
+ // Reset all colors to gray:
+ for (size_t i = 0; i < ARRAYCOUNT(biomeToColor); i++)
+ {
+ biomeToColor[i] = 0x7f;
+ }
+
+ // Set known biomes to their colors:
+ for (size_t i = 0; i < ARRAYCOUNT(biomeColors); i++)
+ {
+ uchar * color = &biomeToColor[4 * biomeColors[i].m_Biome];
+ color[0] = biomeColors[i].m_Color[2];
+ color[1] = biomeColors[i].m_Color[1];
+ color[2] = biomeColors[i].m_Color[0];
+ color[3] = 0xff;
+ }
+ }
+} biomeColorInitializer;
+
+
+
+
+
+/** Converts biomes in an array into the chunk image data. */
+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] = {};
+
+ // Convert the biomes into color:
+ for (size_t i = 0; i < ARRAYCOUNT(a_Biomes); i++)
+ {
+ a_Image[4 * i + 0] = biomeToColor[4 * a_Biomes[i] + 0];
+ a_Image[4 * i + 1] = biomeToColor[4 * a_Biomes[i] + 1];
+ a_Image[4 * i + 2] = biomeToColor[4 * a_Biomes[i] + 2];
+ a_Image[4 * i + 3] = biomeToColor[4 * a_Biomes[i] + 3];
+ }
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// BioGenSource:
+
+BioGenSource::BioGenSource(cIniFilePtr a_IniFile) :
+ m_IniFile(a_IniFile),
+ m_Mtx(QMutex::Recursive)
+{
+ reload();
+}
+
+
+
+
+
+void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk)
+{
+ cChunkDef::BiomeMap biomes;
+ {
+ QMutexLocker lock(&m_Mtx);
+ m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, biomes);
+ }
+ Chunk::Image img;
+ biomesToImage(biomes, img);
+ a_DestChunk->setImage(img);
+}
+
+
+
+
+
+void BioGenSource::reload()
+{
+ int seed = m_IniFile->GetValueSetI("Generator", "Seed", 0);
+ bool unused = false;
+ QMutexLocker lock(&m_Mtx);
+ m_BiomeGen.reset(cBiomeGen::CreateBiomeGen(*m_IniFile, seed, unused));
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// AnvilSource::AnvilFile
+
+class AnvilSource::AnvilFile
+{
+public:
+ /** Coordinates of the region file. */
+ int m_RegionX, m_RegionZ;
+
+ /** True iff the file contains proper data. */
+ bool m_IsValid;
+
+
+
+ /** Creates a new instance with the specified region coords. Reads the file header. */
+ AnvilFile(int a_RegionX, int a_RegionZ, const AString & a_WorldPath) :
+ m_RegionX(a_RegionX),
+ m_RegionZ(a_RegionZ),
+ m_IsValid(false)
+ {
+ readFile(Printf("%s/r.%d.%d.mca", a_WorldPath.c_str(), a_RegionX, a_RegionZ));
+ }
+
+
+
+ /** Returns the compressed data of the specified chunk.
+ Returns an empty string when chunk not present. */
+ AString getChunkData(int a_ChunkX, int a_ChunkZ)
+ {
+ if (!m_IsValid)
+ {
+ return "";
+ }
+
+ // Translate to local coords:
+ int RelChunkX = a_ChunkX - m_RegionX * 32;
+ int RelChunkZ = a_ChunkZ - m_RegionZ * 32;
+ ASSERT((RelChunkX >= 0) && (RelChunkX < 32));
+ ASSERT((RelChunkZ >= 0) && (RelChunkZ < 32));
+
+ // Get the chunk data location:
+ UInt32 chunkOffset = m_Header[RelChunkX + 32 * RelChunkZ] >> 8;
+ UInt32 numChunkSectors = m_Header[RelChunkX + 32 * RelChunkZ] & 0xff;
+ if ((chunkOffset < 2) || (numChunkSectors == 0))
+ {
+ return "";
+ }
+
+ // Get the real data size:
+ const char * chunkData = m_FileData.data() + chunkOffset * 4096;
+ UInt32 chunkSize = GetBEInt(chunkData);
+ if ((chunkSize < 2) || (chunkSize / 4096 > numChunkSectors))
+ {
+ // Bad data, bail out
+ return "";
+ }
+
+ // Check the compression method:
+ if (chunkData[4] != 2)
+ {
+ // Chunk is in an unknown compression
+ return "";
+ }
+ chunkSize--;
+
+ // Read the chunk data:
+ return m_FileData.substr(chunkOffset * 4096 + 5, chunkSize);
+ }
+
+protected:
+ AString m_FileData;
+ UInt32 m_Header[2048];
+
+
+ /** Reads the whole specified file contents and parses the header. */
+ void readFile(const AString & a_FileName)
+ {
+ // Read the entire file:
+ m_FileData = cFile::ReadWholeFile(a_FileName);
+ if (m_FileData.size() < sizeof(m_Header))
+ {
+ return;
+ }
+
+ // Parse the header - change endianness:
+ const char * hdr = m_FileData.data();
+ for (size_t i = 0; i < ARRAYCOUNT(m_Header); i++)
+ {
+ m_Header[i] = GetBEInt(hdr + 4 * i);
+ }
+ m_IsValid = true;
+ }
+};
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// AnvilSource:
+
+AnvilSource::AnvilSource(QString a_WorldRegionFolder) :
+ m_WorldRegionFolder(a_WorldRegionFolder)
+{
+}
+
+
+
+
+
+void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk)
+{
+ // Load the compressed data:
+ AString compressedChunkData = getCompressedChunkData(a_ChunkX, a_ChunkZ);
+ if (compressedChunkData.empty())
+ {
+ return;
+ }
+
+ // Uncompress the chunk data:
+ AString uncompressed;
+ int res = InflateString(compressedChunkData.data(), compressedChunkData.size(), uncompressed);
+ if (res != Z_OK)
+ {
+ return;
+ }
+
+ // Parse the NBT data:
+ cParsedNBT nbt(uncompressed.data(), uncompressed.size());
+ if (!nbt.IsValid())
+ {
+ return;
+ }
+
+ // Get the biomes out of the NBT:
+ int Level = nbt.FindChildByName(0, "Level");
+ if (Level < 0)
+ {
+ return;
+ }
+ cChunkDef::BiomeMap biomeMap;
+ int mcsBiomes = nbt.FindChildByName(Level, "MCSBiomes");
+ if ((mcsBiomes >= 0) && (nbt.GetDataLength(mcsBiomes) == sizeof(biomeMap)))
+ {
+ // Convert the biomes from BigEndian to platform native numbers:
+ const char * beBiomes = nbt.GetData(mcsBiomes);
+ for (size_t i = 0; i < ARRAYCOUNT(biomeMap); i++)
+ {
+ biomeMap[i] = (EMCSBiome)GetBEInt(beBiomes + 4 * i);
+ }
+ // Render the biomes:
+ Chunk::Image img;
+ biomesToImage(biomeMap, img);
+ a_DestChunk->setImage(img);
+ return;
+ }
+
+ // MCS biomes not found, load Vanilla biomes instead:
+ int biomes = nbt.FindChildByName(Level, "Biomes");
+ if ((biomes < 0) || (nbt.GetDataLength(biomes) != ARRAYCOUNT(biomeMap)))
+ {
+ return;
+ }
+ // Convert the biomes from Vanilla to EMCSBiome:
+ const char * vanillaBiomes = nbt.GetData(biomes);
+ for (size_t i = 0; i < ARRAYCOUNT(biomeMap); i++)
+ {
+ biomeMap[i] = EMCSBiome(vanillaBiomes[i]);
+ }
+ // Render the biomes:
+ Chunk::Image img;
+ biomesToImage(biomeMap, img);
+ a_DestChunk->setImage(img);
+}
+
+
+
+
+
+void AnvilSource::reload()
+{
+ // Remove all files from the cache:
+ QMutexLocker lock(&m_Mtx);
+ m_Files.clear();
+}
+
+
+
+
+
+void AnvilSource::chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ)
+{
+ a_RegionX = a_ChunkX >> 5;
+ a_RegionZ = a_ChunkZ >> 5;
+}
+
+
+
+
+
+AString AnvilSource::getCompressedChunkData(int a_ChunkX, int a_ChunkZ)
+{
+ return getAnvilFile(a_ChunkX, a_ChunkZ)->getChunkData(a_ChunkX, a_ChunkZ);
+}
+
+
+
+
+
+AnvilSource::AnvilFilePtr AnvilSource::getAnvilFile(int a_ChunkX, int a_ChunkZ)
+{
+ int RegionX, RegionZ;
+ chunkToRegion(a_ChunkX, a_ChunkZ, RegionX, RegionZ);
+
+ // Search the cache for the file:
+ QMutexLocker lock(&m_Mtx);
+ for (auto itr = m_Files.cbegin(), end = m_Files.cend(); itr != end; ++itr)
+ {
+ if (((*itr)->m_RegionX == RegionX) && ((*itr)->m_RegionZ == RegionZ))
+ {
+ // Found the file in the cache, move it to front and return it:
+ AnvilFilePtr file(*itr);
+ m_Files.erase(itr);
+ m_Files.push_front(file);
+ return file;
+ }
+ }
+
+ // File not in cache, create it:
+ AnvilFilePtr file(new AnvilFile(RegionX, RegionZ, m_WorldRegionFolder.toStdString()));
+ m_Files.push_front(file);
+ return file;
+}
+
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/ChunkSource.h b/Tools/QtBiomeVisualiser/ChunkSource.h
new file mode 100644
index 000000000..05e8ac5de
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/ChunkSource.h
@@ -0,0 +1,107 @@
+#pragma once
+#include "Globals.h"
+#include <QString>
+#include <QMutex>
+#include "Chunk.h"
+
+
+
+
+
+// fwd:
+class cBiomeGen;
+typedef std::shared_ptr<cBiomeGen> cBiomeGenPtr;
+class cIniFile;
+typedef std::shared_ptr<cIniFile> cIniFilePtr;
+
+
+
+
+
+/** Abstract interface for getting biome data for chunks. */
+class ChunkSource
+{
+public:
+ virtual ~ChunkSource() {}
+
+ /** 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;
+};
+
+
+
+
+
+
+class BioGenSource :
+ public ChunkSource
+{
+public:
+ /** Constructs a new BioGenSource based on the biome generator that is defined in the specified world.ini file. */
+ BioGenSource(cIniFilePtr a_IniFile);
+
+ // ChunkSource overrides:
+ virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override;
+ virtual void reload(void) override;
+
+protected:
+ /** The world.ini contents from which the generator is created and re-created on reload(). */
+ cIniFilePtr m_IniFile;
+
+ /** The generator used for generating biomes. */
+ std::unique_ptr<cBiomeGen> m_BiomeGen;
+
+ /** Guards m_BiomeGen against multithreaded access. */
+ QMutex m_Mtx;
+};
+
+
+
+
+class AnvilSource :
+ public ChunkSource
+{
+public:
+ /** Constructs a new AnvilSource based on the world path. */
+ AnvilSource(QString a_WorldRegionFolder);
+
+ // ChunkSource overrides:
+ virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override;
+ virtual void reload() override;
+
+protected:
+ class AnvilFile;
+ typedef std::shared_ptr<AnvilFile> AnvilFilePtr;
+
+
+ /** Folder where the individual Anvil Region files are located. */
+ QString m_WorldRegionFolder;
+
+ /** List of currently loaded files. Acts as a cache so that a file is not opened and closed over and over again.
+ Protected against multithreaded access by m_Mtx. */
+ std::list<AnvilFilePtr> m_Files;
+
+ /** Guards m_Files agains multithreaded access. */
+ QMutex m_Mtx;
+
+
+ /** Converts chunk coords to region coords. */
+ void chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ);
+
+ /** Returns the compressed data of the specified chunk.
+ Returns an empty string if the chunk is not available. */
+ AString getCompressedChunkData(int a_ChunkX, int a_ChunkZ);
+
+ /** Returns the file object that contains the specified chunk.
+ The file is taken from the cache if available there, otherwise it is created anew. */
+ AnvilFilePtr getAnvilFile(int a_ChunkX, int a_ChunkZ);
+
+};
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/GeneratorSetup.cpp b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp
new file mode 100644
index 000000000..f5412404c
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp
@@ -0,0 +1,159 @@
+#include "Globals.h"
+#include "GeneratorSetup.h"
+#include <QLabel>
+#include <QLineEdit>
+#include "src/Generating/BioGen.h"
+#include "inifile/iniFile.h"
+
+
+
+
+
+static const QString s_GeneratorNames[] =
+{
+ QString("Checkerboard"),
+ QString("Constant"),
+ QString("DistortedVoronoi"),
+ QString("MultiStepMap"),
+ QString("TwoLevel"),
+ QString("Voronoi"),
+};
+
+
+
+
+
+GeneratorSetup::GeneratorSetup(const AString & a_IniFileName, QWidget * a_Parent) :
+ super(a_Parent),
+ m_IniFile(new cIniFile())
+{
+ // The seed and generator name is in a separate form layout at the top, always present:
+ m_eSeed = new QLineEdit();
+ m_eSeed->setValidator(new QIntValidator());
+ m_eSeed->setText("0");
+ m_eSeed->setProperty("INI.ItemName", QVariant("Seed"));
+ m_cbGenerator = new QComboBox();
+ m_cbGenerator->setMinimumWidth(120);
+ for (size_t i = 0; i < ARRAYCOUNT(s_GeneratorNames); i++)
+ {
+ m_cbGenerator->addItem(s_GeneratorNames[i]);
+ }
+ QFormLayout * baseLayout = new QFormLayout();
+ baseLayout->addRow(new QLabel(tr("Seed")), m_eSeed);
+ baseLayout->addRow(new QLabel(tr("Generator")), m_cbGenerator);
+
+ // The rest of the controls are in a dynamically created form layout:
+ m_FormLayout = new QFormLayout();
+
+ // The main layout joins these two vertically:
+ m_MainLayout = new QVBoxLayout();
+ m_MainLayout->addLayout(baseLayout);
+ m_MainLayout->addLayout(m_FormLayout);
+ m_MainLayout->addStretch();
+ setLayout(m_MainLayout);
+
+ // Load the INI file, if specified, otherwise set defaults:
+ if (!a_IniFileName.empty() && m_IniFile->ReadFile(a_IniFileName))
+ {
+ m_cbGenerator->setCurrentText(QString::fromStdString(m_IniFile->GetValue("Generator", "BiomeGen")));
+ m_eSeed->setText(QString::number(m_IniFile->GetValueI("Generator", "Seed")));
+ }
+ else
+ {
+ m_IniFile->SetValue("Generator", "Generator", "Composable");
+ m_IniFile->SetValue("Generator", "BiomeGen", m_cbGenerator->currentText().toStdString());
+ bool dummy;
+ delete cBiomeGen::CreateBiomeGen(*m_IniFile, 0, dummy);
+ }
+ updateFromIni();
+
+ // Connect the change events only after the data has been loaded:
+ connect(m_cbGenerator, SIGNAL(currentIndexChanged(QString)), this, SLOT(generatorChanged(QString)));
+ connect(m_eSeed, SIGNAL(textChanged(QString)), this, SLOT(editChanged(QString)));
+}
+
+
+
+
+
+void GeneratorSetup::generatorChanged(const QString & a_NewName)
+{
+ // Clear the current contents of the form layout by assigning it to a stack temporary:
+ {
+ m_MainLayout->takeAt(1);
+ QWidget().setLayout(m_FormLayout);
+ }
+
+ // Re-create the layout:
+ m_FormLayout = new QFormLayout();
+ m_MainLayout->insertLayout(1, m_FormLayout);
+
+ // Recreate the INI file:
+ m_IniFile->Clear();
+ m_IniFile->SetValue("Generator", "Generator", "Composable");
+ m_IniFile->SetValue("Generator", "BiomeGen", a_NewName.toStdString());
+
+ // Create a dummy biome gen from the INI file, this will create the defaults in the INI file:
+ bool dummy;
+ delete cBiomeGen::CreateBiomeGen(*m_IniFile, m_Seed, dummy);
+
+ // Read all values from the INI file and put them into the form layout:
+ updateFromIni();
+
+ // Notify of the changes:
+ emit generatorUpdated();
+}
+
+
+
+
+
+void GeneratorSetup::editChanged(const QString & a_NewValue)
+{
+ QString itemName = sender()->property("INI.ItemName").toString();
+ m_IniFile->SetValue("Generator", itemName.toStdString(), a_NewValue.toStdString());
+ emit generatorUpdated();
+}
+
+
+
+
+
+void GeneratorSetup::updateFromIni()
+{
+ int keyID = m_IniFile->FindKey("Generator");
+ if (keyID <= -1)
+ {
+ return;
+ }
+ int numItems = m_IniFile->GetNumValues(keyID);
+ AString generatorName = m_IniFile->GetValue("Generator", "BiomeGen");
+ size_t generatorNameLen = generatorName.length();
+ for (int i = 0; i < numItems; i++)
+ {
+ AString itemName = m_IniFile->GetValueName(keyID, i);
+ if ((itemName == "Generator") || (itemName == "BiomeGen"))
+ {
+ // These special cases are not to be added
+ continue;
+ }
+ AString itemValue = m_IniFile->GetValue(keyID, i);
+
+ QLineEdit * edit = new QLineEdit();
+ edit->setText(QString::fromStdString(itemValue));
+ edit->setProperty("INI.ItemName", QVariant(QString::fromStdString(itemName)));
+
+ // Remove the generator name prefix from the item name, for clarity purposes:
+ if (NoCaseCompare(itemName.substr(0, generatorNameLen), generatorName) == 0)
+ {
+ itemName.erase(0, generatorNameLen);
+ }
+
+ connect(edit, SIGNAL(textChanged(QString)), this, SLOT(editChanged(QString)));
+ m_FormLayout->addRow(new QLabel(QString::fromStdString(itemName)), edit);
+ } // for i - INI values[]
+}
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/GeneratorSetup.h b/Tools/QtBiomeVisualiser/GeneratorSetup.h
new file mode 100644
index 000000000..e72d3abbc
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/GeneratorSetup.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include <memory>
+#include <QDialog>
+#include <QComboBox>
+#include <QVBoxLayout>
+#include <QFormLayout>
+
+
+
+
+
+class cIniFile;
+typedef std::shared_ptr<cIniFile> cIniFilePtr;
+
+
+
+
+
+class GeneratorSetup :
+ public QWidget
+{
+ typedef QWidget super;
+
+ Q_OBJECT
+
+public:
+ /** Creates the widget and loads the contents of the INI file, if not empty. */
+ explicit GeneratorSetup(const std::string & a_IniFileName, QWidget * parent = nullptr);
+
+ /** Returns the cIniFile instance that is being edited by this widget. */
+ cIniFilePtr getIniFile() { return m_IniFile; }
+
+signals:
+ /** Emitted when the generator parameters have changed. */
+ void generatorUpdated();
+
+public slots:
+ /** Called when the user selects a different generator from the top combobox.
+ Re-creates m_IniFile and updates the form layout. */
+ void generatorChanged(const QString & a_NewName);
+
+protected slots:
+ /** Called when any of the edit widgets are changed. */
+ void editChanged(const QString & a_NewValue);
+
+protected:
+ QComboBox * m_cbGenerator;
+ QLineEdit * m_eSeed;
+ QVBoxLayout * m_MainLayout;
+ QFormLayout * m_FormLayout;
+
+ cIniFilePtr m_IniFile;
+
+ int m_Seed;
+
+
+ /** Updates the form layout with the values from m_IniFile. */
+ void updateFromIni();
+};
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/Globals.h b/Tools/QtBiomeVisualiser/Globals.h
new file mode 100644
index 000000000..8d2e913b7
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/Globals.h
@@ -0,0 +1,386 @@
+#pragma once
+
+
+
+
+
+// Compiler-dependent stuff:
+#if defined(_MSC_VER)
+ // MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether
+ #pragma warning(disable:4481)
+
+ // Disable some warnings that we don't care about:
+ #pragma warning(disable:4100) // Unreferenced formal parameter
+
+ // Useful warnings from warning level 4:
+ #pragma warning(3 : 4127) // Conditional expression is constant
+ #pragma warning(3 : 4189) // Local variable is initialized but not referenced
+ #pragma warning(3 : 4245) // Conversion from 'type1' to 'type2', signed/unsigned mismatch
+ #pragma warning(3 : 4310) // Cast truncates constant value
+ #pragma warning(3 : 4389) // Signed/unsigned mismatch
+ #pragma warning(3 : 4505) // Unreferenced local function has been removed
+ #pragma warning(3 : 4701) // Potentially unitialized local variable used
+ #pragma warning(3 : 4702) // Unreachable code
+ #pragma warning(3 : 4706) // Assignment within conditional expression
+
+ // Disabling this warning, because we know what we're doing when we're doing this:
+ #pragma warning(disable: 4355) // 'this' used in initializer list
+
+ // Disabled because it's useless:
+ #pragma warning(disable: 4512) // 'class': assignment operator could not be generated - reported for each class that has a reference-type member
+
+ // 2014_01_06 xoft: Disabled this warning because MSVC is stupid and reports it in obviously wrong places
+ // #pragma warning(3 : 4244) // Conversion from 'type1' to 'type2', possible loss of data
+
+ #define OBSOLETE __declspec(deprecated)
+
+ // No alignment needed in MSVC
+ #define ALIGN_8
+ #define ALIGN_16
+
+ #define FORMATSTRING(formatIndex, va_argsIndex)
+
+ // MSVC has its own custom version of zu format
+ #define SIZE_T_FMT "%Iu"
+ #define SIZE_T_FMT_PRECISION(x) "%" #x "Iu"
+ #define SIZE_T_FMT_HEX "%Ix"
+
+ #define NORETURN __declspec(noreturn)
+
+#elif defined(__GNUC__)
+
+ // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
+ #define abstract
+
+ // override is part of c++11
+ #if __cplusplus < 201103L
+ #define override
+ #endif
+
+ #define OBSOLETE __attribute__((deprecated))
+
+ #define ALIGN_8 __attribute__((aligned(8)))
+ #define ALIGN_16 __attribute__((aligned(16)))
+
+ // Some portability macros :)
+ #define stricmp strcasecmp
+
+ #define FORMATSTRING(formatIndex, va_argsIndex) __attribute__((format (printf, formatIndex, va_argsIndex)))
+
+ #if defined(_WIN32)
+ // We're compiling on MinGW, which uses an old MSVCRT library that has no support for size_t printfing.
+ // We need direct size formats:
+ #if defined(_WIN64)
+ #define SIZE_T_FMT "%I64u"
+ #define SIZE_T_FMT_PRECISION(x) "%" #x "I64u"
+ #define SIZE_T_FMT_HEX "%I64x"
+ #else
+ #define SIZE_T_FMT "%u"
+ #define SIZE_T_FMT_PRECISION(x) "%" #x "u"
+ #define SIZE_T_FMT_HEX "%x"
+ #endif
+ #else
+ // We're compiling on Linux, so we can use libc's size_t printf format:
+ #define SIZE_T_FMT "%zu"
+ #define SIZE_T_FMT_PRECISION(x) "%" #x "zu"
+ #define SIZE_T_FMT_HEX "%zx"
+ #endif
+
+ #define NORETURN __attribute((__noreturn__))
+
+#else
+
+ #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
+
+ /*
+ // Copy and uncomment this into another #elif section based on your compiler identification
+
+ // Explicitly mark classes as abstract (no instances can be created)
+ #define abstract
+
+ // Mark virtual methods as overriding (forcing them to have a virtual function of the same signature in the base class)
+ #define override
+
+ // Mark functions as obsolete, so that their usage results in a compile-time warning
+ #define OBSOLETE
+
+ // Mark types / variables for alignment. Do the platforms need it?
+ #define ALIGN_8
+ #define ALIGN_16
+ */
+
+#endif
+
+
+#ifdef _DEBUG
+ #define NORETURNDEBUG NORETURN
+#else
+ #define NORETURNDEBUG
+#endif
+
+
+#include <stddef.h>
+
+
+// Integral types with predefined sizes:
+typedef long long Int64;
+typedef int Int32;
+typedef short Int16;
+
+typedef unsigned long long UInt64;
+typedef unsigned int UInt32;
+typedef unsigned short UInt16;
+
+typedef unsigned char Byte;
+
+
+// If you get an error about specialization check the size of integral types
+template <typename T, size_t Size, bool x = sizeof(T) == Size>
+class SizeChecker;
+
+template <typename T, size_t Size>
+class SizeChecker<T, Size, true>
+{
+ T v;
+};
+
+template class SizeChecker<Int64, 8>;
+template class SizeChecker<Int32, 4>;
+template class SizeChecker<Int16, 2>;
+
+template class SizeChecker<UInt64, 8>;
+template class SizeChecker<UInt32, 4>;
+template class SizeChecker<UInt16, 2>;
+
+// A macro to disallow the copy constructor and operator = functions
+// This should be used in the private: declarations for any class that shouldn't allow copying itself
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName &); \
+ void operator =(const TypeName &)
+
+// A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc
+#define UNUSED(X) (void)(X)
+
+
+
+
+// OS-dependent stuff:
+#ifdef _WIN32
+ #define WIN32_LEAN_AND_MEAN
+
+ #define _WIN32_WINNT 0x501 // We want to target WinXP and higher
+
+ #include <Windows.h>
+ #include <winsock2.h>
+ #include <Ws2tcpip.h> // IPv6 stuff
+
+ // Windows SDK defines min and max macros, messing up with our std::min and std::max usage
+ #undef min
+ #undef max
+
+ // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant
+ #ifdef GetFreeSpace
+ #undef GetFreeSpace
+ #endif // GetFreeSpace
+#else
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <time.h>
+ #include <dirent.h>
+ #include <errno.h>
+ #include <iostream>
+ #include <cstdio>
+ #include <cstring>
+ #include <pthread.h>
+ #include <semaphore.h>
+ #include <errno.h>
+ #include <fcntl.h>
+#endif
+
+#if defined(ANDROID_NDK)
+ #define FILE_IO_PREFIX "/sdcard/mcserver/"
+#else
+ #define FILE_IO_PREFIX ""
+#endif
+
+
+
+
+
+// CRT stuff:
+#include <sys/stat.h>
+#include <assert.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdarg.h>
+
+
+
+
+
+// STL stuff:
+#include <vector>
+#include <list>
+#include <deque>
+#include <string>
+#include <map>
+#include <algorithm>
+#include <memory>
+#include <set>
+#include <queue>
+#include <limits>
+
+
+
+#ifndef TEST_GLOBALS
+ // Common headers (part 1, without macros):
+ #include "src/StringUtils.h"
+ #include "src/OSSupport/Sleep.h"
+ #include "src/OSSupport/CriticalSection.h"
+ #include "src/OSSupport/Semaphore.h"
+ #include "src/OSSupport/Event.h"
+ #include "src/OSSupport/Thread.h"
+ #include "src/OSSupport/File.h"
+ #include "src/Logger.h"
+#else
+ // Logging functions
+void inline LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2);
+
+void inline LOGERROR(const char* a_Format, ...)
+{
+ va_list argList;
+ va_start(argList, a_Format);
+ vprintf(a_Format, argList);
+ va_end(argList);
+}
+#endif
+
+
+
+
+
+// Common definitions:
+
+/// Evaluates to the number of elements in an array (compile-time!)
+#define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X)))
+
+/// Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)")
+#define KiB * 1024
+#define MiB * 1024 * 1024
+
+/// Faster than (int)floorf((float)x / (float)div)
+#define FAST_FLOOR_DIV( x, div) (((x) - (((x) < 0) ? ((div) - 1) : 0)) / (div))
+
+// Own version of assert() that writes failed assertions to the log for review
+#ifdef TEST_GLOBALS
+
+ class cAssertFailure
+ {
+ };
+
+ #ifdef _WIN32
+ #if (defined(_MSC_VER) && defined(_DEBUG))
+ #define DBG_BREAK _CrtDbgBreak()
+ #else
+ #define DBG_BREAK
+ #endif
+ #define REPORT_ERROR(FMT, ...) \
+ { \
+ AString msg = Printf(FMT, __VA_ARGS__); \
+ puts(msg.c_str()); \
+ fflush(stdout); \
+ OutputDebugStringA(msg.c_str()); \
+ DBG_BREAK; \
+ }
+ #else
+ #define REPORT_ERROR(FMT, ...) \
+ { \
+ AString msg = Printf(FMT, __VA_ARGS__); \
+ puts(msg.c_str()); \
+ fflush(stdout); \
+ }
+ #endif
+ #define ASSERT(x) do { if (!(x)) { throw cAssertFailure();} } while (0)
+ #define testassert(x) do { if (!(x)) { REPORT_ERROR("Test failure: %s, file %s, line %d\n", #x, __FILE__, __LINE__); exit(1); } } while (0)
+ #define CheckAsserts(x) do { try {x} catch (cAssertFailure) { break; } REPORT_ERROR("Test failure: assert didn't fire for %s, file %s, line %d\n", #x, __FILE__, __LINE__); exit(1); } while (0)
+
+#else
+ #ifdef _DEBUG
+ #define ASSERT( x) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__), assert(0), 0))
+ #else
+ #define ASSERT(x) ((void)(x))
+ #endif
+#endif
+
+// Pretty much the same as ASSERT() but stays in Release builds
+#define VERIFY( x) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0))
+
+// Same as assert but in all Self test builds
+#ifdef SELF_TEST
+ #define assert_test(x) ( !!(x) || (assert(!#x), exit(1), 0))
+#endif
+
+// Allow both Older versions of MSVC and newer versions of everything use a shared_ptr:
+// Note that we cannot typedef, because C++ doesn't allow (partial) templates to be typedeffed.
+#if (defined(_MSC_VER) && (_MSC_VER < 1600))
+ // MSVC before 2010 doesn't have std::shared_ptr, but has std::tr1::shared_ptr, defined in <memory> included earlier
+ #define SharedPtr std::tr1::shared_ptr
+#elif (defined(_MSC_VER) || (__cplusplus >= 201103L))
+ // C++11 has std::shared_ptr in <memory>, included earlier
+ #define SharedPtr std::shared_ptr
+#else
+ // C++03 has std::tr1::shared_ptr in <tr1/memory>
+ #include <tr1/memory>
+ #define SharedPtr std::tr1::shared_ptr
+#endif
+
+
+
+
+
+/** A generic interface used mainly in ForEach() functions */
+template <typename Type> class cItemCallback
+{
+public:
+ virtual ~cItemCallback() {}
+
+ /** Called for each item in the internal list; return true to stop the loop, or false to continue enumerating */
+ virtual bool Item(Type * a_Type) = 0;
+} ;
+
+
+
+
+/** Clamp X to the specified range. */
+template <typename T>
+T Clamp(T a_Value, T a_Min, T a_Max)
+{
+ return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value);
+}
+
+
+
+
+
+#ifndef TOLUA_TEMPLATE_BIND
+ #define TOLUA_TEMPLATE_BIND(x)
+#endif
+
+
+
+
+
+// Common headers (part 2, with macros):
+#include "src/ChunkDef.h"
+#include "src/BiomeDef.h"
+#include "src/BlockID.h"
+#include "src/BlockInfo.h"
+
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp
new file mode 100644
index 000000000..eb45690c1
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/MainWindow.cpp
@@ -0,0 +1,310 @@
+#include "Globals.h"
+#include "MainWindow.h"
+#include <QVBoxLayout>
+#include <QAction>
+#include <QMenuBar>
+#include <QApplication>
+#include <QFileDialog>
+#include <QSettings>
+#include <QDirIterator>
+#include "inifile/iniFile.h"
+#include "ChunkSource.h"
+#include "src/Generating/BioGen.h"
+#include "src/StringCompression.h"
+#include "src/WorldStorage/FastNBT.h"
+#include "GeneratorSetup.h"
+
+
+
+
+
+MainWindow::MainWindow(QWidget * parent) :
+ QMainWindow(parent),
+ m_GeneratorSetup(nullptr),
+ m_LineSeparator(nullptr)
+{
+ initMinecraftPath();
+
+ m_BiomeView = new BiomeView();
+ m_MainLayout = new QHBoxLayout();
+ m_MainLayout->addWidget(m_BiomeView, 1);
+ m_MainLayout->setMenuBar(menuBar());
+ m_MainLayout->setMargin(0);
+ QWidget * central = new QWidget();
+ central->setLayout(m_MainLayout);
+ setCentralWidget(central);
+
+ createActions();
+ createMenus();
+}
+
+
+
+
+
+MainWindow::~MainWindow()
+{
+
+}
+
+
+
+
+
+void MainWindow::newGenerator()
+{
+ // (Re-)open the generator setup dialog with empty settings:
+ openGeneratorSetup("");
+
+ // Set the chunk source:
+ cIniFilePtr iniFile = m_GeneratorSetup->getIniFile();
+ m_BiomeView->setChunkSource(std::shared_ptr<BioGenSource>(new BioGenSource(iniFile)));
+ m_BiomeView->redraw();
+}
+
+
+
+
+
+void MainWindow::openGenerator()
+{
+ // Let the user specify the world.ini file:
+ QString worldIni = QFileDialog::getOpenFileName(this, tr("Open world.ini"), QString(), tr("world.ini (world.ini)"));
+ if (worldIni.isEmpty())
+ {
+ return;
+ }
+
+ // (Re-)open the generator setup dialog:
+ openGeneratorSetup(worldIni.toStdString());
+
+ // Set the chunk source:
+ m_BiomeView->setChunkSource(std::shared_ptr<BioGenSource>(new BioGenSource(m_GeneratorSetup->getIniFile())));
+ m_BiomeView->redraw();
+}
+
+
+
+
+
+void MainWindow::openWorld()
+{
+ // Let the user specify the world:
+ QString regionFolder = QFileDialog::getExistingDirectory(this, tr("Select the region folder"), QString());
+ if (regionFolder.isEmpty())
+ {
+ return;
+ }
+
+ // Remove the generator setup dialog, if open:
+ closeGeneratorSetup();
+
+ // Set the chunk source:
+ m_BiomeView->setChunkSource(std::shared_ptr<AnvilSource>(new AnvilSource(regionFolder)));
+ m_BiomeView->redraw();
+}
+
+
+
+
+
+void MainWindow::openVanillaWorld()
+{
+ // The world is stored in the sender action's data, retrieve it:
+ QAction * action = qobject_cast<QAction *>(sender());
+ if (action == nullptr)
+ {
+ return;
+ }
+
+ // Remove the generator setup dialog, if open:
+ closeGeneratorSetup();
+
+ // Set the chunk source:
+ m_BiomeView->setChunkSource(std::shared_ptr<AnvilSource>(new AnvilSource(action->data().toString())));
+ m_BiomeView->redraw();
+}
+
+
+
+
+
+void MainWindow::initMinecraftPath()
+{
+ #ifdef Q_OS_MAC
+ m_MinecraftPath = QDir::homePath() + QDir::toNativeSeparators("/Library/Application Support/minecraft");
+ #elif defined Q_OS_WIN32
+ QSettings ini(QSettings::IniFormat, QSettings::UserScope, ".minecraft", "minecraft1");
+ m_MinecraftPath = QFileInfo(ini.fileName()).absolutePath();
+ #else
+ m_MinecraftPath = QDir::homePath() + QDir::toNativeSeparators("/.minecraft");
+ #endif
+}
+
+
+
+
+
+void MainWindow::createActions()
+{
+ createWorldActions();
+
+ m_actNewGen = new QAction(tr("&New generator"), this);
+ m_actNewGen->setShortcut(tr("Ctrl+N"));
+ m_actNewGen->setStatusTip(tr("Open a generator INI file and display the generated biomes"));
+ connect(m_actNewGen, SIGNAL(triggered()), this, SLOT(newGenerator()));
+
+ m_actOpenGen = new QAction(tr("&Open generator..."), this);
+ m_actOpenGen->setShortcut(tr("Ctrl+G"));
+ m_actOpenGen->setStatusTip(tr("Open a generator INI file and display the generated biomes"));
+ connect(m_actOpenGen, SIGNAL(triggered()), this, SLOT(openGenerator()));
+
+ m_actOpenWorld = new QAction(tr("&Open world..."), this);
+ m_actOpenWorld->setShortcut(tr("Ctrl+O"));
+ m_actOpenWorld->setStatusTip(tr("Open an existing world and display its biomes"));
+ connect(m_actOpenWorld, SIGNAL(triggered()), this, SLOT(openWorld()));
+
+ m_actReload = new QAction(tr("&Reload"), this);
+ m_actReload->setShortcut(tr("F5"));
+ m_actReload->setStatusTip(tr("Clear the view cache and force a reload of all the data"));
+ 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()));
+ connect(m_actExit, SIGNAL(triggered()), this, SLOT(close()));
+}
+
+
+
+
+
+void MainWindow::createWorldActions()
+{
+ QDir mc(m_MinecraftPath);
+ if (!mc.cd("saves"))
+ {
+ return;
+ }
+
+ QDirIterator it(mc);
+ int key = 1;
+ while (it.hasNext())
+ {
+ it.next();
+ if (!it.fileInfo().isDir())
+ {
+ continue;
+ }
+ QString name = getWorldName(it.filePath().toStdString());
+ if (name.isEmpty())
+ {
+ continue;
+ }
+ QAction * w = new QAction(this);
+ w->setText(name);
+ w->setData(it.filePath() + "/region");
+ if (key < 10)
+ {
+ w->setShortcut("Ctrl+" + QString::number(key));
+ key++;
+ }
+ connect(w, SIGNAL(triggered()), this, SLOT(openVanillaWorld()));
+ m_WorldActions.append(w);
+ }
+}
+
+
+
+
+
+void MainWindow::createMenus()
+{
+ QMenu * file = menuBar()->addMenu(tr("&Map"));
+ file->addAction(m_actNewGen);
+ file->addAction(m_actOpenGen);
+ file->addSeparator();
+ QMenu * worlds = file->addMenu(tr("Open existing"));
+ worlds->addActions(m_WorldActions);
+ if (m_WorldActions.empty())
+ {
+ worlds->setEnabled(false);
+ }
+ file->addAction(m_actOpenWorld);
+ file->addSeparator();
+ file->addAction(m_actReload);
+ file->addSeparator();
+ file->addAction(m_actExit);
+}
+
+
+
+
+
+QString MainWindow::getWorldName(const AString & a_Path)
+{
+ AString levelData = cFile::ReadWholeFile(a_Path + "/level.dat");
+ if (levelData.empty())
+ {
+ // No such file / no data
+ return QString();
+ }
+
+ AString uncompressed;
+ if (UncompressStringGZIP(levelData.data(), levelData.size(), uncompressed) != Z_OK)
+ {
+ return QString();
+ }
+ cParsedNBT nbt(uncompressed.data(), uncompressed.size());
+ if (!nbt.IsValid())
+ {
+ return QString();
+ }
+ AString name = nbt.GetName(1);
+ int levelNameTag = nbt.FindTagByPath(nbt.GetRoot(), "Data\\LevelName");
+ if ((levelNameTag <= 0) || (nbt.GetType(levelNameTag) != TAG_String))
+ {
+ return QString();
+ }
+ return QString::fromStdString(nbt.GetString(levelNameTag));
+}
+
+
+
+
+
+void MainWindow::openGeneratorSetup(const AString & a_IniFileName)
+{
+ // Close any previous editor:
+ closeGeneratorSetup();
+
+ // Open up a new editor:
+ m_GeneratorSetup = new GeneratorSetup(a_IniFileName);
+ m_LineSeparator = new QWidget();
+ m_LineSeparator->setFixedWidth(2);
+ m_LineSeparator->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+ m_LineSeparator->setStyleSheet(QString("background-color: #c0c0c0;"));
+ m_MainLayout->addWidget(m_LineSeparator);
+ m_MainLayout->addWidget(m_GeneratorSetup);
+
+ // Connect the signals from the setup pane:
+ connect(m_GeneratorSetup, SIGNAL(generatorUpdated()), m_BiomeView, SLOT(reload()));
+}
+
+
+
+
+
+void MainWindow::closeGeneratorSetup()
+{
+ delete m_MainLayout->takeAt(2);
+ delete m_MainLayout->takeAt(1);
+ delete m_GeneratorSetup;
+ delete m_LineSeparator;
+ m_GeneratorSetup = nullptr;
+ m_LineSeparator = nullptr;
+}
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/MainWindow.h b/Tools/QtBiomeVisualiser/MainWindow.h
new file mode 100644
index 000000000..6490a937f
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/MainWindow.h
@@ -0,0 +1,96 @@
+#pragma once
+
+#include <memory>
+#include <QList>
+#include <QMainWindow>
+#include <QHBoxLayout>
+#include "BiomeView.h"
+
+
+
+
+
+// fwd:
+class GeneratorSetup;
+
+
+
+
+
+class MainWindow :
+ public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow(QWidget * parent = nullptr);
+ ~MainWindow();
+
+private slots:
+ /** Creates a generator definition from scratch, lets user modify generator params in realtime. */
+ void newGenerator();
+
+ /** Opens a generator definition and generates the biomes based on that. */
+ void openGenerator();
+
+ /** Opens an existing world and displays the loaded biomes. */
+ void openWorld();
+
+ /** Opens a vanilla world that is specified by the calling action. */
+ void openVanillaWorld();
+
+protected:
+ // Actions:
+ QAction * m_actNewGen;
+ QAction * m_actOpenGen;
+ QAction * m_actOpenWorld;
+ QAction * m_actReload;
+ QAction * m_actExit;
+
+ /** List of actions that open the specific vanilla world. */
+ QList<QAction *> m_WorldActions;
+
+ /** Path to the vanilla folder. */
+ QString m_MinecraftPath;
+
+ /** The pane for setting up the generator, available when visualising a generator. */
+ GeneratorSetup * m_GeneratorSetup;
+
+ /** The main biome display widget. */
+ BiomeView * m_BiomeView;
+
+ /** The layout for the window. */
+ QHBoxLayout * m_MainLayout;
+
+ /** The separator line between biome view and generator setup. */
+ QWidget * m_LineSeparator;
+
+
+ /** Initializes the m_MinecraftPath based on the proper MC path */
+ void initMinecraftPath();
+
+ /** Creates the actions that the UI supports. */
+ void createActions();
+
+ /** Creates the actions that open a specific vanilla world. Iterates over the minecraft saves folder. */
+ void createWorldActions();
+
+ /** Creates the menu bar and connects its events. */
+ void createMenus();
+
+ /** Returns the name of the vanilla world in the specified path.
+ Reads the level.dat file for the name. Returns an empty string on failure. */
+ QString getWorldName(const AString & a_Path);
+
+ /** Opens the generator setup pane, if not already open, and loads the specified INI file to it. */
+ void openGeneratorSetup(const AString & a_IniFileName);
+
+ /** Closes and destroys the generator setup pane, if there is one. */
+ void closeGeneratorSetup();
+};
+
+
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro
new file mode 100644
index 000000000..d6630bd34
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro
@@ -0,0 +1,94 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2014-09-11T15:22:43
+#
+#-------------------------------------------------
+
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = QtBiomeVisualiser
+TEMPLATE = app
+
+
+SOURCES += main.cpp\
+ MainWindow.cpp \
+ BiomeView.cpp \
+ ../../src/Generating/BioGen.cpp \
+ ../../src/VoronoiMap.cpp \
+ ../../src/Noise.cpp \
+ ../../src/StringUtils.cpp \
+ ../../src/LoggerListeners.cpp \
+ ../../src/Logger.cpp \
+ ../../lib/inifile/iniFile.cpp \
+ ../../src/OSSupport/File.cpp \
+ ../../src/OSSupport/CriticalSection.cpp \
+ ../../src/OSSupport/IsThread.cpp \
+ ../../src/BiomeDef.cpp \
+ ChunkCache.cpp \
+ Chunk.cpp \
+ ChunkSource.cpp \
+ ChunkLoader.cpp \
+ ../../src/StringCompression.cpp \
+ ../../src/WorldStorage/FastNBT.cpp \
+ ../../lib/zlib/adler32.c \
+ ../../lib/zlib/compress.c \
+ ../../lib/zlib/crc32.c \
+ ../../lib/zlib/deflate.c \
+ ../../lib/zlib/gzclose.c \
+ ../../lib/zlib/gzlib.c \
+ ../../lib/zlib/gzread.c \
+ ../../lib/zlib/gzwrite.c \
+ ../../lib/zlib/infback.c \
+ ../../lib/zlib/inffast.c \
+ ../../lib/zlib/inflate.c \
+ ../../lib/zlib/inftrees.c \
+ ../../lib/zlib/trees.c \
+ ../../lib/zlib/uncompr.c \
+ ../../lib/zlib/zutil.c \
+ GeneratorSetup.cpp
+
+HEADERS += MainWindow.h \
+ Globals.h \
+ BiomeView.h \
+ ../../src/Generating/BioGen.h \
+ ../../src/VoronoiMap.h \
+ ../../src/Noise.h \
+ ../../src/StringUtils.h \
+ ../../src/LoggerListeners.h \
+ ../../src/Logger.h \
+ ../../lib/inifile/iniFile.h \
+ ../../src/OSSupport/File.h \
+ ../../src/OSSupport/CriticalSection.h \
+ ../../src/OSSupport/IsThread.h \
+ ../../src/BiomeDef.h \
+ ChunkCache.h \
+ Chunk.h \
+ ChunkSource.h \
+ ChunkLoader.h \
+ ../../src/StringCompression.h \
+ ../../src/WorldStorage/FastNBT.h \
+ ../../lib/zlib/crc32.h \
+ ../../lib/zlib/deflate.h \
+ ../../lib/zlib/gzguts.h \
+ ../../lib/zlib/inffast.h \
+ ../../lib/zlib/inffixed.h \
+ ../../lib/zlib/inflate.h \
+ ../../lib/zlib/inftrees.h \
+ ../../lib/zlib/trees.h \
+ ../../lib/zlib/zconf.h \
+ ../../lib/zlib/zlib.h \
+ ../../lib/zlib/zutil.h \
+ GeneratorSetup.h
+
+INCLUDEPATH += $$_PRO_FILE_PWD_ \
+ $$_PRO_FILE_PWD_/../../lib \
+ $$_PRO_FILE_PWD_/../../
+
+
+CONFIG += C++11
+
+OTHER_FILES +=
+
+
diff --git a/Tools/QtBiomeVisualiser/main.cpp b/Tools/QtBiomeVisualiser/main.cpp
new file mode 100644
index 000000000..f41cdcfb2
--- /dev/null
+++ b/Tools/QtBiomeVisualiser/main.cpp
@@ -0,0 +1,20 @@
+#include "Globals.h"
+#include "MainWindow.h"
+#include <QApplication>
+
+
+
+
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ MainWindow w;
+ w.show();
+
+ return a.exec();
+}
+
+
+
+