1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-18 17:40:48 +02:00

Merge branch 'cpp-map-editor' into EraseAction

This commit is contained in:
Nordsoft91 2022-09-06 21:24:07 +04:00 committed by GitHub
commit cb09ea9814
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 385 additions and 407 deletions

View File

@ -4,13 +4,10 @@
// //
// Created by nordsoft on 29.08.2022. // Created by nordsoft on 29.08.2022.
// //
#include "BitmapHandler.h"
#include "StdInc.h" #include "StdInc.h"
#include "BitmapHandler.h"
#include "../lib/filesystem/Filesystem.h" #include "../lib/filesystem/Filesystem.h"
#include "BitmapHandler.h"
#include <QBitmap> #include <QBitmap>
#include <QImage> #include <QImage>
@ -21,152 +18,152 @@ namespace BitmapHandler
QImage loadH3PCX(ui8 * data, size_t size); QImage loadH3PCX(ui8 * data, size_t size);
QImage loadBitmapFromDir(std::string path, std::string fname, bool setKey=true); QImage loadBitmapFromDir(std::string path, std::string fname, bool setKey=true);
}
bool isPCX(const ui8 *header)//check whether file can be PCX according to header bool isPCX(const ui8 *header)//check whether file can be PCX according to header
{
ui32 fSize = read_le_u32(header + 0);
ui32 width = read_le_u32(header + 4);
ui32 height = read_le_u32(header + 8);
return fSize == width*height || fSize == width*height*3;
}
enum Epcxformat
{
PCX8B,
PCX24B
};
QImage BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
{
//SDL_Surface * ret;
Epcxformat format;
int it=0;
ui32 fSize = read_le_u32(pcx + it); it+=4;
ui32 width = read_le_u32(pcx + it); it+=4;
ui32 height = read_le_u32(pcx + it); it+=4;
if (fSize==width*height*3)
format=PCX24B;
else if (fSize==width*height)
format=PCX8B;
else
return QImage();
QSize qsize(width, height);
if (format==PCX8B)
{ {
it = 0xC; ui32 fSize = read_le_u32(header + 0);
//auto bitmap = QBitmap::fromData(qsize, pcx + it); ui32 width = read_le_u32(header + 4);
QImage image(pcx + it, width, height, QImage::Format_Indexed8); ui32 height = read_le_u32(header + 8);
return fSize == width*height || fSize == width*height*3;
}
enum Epcxformat
{
PCX8B,
PCX24B
};
QImage loadH3PCX(ui8 * pcx, size_t size)
{
//SDL_Surface * ret;
//palette - last 256*3 bytes Epcxformat format;
QVector<QRgb> colorTable; int it=0;
it = (int)size-256*3;
for (int i=0;i<256;i++) ui32 fSize = read_le_u32(pcx + it); it+=4;
ui32 width = read_le_u32(pcx + it); it+=4;
ui32 height = read_le_u32(pcx + it); it+=4;
if (fSize==width*height*3)
format=PCX24B;
else if (fSize==width*height)
format=PCX8B;
else
return QImage();
QSize qsize(width, height);
if (format==PCX8B)
{ {
char bytes[3]; it = 0xC;
bytes[0] = pcx[it++]; //auto bitmap = QBitmap::fromData(qsize, pcx + it);
bytes[1] = pcx[it++]; QImage image(pcx + it, width, height, QImage::Format_Indexed8);
bytes[2] = pcx[it++];
colorTable.append(qRgb(bytes[0], bytes[1], bytes[2])); //palette - last 256*3 bytes
} QVector<QRgb> colorTable;
image.setColorTable(colorTable); it = (int)size-256*3;
return image; for (int i=0;i<256;i++)
}
else
{
QImage image(pcx + it, width, height, QImage::Format_RGB32);
return image;
}
}
QImage BitmapHandler::loadBitmapFromDir(std::string path, std::string fname, bool setKey)
{
if(!fname.size())
{
logGlobal->warn("Call to loadBitmap with void fname!");
return QImage();
}
if (!CResourceHandler::get()->existsResource(ResourceID(path + fname, EResType::IMAGE)))
{
return QImage();
}
auto fullpath = CResourceHandler::get()->getResourceName(ResourceID(path + fname, EResType::IMAGE));
auto readFile = CResourceHandler::get()->load(ResourceID(path + fname, EResType::IMAGE))->readAll();
if (isPCX(readFile.first.get()))
{//H3-style PCX
auto image = loadH3PCX(readFile.first.get(), readFile.second);
if(!image.isNull())
{
if(image.bitPlaneCount() == 1 && setKey)
{ {
QVector<QRgb> colorTable = image.colorTable(); char bytes[3];
colorTable[0] = qRgba(255, 255, 255, 0); bytes[0] = pcx[it++];
image.setColorTable(colorTable); bytes[1] = pcx[it++];
bytes[2] = pcx[it++];
colorTable.append(qRgb(bytes[0], bytes[1], bytes[2]));
} }
image.setColorTable(colorTable);
return image;
} }
else else
{ {
logGlobal->error("Failed to open %s as H3 PCX!", fname); QImage image(pcx + it, width, height, QImage::Format_RGB32);
}
return image;
}
else
{ //loading via SDL_Image
QImage image(QString::fromStdString(fullpath->make_preferred().string()));
if(!image.isNull())
{
if(image.bitPlaneCount() == 1)
{
//set correct value for alpha\unused channel
QVector<QRgb> colorTable = image.colorTable();
for(auto & c : colorTable)
c = qRgb(qRed(c), qGreen(c), qBlue(c));
image.setColorTable(colorTable);
}
}
else
{
logGlobal->error("Failed to open %s via QImage", fname);
return image; return image;
} }
} }
return QImage();
// When modifying anything here please check two use cases:
// 1) Vampire mansion in Necropolis (not 1st color is transparent)
// 2) Battle background when fighting on grass/dirt, topmost sky part (NO transparent color)
// 3) New objects that may use 24-bit images for icons (e.g. witchking arts)
/*if (ret->format->palette)
{
CSDL_Ext::setDefaultColorKeyPresize(ret);
}
else if (ret->format->Amask)
{
SDL_SetSurfaceBlendMode(ret, SDL_BLENDMODE_BLEND);
}
else // always set
{
CSDL_Ext::setDefaultColorKey(ret);
}
return ret;*/
}
QImage BitmapHandler::loadBitmap(std::string fname, bool setKey) QImage loadBitmapFromDir(std::string path, std::string fname, bool setKey)
{
QImage image = loadBitmapFromDir("DATA/", fname, setKey);
if(image.isNull())
{ {
image = loadBitmapFromDir("SPRITES/", fname, setKey); if(!fname.size())
{
logGlobal->warn("Call to loadBitmap with void fname!");
return QImage();
}
if (!CResourceHandler::get()->existsResource(ResourceID(path + fname, EResType::IMAGE)))
{
return QImage();
}
auto fullpath = CResourceHandler::get()->getResourceName(ResourceID(path + fname, EResType::IMAGE));
auto readFile = CResourceHandler::get()->load(ResourceID(path + fname, EResType::IMAGE))->readAll();
if (isPCX(readFile.first.get()))
{//H3-style PCX
auto image = BitmapHandler::loadH3PCX(readFile.first.get(), readFile.second);
if(!image.isNull())
{
if(image.bitPlaneCount() == 1 && setKey)
{
QVector<QRgb> colorTable = image.colorTable();
colorTable[0] = qRgba(255, 255, 255, 0);
image.setColorTable(colorTable);
}
}
else
{
logGlobal->error("Failed to open %s as H3 PCX!", fname);
}
return image;
}
else
{ //loading via SDL_Image
QImage image(QString::fromStdString(fullpath->make_preferred().string()));
if(!image.isNull())
{
if(image.bitPlaneCount() == 1)
{
//set correct value for alpha\unused channel
QVector<QRgb> colorTable = image.colorTable();
for(auto & c : colorTable)
c = qRgb(qRed(c), qGreen(c), qBlue(c));
image.setColorTable(colorTable);
}
}
else
{
logGlobal->error("Failed to open %s via QImage", fname);
return image;
}
}
return QImage();
// When modifying anything here please check two use cases:
// 1) Vampire mansion in Necropolis (not 1st color is transparent)
// 2) Battle background when fighting on grass/dirt, topmost sky part (NO transparent color)
// 3) New objects that may use 24-bit images for icons (e.g. witchking arts)
/*if (ret->format->palette)
{
CSDL_Ext::setDefaultColorKeyPresize(ret);
}
else if (ret->format->Amask)
{
SDL_SetSurfaceBlendMode(ret, SDL_BLENDMODE_BLEND);
}
else // always set
{
CSDL_Ext::setDefaultColorKey(ret);
}
return ret;*/
}
QImage loadBitmap(std::string fname, bool setKey)
{
QImage image = loadBitmapFromDir("DATA/", fname, setKey);
if(image.isNull()) if(image.isNull())
{ {
logGlobal->error("Error: Failed to find file %s", fname); image = loadBitmapFromDir("SPRITES/", fname, setKey);
if(image.isNull())
{
logGlobal->error("Error: Failed to find file %s", fname);
}
} }
return image;
} }
return image;
} }

