1
0

Added new Qt-based biome visualiser.

Compile with Qt 5.1+
This commit is contained in:
Mattes D 2014-09-14 01:32:00 +02:00
parent c4a53c5d7d
commit e3a2dc5a13
37 changed files with 1482 additions and 2181 deletions

1
Tools/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
Debug/

View File

@ -1,4 +0,0 @@
Debug/
logs/
Release/
Release profiled/

View File

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

View File

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

View File

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

View File

@ -1,15 +0,0 @@
// BiomeColors.h
// Declares the g_BiomeColors[] array used for biome color lookup
extern int g_BiomeColors[256];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

2
Tools/QtBiomeVisualiser/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.pro.user
*.pro.user.*

View File

@ -0,0 +1,246 @@
#include "Globals.h"
#include "BiomeView.h"
#include "Chunk.h"
#include <QPainter>
#include <QResizeEvent>
BiomeView::BiomeView(QWidget * parent) :
super(parent),
m_X(0),
m_Z(0),
m_Zoom(1)
{
// 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)));
}
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::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::queueChunkRender(ChunkPtr a_Chunk)
{
}

View File

@ -0,0 +1,65 @@
#pragma once
#include <QWidget>
#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);
protected:
double m_X, m_Z;
int m_Zoom;
ChunkCache m_Cache;
QImage m_Image;
/** 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;
/** Queues the chunk for rendering. */
void queueChunkRender(ChunkPtr a_Chunk);
};

View File

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

View File

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

View File

@ -0,0 +1,110 @@
#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::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);
}

View File

@ -0,0 +1,68 @@
#pragma once
#include <QObject>
#include <QCache>
#include <QMutex>
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(void) const { return (m_ChunkSource.get() != nullptr); }
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);
};

View File

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

View File

@ -0,0 +1,43 @@
#pragma once
#include <QObject>
#include <QRunnable>
// 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;
};

View File

@ -0,0 +1,164 @@
#include "Globals.h"
#include "ChunkSource.h"
#include "Generating/BioGen.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[0];
color[1] = biomeColors[i].m_Color[1];
color[2] = biomeColors[i].m_Color[2];
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(cBiomeGen * a_BiomeGen) :
m_BiomeGen(a_BiomeGen)
{
}
void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk)
{
// TODO: To make use of multicore machines, we need multiple copies of the biomegen
// Right now we have only one, so we can let only one thread use it (hence the mutex)
QMutexLocker lock(&m_Mtx);
cChunkDef::BiomeMap biomes;
m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, biomes);
Chunk::Image img;
biomesToImage(biomes, img);
a_DestChunk->setImage(img);
}

View File

@ -0,0 +1,60 @@
#pragma once
#include "Chunk.h"
// fwd:
class cBiomeGen;
/** 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;
};
class BioGenSource :
public ChunkSource
{
public:
/** Constructs a new BioGenSource based on the biome generator given.
Takes ownership of a_BiomeGen */
BioGenSource(cBiomeGen * a_BiomeGen);
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override;
protected:
std::shared_ptr<cBiomeGen> m_BiomeGen;
QMutex m_Mtx;
};
class AnvilSource :
public ChunkSource
{
public:
// TODO
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override;
};

View File

@ -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 "StringUtils.h"
#include "OSSupport/Sleep.h"
#include "OSSupport/CriticalSection.h"
#include "OSSupport/Semaphore.h"
#include "OSSupport/Event.h"
#include "OSSupport/Thread.h"
#include "OSSupport/File.h"
#include "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 "ChunkDef.h"
#include "BiomeDef.h"
#include "BlockID.h"
#include "BlockInfo.h"

View File

@ -0,0 +1,104 @@
#include "Globals.h"
#include "MainWindow.h"
#include <QVBoxLayout>
#include <QAction>
#include <QMenuBar>
#include <QApplication>
#include <QFileDialog>
#include "inifile/iniFile.h"
#include "ChunkSource.h"
#include "Generating/BioGen.h"
MainWindow::MainWindow(QWidget * parent) :
QMainWindow(parent)
{
createActions();
createMenus();
m_BiomeView = new BiomeView(this);
setCentralWidget(m_BiomeView);
}
MainWindow::~MainWindow()
{
}
void MainWindow::generate()
{
QString worldIni = QFileDialog::getOpenFileName(this, tr("Open world.ini"), QString(), tr("world.ini (world.ini)"));
cIniFile ini;
if (!ini.ReadFile(worldIni.toStdString()))
{
return;
}
int seed = ini.GetValueSetI("Seed", "Seed", 0);
bool unused = false;
cBiomeGen * biomeGen = cBiomeGen::CreateBiomeGen(ini, seed, unused);
if (biomeGen == nullptr)
{
return;
}
m_BiomeView->setChunkSource(std::shared_ptr<BioGenSource>(new BioGenSource(biomeGen)));
m_BiomeView->redraw();
}
void MainWindow::open()
{
// TODO
}
void MainWindow::createActions()
{
m_actGen = new QAction(tr("&Generate..."), this);
m_actGen->setShortcut(tr("Ctrl+N"));
m_actGen->setStatusTip(tr("Open a generator INI file and display the generated biomes"));
connect(m_actGen, SIGNAL(triggered()), this, SLOT(generate()));
m_actOpen = new QAction(tr("&Open world..."), this);
m_actOpen->setShortcut(tr("Ctrl+O"));
m_actOpen->setStatusTip(tr("Open an existing world and display its biomes"));
connect(m_actOpen, SIGNAL(triggered()), this, SLOT(open()));
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::createMenus()
{
QMenu * mFile = menuBar()->addMenu(tr("&World"));
mFile->addAction(m_actGen);
mFile->addAction(m_actOpen);
mFile->addSeparator();
mFile->addAction(m_actExit);
}

View File

@ -0,0 +1,46 @@
#pragma once
#include <QMainWindow>
#include "BiomeView.h"
class MainWindow :
public QMainWindow
{
Q_OBJECT
BiomeView * m_BiomeView;
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
/** Opens a generator definition and generates the biomes based on that. */
void generate();
/** Opens an existing world and displays the loaded biomes. */
void open();
protected:
// Actions:
QAction * m_actGen;
QAction * m_actOpen;
QAction * m_actExit;
/** Creates the actions that the UI supports. */
void createActions();
/** Creates the menu bar and connects its events. */
void createMenus();
};

View File

@ -0,0 +1,62 @@
#-------------------------------------------------
#
# 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
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
INCLUDEPATH += $$_PRO_FILE_PWD_ \
$$_PRO_FILE_PWD_/../../src \
$$_PRO_FILE_PWD_/../../lib
CONFIG += STATIC

View File

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