View File

@ -10,6 +10,8 @@
#define read_le_u16(p) (* reinterpret_cast<const ui16 *>(p)) #define read_le_u16(p) (* reinterpret_cast<const ui16 *>(p))
#define read_le_u32(p) (* reinterpret_cast<const ui32 *>(p)) #define read_le_u32(p) (* reinterpret_cast<const ui32 *>(p))
#include <QImage>
namespace BitmapHandler namespace BitmapHandler
{ {
//Load file from /DATA or /SPRITES //Load file from /DATA or /SPRITES

View File

@ -4,9 +4,10 @@
#include "../lib/spells/CSpellHandler.h" #include "../lib/spells/CSpellHandler.h"
#include "../lib/CRandomGenerator.h" #include "../lib/CRandomGenerator.h"
#include "../lib/mapObjects/CObjectClassesHandler.h" #include "../lib/mapObjects/CObjectClassesHandler.h"
#include "../lib/mapping/CMap.h"
//===============IMPLEMENT OBJECT INITIALIZATION FUNCTIONS================ //===============IMPLEMENT OBJECT INITIALIZATION FUNCTIONS================
Initializer::Initializer(CGObjectInstance * o) Initializer::Initializer(CMap * m, CGObjectInstance * o) : map(m)
{ {
///IMPORTANT! initialize order should be from base objects to derived objects ///IMPORTANT! initialize order should be from base objects to derived objects
INIT_OBJ_TYPE(CGResource); INIT_OBJ_TYPE(CGResource);
@ -16,14 +17,14 @@ Initializer::Initializer(CGObjectInstance * o)
INIT_OBJ_TYPE(CGTownInstance); INIT_OBJ_TYPE(CGTownInstance);
} }
void initialize(CArmedInstance * o) void Initializer::initialize(CArmedInstance * o)
{ {
if(!o) return; if(!o) return;
o->tempOwner = PlayerColor::NEUTRAL; o->tempOwner = PlayerColor::NEUTRAL;
} }
void initialize(CGTownInstance * o) void Initializer::initialize(CGTownInstance * o)
{ {
if(!o) return; if(!o) return;
@ -37,7 +38,7 @@ void initialize(CGTownInstance * o)
} }
} }
void initialize(CGArtifact * o) void Initializer::initialize(CGArtifact * o)
{ {
if(!o) return; if(!o) return;
@ -46,7 +47,7 @@ void initialize(CGArtifact * o)
std::vector<SpellID> out; std::vector<SpellID> out;
for(auto spell : VLC->spellh->objects) //spellh size appears to be greater (?) for(auto spell : VLC->spellh->objects) //spellh size appears to be greater (?)
{ {
if(/*map.isAllowedSpell(spell->id) && spell->level == i + 1*/ true) //if(map->isAllowedSpell(spell->id))
{ {
out.push_back(spell->id); out.push_back(spell->id);
} }
@ -56,7 +57,7 @@ void initialize(CGArtifact * o)
} }
} }
void initialize(CGMine * o) void Initializer::initialize(CGMine * o)
{ {
if(!o) return; if(!o) return;
@ -64,7 +65,7 @@ void initialize(CGMine * o)
o->producedQuantity = o->defaultResProduction(); o->producedQuantity = o->defaultResProduction();
} }
void initialize(CGResource * o) void Initializer::initialize(CGResource * o)
{ {
if(!o) return; if(!o) return;

View File

@ -18,12 +18,23 @@ void setProperty(x*, const QString &, const QVariant &);
#define UPDATE_OBJ_PROPERTIES(x) updateProperties(dynamic_cast<x*>(obj)) #define UPDATE_OBJ_PROPERTIES(x) updateProperties(dynamic_cast<x*>(obj))
#define SET_PROPERTIES(x) setProperty(dynamic_cast<x*>(obj), key, value) #define SET_PROPERTIES(x) setProperty(dynamic_cast<x*>(obj), key, value)
//===============DECLARE MAP OBJECTS======================================
DECLARE_OBJ_TYPE(CArmedInstance); class Initializer
DECLARE_OBJ_TYPE(CGTownInstance); {
DECLARE_OBJ_TYPE(CGArtifact); public:
DECLARE_OBJ_TYPE(CGMine); //===============DECLARE MAP OBJECTS======================================
DECLARE_OBJ_TYPE(CGResource); DECLARE_OBJ_TYPE(CArmedInstance);
DECLARE_OBJ_TYPE(CGTownInstance);
DECLARE_OBJ_TYPE(CGArtifact);
DECLARE_OBJ_TYPE(CGMine);
DECLARE_OBJ_TYPE(CGResource);
Initializer(CMap *, CGObjectInstance *);
private:
CMap * map;
};
class Inspector class Inspector
{ {
@ -90,11 +101,7 @@ protected:
}; };
class Initializer
{
public:
Initializer(CGObjectInstance *);
};
class PlayerColorDelegate : public QStyledItemDelegate class PlayerColorDelegate : public QStyledItemDelegate
{ {

View File

@ -103,7 +103,9 @@ void MapController::sceneForceUpdate(int level)
void MapController::resetMapHandler() void MapController::resetMapHandler()
{ {
_mapHandler.reset(new MapHandler(_map.get())); if(!_mapHandler)
_mapHandler.reset(new MapHandler());
_mapHandler->reset(map());
_scenes[0]->initialize(*this); _scenes[0]->initialize(*this);
_scenes[1]->initialize(*this); _scenes[1]->initialize(*this);
_miniscenes[0]->initialize(*this); _miniscenes[0]->initialize(*this);
@ -141,7 +143,9 @@ void MapController::commitObjectErase(int level)
} }
else if (selectedObjects.size() == 1) else if (selectedObjects.size() == 1)
{ {
_map->getEditManager()->removeObject(*selectedObjects.begin()); _map->getEditManager()->removeObject(selectedObjects.front());
//invalidate tiles under object
_mapHandler->invalidate(_mapHandler->geTilesUnderObject(selectedObjects.front()));
} }
else //nothing to erase - shouldn't be here else //nothing to erase - shouldn't be here
{ {
@ -149,8 +153,8 @@ void MapController::commitObjectErase(int level)
} }
_scenes[level]->selectionObjectsView.clear(); _scenes[level]->selectionObjectsView.clear();
resetMapHandler(); _scenes[level]->objectsView.draw();
_scenes[level]->updateViews(); _scenes[level]->selectionObjectsView.draw();
_miniscenes[level]->updateViews(); _miniscenes[level]->updateViews();
main->mapChanged(); main->mapChanged();
@ -201,8 +205,14 @@ void MapController::commitObstacleFill(int level)
sel.second.placeObstacles(_map.get(), CRandomGenerator::getDefault()); sel.second.placeObstacles(_map.get(), CRandomGenerator::getDefault());
} }
resetMapHandler(); for(auto & t : selection)
_scenes[level]->updateViews(); {
_mapHandler->invalidate(t.x, t.y, t.z);
}
_scenes[level]->selectionTerrainView.clear();
_scenes[level]->selectionTerrainView.draw();
_scenes[level]->objectsView.draw();
_miniscenes[level]->updateViews(); _miniscenes[level]->updateViews();
main->mapChanged(); main->mapChanged();
@ -210,7 +220,8 @@ void MapController::commitObstacleFill(int level)
void MapController::commitObjectChange(int level) void MapController::commitObjectChange(int level)
{ {
resetMapHandler(); //for(auto * o : _scenes[level]->selectionObjectsView.getSelection())
//_mapHandler->invalidate(o);
_scenes[level]->objectsView.draw(); _scenes[level]->objectsView.draw();
_scenes[level]->selectionObjectsView.draw(); _scenes[level]->selectionObjectsView.draw();
@ -244,16 +255,18 @@ void MapController::commitObjectShiftOrCreate(int level)
} }
else else
{ {
auto prevPositions = _mapHandler->geTilesUnderObject(obj);
_map->getEditManager()->moveObject(obj, pos); _map->getEditManager()->moveObject(obj, pos);
_mapHandler->invalidate(prevPositions);
_mapHandler->invalidate(obj);
} }
} }
_scenes[level]->selectionObjectsView.newObject = nullptr; _scenes[level]->selectionObjectsView.newObject = nullptr;
_scenes[level]->selectionObjectsView.shift = QPoint(0, 0); _scenes[level]->selectionObjectsView.shift = QPoint(0, 0);
_scenes[level]->selectionObjectsView.selectionMode = 0; _scenes[level]->selectionObjectsView.selectionMode = 0;
_scenes[level]->objectsView.draw();
resetMapHandler(); _scenes[level]->selectionObjectsView.draw();
_scenes[level]->updateViews();
_miniscenes[level]->updateViews(); _miniscenes[level]->updateViews();
main->mapChanged(); main->mapChanged();
@ -264,9 +277,10 @@ void MapController::commitObjectCreate(int level)
auto * newObj = _scenes[level]->selectionObjectsView.newObject; auto * newObj = _scenes[level]->selectionObjectsView.newObject;
if(!newObj) if(!newObj)
return; return;
Initializer init(newObj); Initializer init(map(), newObj);
_map->getEditManager()->insertObject(newObj); _map->getEditManager()->insertObject(newObj);
_mapHandler->invalidate(newObj);
main->mapChanged(); main->mapChanged();
} }

View File

@ -13,26 +13,37 @@
const int tileSize = 32; const int tileSize = 32;
static bool objectBlitOrderSorter(const TerrainTileObject & a, const TerrainTileObject & b) static bool objectBlitOrderSorter(const TileObject & a, const TileObject & b)
{ {
return MapHandler::compareObjectBlitOrder(a.obj, b.obj); return MapHandler::compareObjectBlitOrder(a.obj, b.obj);
} }
MapHandler::MapHandler(const CMap * Map): int MapHandler::index(int x, int y, int z) const
map(Map)
{ {
init(); return z * (sizes.x * sizes.y) + y * sizes.x + x;
} }
void MapHandler::init() int MapHandler::index(const int3 & p) const
{ {
return index(p.x, p.y, p.z);
}
MapHandler::MapHandler()
{
initTerrainGraphics();
logGlobal->info("\tPreparing terrain, roads, rivers, borders");
}
void MapHandler::reset(const CMap * Map)
{
ttiles.clear();
map = Map;
//sizes of terrain //sizes of terrain
sizes.x = map->width; sizes.x = map->width;
sizes.y = map->height; sizes.y = map->height;
sizes.z = map->twoLevel ? 2 : 1; sizes.z = map->twoLevel ? 2 : 1;
initTerrainGraphics();
logGlobal->info("\tPreparing terrain, roads, rivers, borders");
initObjectRects(); initObjectRects();
logGlobal->info("\tMaking object rects"); logGlobal->info("\tMaking object rects");
} }
@ -78,22 +89,17 @@ void MapHandler::initTerrainGraphics()
loadFlipped(terrainAnimations, terrainImages, terrainFiles); loadFlipped(terrainAnimations, terrainImages, terrainFiles);
loadFlipped(roadAnimations, roadImages, ROAD_FILES); loadFlipped(roadAnimations, roadImages, ROAD_FILES);
loadFlipped(riverAnimations, riverImages, RIVER_FILES); loadFlipped(riverAnimations, riverImages, RIVER_FILES);
ttiles.resize(sizes.x * sizes.y * sizes.z);
} }
void MapHandler::drawTerrainTile(QPainter & painter, int x, int y, int z) void MapHandler::drawTerrainTile(QPainter & painter, int x, int y, int z)
{ {
auto & tinfo = map->getTile(int3(x, y, z)); auto & tinfo = map->getTile(int3(x, y, z));
//Rect destRect(realTileRect);
ui8 rotation = tinfo.extTileFlags % 4; ui8 rotation = tinfo.extTileFlags % 4;
if(terrainImages.at(tinfo.terType).size() <= tinfo.terView) if(terrainImages.at(tinfo.terType).size() <= tinfo.terView)
return; return;
bool hflip = (rotation == 1 || rotation == 3), vflip = (rotation == 2 || rotation == 3); bool hflip = (rotation == 1 || rotation == 3), vflip = (rotation == 2 || rotation == 3);
painter.drawImage(x * tileSize, y * tileSize, terrainImages.at(tinfo.terType)[tinfo.terView]->mirrored(hflip, vflip)); painter.drawImage(x * tileSize, y * tileSize, terrainImages.at(tinfo.terType)[tinfo.terView]->mirrored(hflip, vflip));
} }
@ -102,24 +108,11 @@ void MapHandler::drawRoad(QPainter & painter, int x, int y, int z)
auto & tinfo = map->getTile(int3(x, y, z)); auto & tinfo = map->getTile(int3(x, y, z));
auto * tinfoUpper = map->isInTheMap(int3(x, y - 1, z)) ? &map->getTile(int3(x, y - 1, z)) : nullptr; auto * tinfoUpper = map->isInTheMap(int3(x, y - 1, z)) ? &map->getTile(int3(x, y - 1, z)) : nullptr;
/*if(tinfoUpper && tinfoUpper->roadType != ROAD_NAMES[0])
{
ui8 rotation = (tinfoUpper->extTileFlags >> 4) % 4;
bool hflip = (rotation == 1 || rotation == 3), vflip = (rotation == 2 || rotation == 3);
if(roadImages.at(tinfoUpper->roadType).size() > tinfoUpper->roadDir)
{
painter.drawImage(x * tileSize, y * tileSize, roadImages.at(tinfoUpper->roadType)[tinfoUpper->roadDir]->mirrored(hflip, vflip));
}
}*/
if(tinfo.roadType != ROAD_NAMES[0]) //print road from this tile if(tinfo.roadType != ROAD_NAMES[0]) //print road from this tile
{ {
ui8 rotation = (tinfo.extTileFlags >> 4) % 4; ui8 rotation = (tinfo.extTileFlags >> 4) % 4;
bool hflip = (rotation == 1 || rotation == 3), vflip = (rotation == 2 || rotation == 3); bool hflip = (rotation == 1 || rotation == 3), vflip = (rotation == 2 || rotation == 3);
if(roadImages.at(tinfo.roadType).size() > tinfo.roadDir) if(roadImages.at(tinfo.roadType).size() > tinfo.roadDir)
{ {
painter.drawImage(x * tileSize, y * tileSize, roadImages.at(tinfo.roadType)[tinfo.roadDir]->mirrored(hflip, vflip)); painter.drawImage(x * tileSize, y * tileSize, roadImages.at(tinfo.roadType)[tinfo.roadDir]->mirrored(hflip, vflip));
@ -138,7 +131,6 @@ void MapHandler::drawRiver(QPainter & painter, int x, int y, int z)
return; return;
ui8 rotation = (tinfo.extTileFlags >> 2) % 4; ui8 rotation = (tinfo.extTileFlags >> 2) % 4;
bool hflip = (rotation == 1 || rotation == 3), vflip = (rotation == 2 || rotation == 3); bool hflip = (rotation == 1 || rotation == 3), vflip = (rotation == 2 || rotation == 3);
painter.drawImage(x * tileSize, y * tileSize, riverImages.at(tinfo.riverType)[tinfo.riverDir]->mirrored(hflip, vflip)); painter.drawImage(x * tileSize, y * tileSize, riverImages.at(tinfo.riverType)[tinfo.riverDir]->mirrored(hflip, vflip));
@ -162,6 +154,8 @@ void setPlayerColor(QImage * sur, PlayerColor player)
void MapHandler::initObjectRects() void MapHandler::initObjectRects()
{ {
ttiles.resize(sizes.x * sizes.y * sizes.z);
//initializing objects / rects //initializing objects / rects
for(const CGObjectInstance * elem : map->objects) for(const CGObjectInstance * elem : map->objects)
{ {
@ -184,16 +178,17 @@ void MapHandler::initObjectRects()
continue; continue;
auto image = animation->getImage(0,0); auto image = animation->getImage(0,0);
bool real = true;
for(int fx=0; fx < obj->getWidth(); ++fx) for(int fx=0; fx < obj->getWidth(); ++fx)
{ {
for(int fy=0; fy < obj->getHeight(); ++fy) for(int fy=0; fy < obj->getHeight(); ++fy)
{ {
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z); int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
QRect cr(image->width() - fx * 32 - 32, image->height() - fy * 32 - 32, image->width(), image->height()); QRect cr(image->width() - fx * tileSize - tileSize,
TerrainTileObject toAdd(obj, cr, real/*obj->visitableAt(currTile.x, currTile.y)*/); image->height() - fy * tileSize - tileSize,
real = false; image->width(),
image->height());
TileObject toAdd(obj, cr);
if( map->isInTheMap(currTile) && // within map if( map->isInTheMap(currTile) && // within map
cr.x() + cr.width() > 0 && // image has data on this tile cr.x() + cr.width() > 0 && // image has data on this tile
@ -201,7 +196,7 @@ void MapHandler::initObjectRects()
obj->coveringAt(currTile.x, currTile.y) // object is visible here obj->coveringAt(currTile.x, currTile.y) // object is visible here
) )
{ {
ttiles[currTile.z * (sizes.x * sizes.y) + currTile.y * sizes.x + currTile.x].objects.push_back(toAdd); ttiles[index(currTile)].push_back(toAdd);
} }
} }
} }
@ -209,7 +204,7 @@ void MapHandler::initObjectRects()
for(auto & tt : ttiles) for(auto & tt : ttiles)
{ {
stable_sort(tt.objects.begin(), tt.objects.end(), objectBlitOrderSorter); stable_sort(tt.begin(), tt.end(), objectBlitOrderSorter);
} }
} }
@ -239,125 +234,24 @@ bool MapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObje
return false; return false;
} }
TerrainTileObject::TerrainTileObject(CGObjectInstance * obj_, QRect rect_, bool real_) TileObject::TileObject(CGObjectInstance * obj_, QRect rect_)
: obj(obj_), : obj(obj_),
rect(rect_), rect(rect_)
real(real_)
{ {
} }
TerrainTileObject::~TerrainTileObject() TileObject::~TileObject()
{ {
} }
ui8 MapHandler::getHeroFrameGroup(ui8 dir, bool isMoving) const
{
if(isMoving)
{
static const ui8 frame [] = {0xff, 10, 5, 6, 7, 8, 9, 12, 11};
return frame[dir];
}
else //if(isMoving)
{
static const ui8 frame [] = {0xff, 13, 0, 1, 2, 3, 4, 15, 14};
return frame[dir];
}
}
ui8 MapHandler::getPhaseShift(const CGObjectInstance *object) const
{
auto i = animationPhase.find(object);
if(i == animationPhase.end())
{
ui8 ret = CRandomGenerator::getDefault().nextInt(254);
animationPhase[object] = ret;
return ret;
}
return i->second;
}
MapHandler::AnimBitmapHolder MapHandler::findHeroBitmap(const CGHeroInstance * hero, int anim) const
{
if(hero && hero->moveDir && hero->type) //it's hero or boat
{
if(hero->tempOwner >= PlayerColor::PLAYER_LIMIT) //Neutral hero?
{
logGlobal->error("A neutral hero (%s) at %s. Should not happen!", hero->name, hero->pos.toString());
return MapHandler::AnimBitmapHolder();
}
//pick graphics of hero (or boat if hero is sailing)
std::shared_ptr<Animation> animation;
if (hero->boat)
animation = graphics->boatAnimations[hero->boat->subID];
else
animation = graphics->heroAnimations[hero->appearance.animationFile];
bool moving = !hero->isStanding;
int group = getHeroFrameGroup(hero->moveDir, moving);
if(animation->size(group) > 0)
{
int frame = anim % animation->size(group);
auto heroImage = animation->getImage(frame, group);
//get flag overlay only if we have main image
auto flagImage = findFlagBitmap(hero, anim, &hero->tempOwner, group);
return MapHandler::AnimBitmapHolder(heroImage, flagImage);
}
}
return MapHandler::AnimBitmapHolder();
}
MapHandler::AnimBitmapHolder MapHandler::findBoatBitmap(const CGBoat * boat, int anim) const
{
auto animation = graphics->boatAnimations.at(boat->subID);
int group = getHeroFrameGroup(boat->direction, false);
if(animation->size(group) > 0)
return MapHandler::AnimBitmapHolder(animation->getImage(anim % animation->size(group), group));
else
return MapHandler::AnimBitmapHolder();
}
std::shared_ptr<QImage> MapHandler::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const std::shared_ptr<QImage> MapHandler::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
{ {
if(!hero) if(!hero || hero->boat)
return std::shared_ptr<QImage>(); return std::shared_ptr<QImage>();
if(hero->boat)
return findBoatFlagBitmap(hero->boat, anim, color, group, hero->moveDir);
return findHeroFlagBitmap(hero, anim, color, group);
}
std::shared_ptr<QImage> MapHandler::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
{
return findFlagBitmapInternal(graphics->heroFlagAnimations.at(color->getNum()), anim, group, hero->moveDir, !hero->isStanding); return findFlagBitmapInternal(graphics->heroFlagAnimations.at(color->getNum()), anim, group, hero->moveDir, !hero->isStanding);
} }
std::shared_ptr<QImage> MapHandler::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int group, ui8 dir) const
{
int boatType = boat->subID;
if(boatType < 0 || boatType >= graphics->boatFlagAnimations.size())
{
logGlobal->error("Not supported boat subtype: %d", boat->subID);
return nullptr;
}
const auto & subtypeFlags = graphics->boatFlagAnimations.at(boatType);
int colorIndex = color->getNum();
if(colorIndex < 0 || colorIndex >= subtypeFlags.size())
{
logGlobal->error("Invalid player color %d", colorIndex);
return nullptr;
}
return findFlagBitmapInternal(subtypeFlags.at(colorIndex), anim, group, dir, false);
}
std::shared_ptr<QImage> MapHandler::findFlagBitmapInternal(std::shared_ptr<Animation> animation, int anim, int group, ui8 dir, bool moving) const std::shared_ptr<QImage> MapHandler::findFlagBitmapInternal(std::shared_ptr<Animation> animation, int anim, int group, ui8 dir, bool moving) const
{ {
size_t groupSize = animation->size(group); size_t groupSize = animation->size(group);
@ -370,16 +264,11 @@ std::shared_ptr<QImage> MapHandler::findFlagBitmapInternal(std::shared_ptr<Anima
return animation->getImage((anim / 4) % groupSize, group); return animation->getImage((anim / 4) % groupSize, group);
} }
MapHandler::AnimBitmapHolder MapHandler::findObjectBitmap(const CGObjectInstance * obj, int anim) const MapHandler::AnimBitmapHolder MapHandler::findObjectBitmap(const CGObjectInstance * obj, int anim) const
{ {
if (!obj) if(!obj || obj->ID == Obj::HERO || obj->ID == Obj::BOAT)
return MapHandler::AnimBitmapHolder(); return MapHandler::AnimBitmapHolder();
if (obj->ID == Obj::HERO)
return findHeroBitmap(static_cast<const CGHeroInstance*>(obj), anim);
if (obj->ID == Obj::BOAT)
return findBoatBitmap(static_cast<const CGBoat*>(obj), anim);
// normal object // normal object
std::shared_ptr<Animation> animation = graphics->getAnimation(obj); std::shared_ptr<Animation> animation = graphics->getAnimation(obj);
size_t groupSize = animation->size(); size_t groupSize = animation->size();
@ -387,7 +276,7 @@ MapHandler::AnimBitmapHolder MapHandler::findObjectBitmap(const CGObjectInstance
return MapHandler::AnimBitmapHolder(); return MapHandler::AnimBitmapHolder();
animation->playerColored(obj->tempOwner); animation->playerColored(obj->tempOwner);
auto bitmap = animation->getImage((anim + getPhaseShift(obj)) % groupSize); auto bitmap = animation->getImage(anim % groupSize);
if(!bitmap) if(!bitmap)
return MapHandler::AnimBitmapHolder(); return MapHandler::AnimBitmapHolder();
@ -396,9 +285,9 @@ MapHandler::AnimBitmapHolder MapHandler::findObjectBitmap(const CGObjectInstance
return MapHandler::AnimBitmapHolder(bitmap); return MapHandler::AnimBitmapHolder(bitmap);
} }
std::vector<TerrainTileObject> & MapHandler::getObjects(int x, int y, int z) std::vector<TileObject> & MapHandler::getObjects(int x, int y, int z)
{ {
return ttiles[z * (sizes.x * sizes.y) + y * sizes.x + x].objects; return ttiles[index(x, y, z)];
} }
void MapHandler::drawObjects(QPainter & painter, int x, int y, int z) void MapHandler::drawObjects(QPainter & painter, int x, int y, int z)
@ -418,33 +307,19 @@ void MapHandler::drawObjects(QPainter & painter, int x, int y, int z)
if (objData.objBitmap) if (objData.objBitmap)
{ {
auto pos = obj->getPosition(); auto pos = obj->getPosition();
QRect srcRect(object.rect.x() + pos.x * 32, object.rect.y() + pos.y * 32, tileSize, tileSize);
painter.drawImage(QPoint(x * 32, y * 32), *objData.objBitmap, object.rect); painter.drawImage(QPoint(x * tileSize, y * tileSize), *objData.objBitmap, object.rect);
//painter.drawImage(pos.x * 32 - object.rect.x(), pos.y * 32 - object.rect.y(), *objData.objBitmap);
//drawObject(targetSurf, objData.objBitmap, &srcRect, objData.isMoving);
if(objData.flagBitmap) if(objData.flagBitmap)
{ {
/*if (objData.isMoving)
{
srcRect.y += FRAMES_PER_MOVE_ANIM_GROUP * 2 - tileSize;
Rect dstRect(realPos.x, realPos.y - tileSize / 2, tileSize, tileSize);
drawHeroFlag(targetSurf, objData.flagBitmap, &srcRect, &dstRect, true);
}*/
if (obj->pos.x == pos.x && obj->pos.y == pos.y) if (obj->pos.x == pos.x && obj->pos.y == pos.y)
{ painter.drawImage(QPoint(x * tileSize, y * tileSize), *objData.flagBitmap, object.rect);
//Rect dstRect(realPos.x - 2 * tileSize, realPos.y - tileSize, 3 * tileSize, 2 * tileSize);
painter.drawImage(QPoint(x * 32, y * 32), *objData.flagBitmap, object.rect);
//drawHeroFlag(targetSurf, objData.flagBitmap, nullptr, &dstRect, false);
}
} }
} }
} }
} }
void MapHandler::drawObject(QPainter & painter, const TerrainTileObject & object) void MapHandler::drawObject(QPainter & painter, const TileObject & object)
{ {
//if(object.visi)
const CGObjectInstance * obj = object.obj; const CGObjectInstance * obj = object.obj;
if (!obj) if (!obj)
{ {
@ -458,24 +333,13 @@ void MapHandler::drawObject(QPainter & painter, const TerrainTileObject & object
if (objData.objBitmap) if (objData.objBitmap)
{ {
auto pos = obj->getPosition(); auto pos = obj->getPosition();
QRect srcRect(object.rect.x() + pos.x * 32, object.rect.y() + pos.y * 32, tileSize, tileSize);
painter.drawImage(pos.x * 32 - object.rect.x(), pos.y * 32 - object.rect.y(), *objData.objBitmap); painter.drawImage(pos.x * tileSize - object.rect.x(), pos.y * tileSize - object.rect.y(), *objData.objBitmap);
//drawObject(targetSurf, objData.objBitmap, &srcRect, objData.isMoving);
if (objData.flagBitmap) if (objData.flagBitmap)
{ {
/*if (objData.isMoving)
{
srcRect.y += FRAMES_PER_MOVE_ANIM_GROUP * 2 - tileSize;
Rect dstRect(realPos.x, realPos.y - tileSize / 2, tileSize, tileSize);
drawHeroFlag(targetSurf, objData.flagBitmap, &srcRect, &dstRect, true);
}
else */
if (obj->pos.x == pos.x && obj->pos.y == pos.y) if (obj->pos.x == pos.x && obj->pos.y == pos.y)
{ {
//Rect dstRect(realPos.x - 2 * tileSize, realPos.y - tileSize, 3 * tileSize, 2 * tileSize); painter.drawImage(pos.x * tileSize - object.rect.x(), pos.y * tileSize - object.rect.y(), *objData.flagBitmap);
//drawHeroFlag(targetSurf, objData.flagBitmap, nullptr, &dstRect, false);
painter.drawImage(pos.x * 32 - object.rect.x(), pos.y * 32 - object.rect.y(), *objData.flagBitmap);
} }
} }
} }
@ -538,3 +402,102 @@ void MapHandler::drawMinimapTile(QPainter & painter, int x, int y, int z)
painter.setPen(getTileColor(x, y, z)); painter.setPen(getTileColor(x, y, z));
painter.drawPoint(x, y); painter.drawPoint(x, y);
} }
void MapHandler::invalidate(int x, int y, int z)
{
auto & objects = getObjects(x, y, z);
for(auto obj = objects.begin(); obj != objects.end();)
{
//object was removed
if(std::find(map->objects.begin(), map->objects.end(), obj->obj) == map->objects.end())
{
obj = objects.erase(obj);
continue;
}
//object was moved
auto & pos = obj->obj->pos;
if(pos.z != z || pos.x < x || pos.y < y || pos.x - obj->obj->getWidth() >= x || pos.y - obj->obj->getHeight() >= y)
{
obj = objects.erase(obj);
continue;
}
++obj;
//invalidate(obj->obj);
}
stable_sort(objects.begin(), objects.end(), objectBlitOrderSorter);
}
void MapHandler::invalidate(CGObjectInstance * obj)
{
std::shared_ptr<Animation> animation = graphics->getAnimation(obj);
//no animation at all or empty animation
if(!animation || animation->size(0) == 0)
return;
auto image = animation->getImage(0,0);
for(int fx=0; fx < obj->getWidth(); ++fx)
{
for(int fy=0; fy < obj->getHeight(); ++fy)
{
//object presented on the tile
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
QRect cr(image->width() - fx * tileSize - tileSize, image->height() - fy * tileSize - tileSize, image->width(), image->height());
if( map->isInTheMap(currTile) && // within map
cr.x() + cr.width() > 0 && // image has data on this tile
cr.y() + cr.height() > 0 &&
obj->coveringAt(currTile.x, currTile.y) // object is visible here
)
{
auto & objects = ttiles[index(currTile)];
bool found = false;
for(auto & o : objects)
{
if(o.obj == obj)
{
o.rect = cr;
found = true;
break;
}
}
if(!found)
objects.emplace_back(obj, cr);
stable_sort(objects.begin(), objects.end(), objectBlitOrderSorter);
}
}
}
}
std::vector<int3> MapHandler::geTilesUnderObject(CGObjectInstance * obj) const
{
std::vector<int3> result;
for(int fx=0; fx < obj->getWidth(); ++fx)
{
for(int fy=0; fy < obj->getHeight(); ++fy)
{
//object presented on the tile
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
if(map->isInTheMap(currTile) && // within map
obj->coveringAt(currTile.x, currTile.y) // object is visible here
)
{
result.push_back(currTile);
}
}
}
return result;
}
void MapHandler::invalidate(const std::vector<int3> & tiles)
{
for(auto & currTile : tiles)
{
invalidate(currTile.x, currTile.y, currTile.z);
}
}

View File

@ -13,20 +13,16 @@ class CGObjectInstance;
class CGBoat; class CGBoat;
class PlayerColor; class PlayerColor;
struct TerrainTileObject struct TileObject
{ {
CGObjectInstance *obj; CGObjectInstance *obj;
QRect rect; QRect rect;
bool real;
TerrainTileObject(CGObjectInstance *obj_, QRect rect_, bool visitablePos = false); TileObject(CGObjectInstance *obj_, QRect rect_);
~TerrainTileObject(); ~TileObject();
}; };
struct TerrainTile2 using TileObjects = std::vector<TileObject>; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
{
std::vector<TerrainTileObject> objects; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
};
class MapHandler class MapHandler
{ {
@ -44,21 +40,30 @@ public:
private: private:
ui8 getHeroFrameGroup(ui8 dir, bool isMoving) const; int index(int x, int y, int z) const;
ui8 getPhaseShift(const CGObjectInstance *object) const; int index(const int3 &) const;
// internal helper methods to choose correct bitmap(s) for object; called internally by findObjectBitmap
AnimBitmapHolder findHeroBitmap(const CGHeroInstance * hero, int anim) const;
AnimBitmapHolder findBoatBitmap(const CGBoat * hero, int anim) const;
std::shared_ptr<QImage> findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
std::shared_ptr<QImage> findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
std::shared_ptr<QImage> findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int group, ui8 dir) const;
std::shared_ptr<QImage> findFlagBitmapInternal(std::shared_ptr<Animation> animation, int anim, int group, ui8 dir, bool moving) const; std::shared_ptr<QImage> findFlagBitmapInternal(std::shared_ptr<Animation> animation, int anim, int group, ui8 dir, bool moving) const;
std::shared_ptr<QImage> findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
public:
AnimBitmapHolder findObjectBitmap(const CGObjectInstance * obj, int anim) const; AnimBitmapHolder findObjectBitmap(const CGObjectInstance * obj, int anim) const;
//FIXME: unique_ptr should be enough, but fails to compile in MSVS 2013
typedef std::map<std::string, std::shared_ptr<Animation>> TFlippedAnimations; //[type, rotation]
typedef std::map<std::string, std::vector<std::shared_ptr<QImage>>> TFlippedCache;//[type, view type, rotation]
TFlippedAnimations terrainAnimations;//[terrain type, rotation]
TFlippedCache terrainImages;//[terrain type, view type, rotation]
TFlippedAnimations roadAnimations;//[road type, rotation]
TFlippedCache roadImages;//[road type, view type, rotation]
TFlippedAnimations riverAnimations;//[river type, rotation]
TFlippedCache riverImages;//[river type, view type, rotation]
std::vector<TileObjects> ttiles; //informations about map tiles
int3 sizes; //map size (x = width, y = height, z = number of levels)
const CMap * map;
enum class EMapCacheType : char enum class EMapCacheType : char
{ {
TERRAIN, OBJECTS, ROADS, RIVERS, FOW, HEROES, HERO_FLAGS, FRAME, AFTER_LAST TERRAIN, OBJECTS, ROADS, RIVERS, FOW, HEROES, HERO_FLAGS, FRAME, AFTER_LAST
@ -66,59 +71,34 @@ public:
void initObjectRects(); void initObjectRects();
void initTerrainGraphics(); void initTerrainGraphics();
QRgb getTileColor(int x, int y, int z);
public:
MapHandler();
~MapHandler() = default;
void reset(const CMap * Map);
std::vector<TerrainTile2> ttiles; //informations about map tiles void updateWater();
int3 sizes; //map size (x = width, y = height, z = number of levels)
const CMap * map;
//terrain graphics
//FIXME: unique_ptr should be enough, but fails to compile in MSVS 2013
typedef std::map<std::string, std::shared_ptr<Animation>> TFlippedAnimations; //[type, rotation]
typedef std::map<std::string, std::vector<std::shared_ptr<QImage>>> TFlippedCache;//[type, view type, rotation]
TFlippedAnimations terrainAnimations;//[terrain type, rotation]
TFlippedCache terrainImages;//[terrain type, view type, rotation]
TFlippedAnimations roadAnimations;//[road type, rotation]
TFlippedCache roadImages;//[road type, view type, rotation]
TFlippedAnimations riverAnimations;//[river type, rotation]
TFlippedCache riverImages;//[river type, view type, rotation]
void drawTerrainTile(QPainter & painter, int x, int y, int z); void drawTerrainTile(QPainter & painter, int x, int y, int z);
/// draws a river segment on current tile /// draws a river segment on current tile
void drawRiver(QPainter & painter, int x, int y, int z); void drawRiver(QPainter & painter, int x, int y, int z);
/// draws a road segment on current tile /// draws a road segment on current tile
void drawRoad(QPainter & painter, int x, int y, int z); void drawRoad(QPainter & painter, int x, int y, int z);
void invalidate(int x, int y, int z); //invalidates all objects in particular tile
void invalidate(CGObjectInstance *); //invalidates object rects
void invalidate(const std::vector<int3> &); //invalidates all tiles
std::vector<int3> geTilesUnderObject(CGObjectInstance *) const;
/// draws all objects on current tile (higher-level logic, unlike other draw*** methods) /// draws all objects on current tile (higher-level logic, unlike other draw*** methods)
void drawObjects(QPainter & painter, int x, int y, int z); void drawObjects(QPainter & painter, int x, int y, int z);
void drawObject(QPainter & painter, const TerrainTileObject & object); void drawObject(QPainter & painter, const TileObject & object);
void drawObjectAt(QPainter & painter, const CGObjectInstance * object, int x, int y); void drawObjectAt(QPainter & painter, const CGObjectInstance * object, int x, int y);
std::vector<TerrainTileObject> & getObjects(int x, int y, int z); std::vector<TileObject> & getObjects(int x, int y, int z);
//void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, bool moving) const;
//void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const;
QRgb getTileColor(int x, int y, int z);
void drawMinimapTile(QPainter & painter, int x, int y, int z); void drawMinimapTile(QPainter & painter, int x, int y, int z);
mutable std::map<const CGObjectInstance*, ui8> animationPhase;
MapHandler(const CMap * Map);
~MapHandler() = default;
void init();
//void getTerrainDescr(const int3 & pos, std::string & out, bool isRMB) const; // isRMB = whether Right Mouse Button is clicked
//bool printObject(const CGObjectInstance * obj, bool fadein = false); //puts appropriate things to tiles, so obj will be visible on map
//bool hideObject(const CGObjectInstance * obj, bool fadeout = false); //removes appropriate things from ttiles, so obj will be no longer visible on map (but still will exist)
//bool hasObjectHole(const int3 & pos) const; // Checks if TerrainTile2 tile has a pit remained after digging.
//EMapAnimRedrawStatus drawTerrainRectNew(SDL_Surface * targetSurface, const MapDrawingInfo * info, bool redrawOnlyAnim = false);
void updateWater();
/// determines if the map is ready to handle new hero movement (not available during fading animations)
//bool canStartHeroMovement();
//void discardWorldViewCache();
static bool compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b); static bool compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b);
}; };

View File

@ -329,7 +329,6 @@ void ObjectsLayer::setDirty(int x, int y)
void ObjectsLayer::setDirty(const CGObjectInstance * object) void ObjectsLayer::setDirty(const CGObjectInstance * object)
{ {
dirty.insert(object);
} }
SelectionObjectsLayer::SelectionObjectsLayer(MapSceneBase * s): AbstractLayer(s), newObject(nullptr) SelectionObjectsLayer::SelectionObjectsLayer(MapSceneBase * s): AbstractLayer(s), newObject(nullptr)

View File

@ -109,7 +109,8 @@ public:
void setDirty(const CGObjectInstance * object); void setDirty(const CGObjectInstance * object);
private: private:
std::set<const CGObjectInstance *> dirty; std::set<const CGObjectInstance *> objDirty;
std::set<int3> dirty;
}; };

View File

@ -88,6 +88,13 @@ void WindowNewMap::on_okButtong_clicked()
std::unique_ptr<CMap> nmap; std::unique_ptr<CMap> nmap;
if(ui->randomMapCheck->isChecked()) if(ui->randomMapCheck->isChecked())
{ {
//verify map template
if(mapGenOptions.getPossibleTemplates().empty())
{
QMessageBox::warning(this, "No template", "No template for parameters scecified. Random map cannot be generated.");
return;
}
CMapGenerator generator(mapGenOptions); CMapGenerator generator(mapGenOptions);
//TODO: fix water and roads //TODO: fix water and roads
generator.disableModificator("RoadPlacer"); generator.disableModificator("RoadPlacer");
@ -96,9 +103,16 @@ void WindowNewMap::on_okButtong_clicked()
auto progressBarWnd = new GeneratorProgress(generator, this); auto progressBarWnd = new GeneratorProgress(generator, this);
progressBarWnd->show(); progressBarWnd->show();
auto f = std::async(std::launch::async, &CMapGenerator::generate, &generator); try
progressBarWnd->update(); {
nmap = f.get(); auto f = std::async(std::launch::async, &CMapGenerator::generate, &generator);
progressBarWnd->update();
nmap = f.get();
}
catch(const std::exception & e)
{
QMessageBox::critical(this, "RMG failure", e.what());
}
} }
else else
{ {