mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-22 22:13:35 +02:00
Implement smart invalidation for objects
This commit is contained in:
parent
7ad2282b64
commit
e7de865f26
@ -4,13 +4,10 @@
|
||||
//
|
||||
// Created by nordsoft on 29.08.2022.
|
||||
//
|
||||
|
||||
#include "BitmapHandler.h"
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "BitmapHandler.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "BitmapHandler.h"
|
||||
|
||||
#include <QBitmap>
|
||||
#include <QImage>
|
||||
@ -21,152 +18,152 @@ namespace BitmapHandler
|
||||
QImage loadH3PCX(ui8 * data, size_t size);
|
||||
|
||||
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
|
||||
{
|
||||
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)
|
||||
bool isPCX(const ui8 *header)//check whether file can be PCX according to header
|
||||
{
|
||||
it = 0xC;
|
||||
//auto bitmap = QBitmap::fromData(qsize, pcx + it);
|
||||
QImage image(pcx + it, width, height, QImage::Format_Indexed8);
|
||||
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 loadH3PCX(ui8 * pcx, size_t size)
|
||||
{
|
||||
//SDL_Surface * ret;
|
||||
|
||||
//palette - last 256*3 bytes
|
||||
QVector<QRgb> colorTable;
|
||||
it = (int)size-256*3;
|
||||
for (int i=0;i<256;i++)
|
||||
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)
|
||||
{
|
||||
char bytes[3];
|
||||
bytes[0] = pcx[it++];
|
||||
bytes[1] = pcx[it++];
|
||||
bytes[2] = pcx[it++];
|
||||
colorTable.append(qRgb(bytes[0], bytes[1], bytes[2]));
|
||||
}
|
||||
image.setColorTable(colorTable);
|
||||
return image;
|
||||
}
|
||||
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)
|
||||
it = 0xC;
|
||||
//auto bitmap = QBitmap::fromData(qsize, pcx + it);
|
||||
QImage image(pcx + it, width, height, QImage::Format_Indexed8);
|
||||
|
||||
//palette - last 256*3 bytes
|
||||
QVector<QRgb> colorTable;
|
||||
it = (int)size-256*3;
|
||||
for (int i=0;i<256;i++)
|
||||
{
|
||||
QVector<QRgb> colorTable = image.colorTable();
|
||||
colorTable[0] = qRgba(255, 255, 255, 0);
|
||||
image.setColorTable(colorTable);
|
||||
char bytes[3];
|
||||
bytes[0] = pcx[it++];
|
||||
bytes[1] = pcx[it++];
|
||||
bytes[2] = pcx[it++];
|
||||
colorTable.append(qRgb(bytes[0], bytes[1], bytes[2]));
|
||||
}
|
||||
image.setColorTable(colorTable);
|
||||
return image;
|
||||
}
|
||||
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);
|
||||
QImage image(pcx + it, width, height, QImage::Format_RGB32);
|
||||
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 image = loadBitmapFromDir("DATA/", fname, setKey);
|
||||
if(image.isNull())
|
||||
QImage loadBitmapFromDir(std::string path, std::string fname, bool setKey)
|
||||
{
|
||||
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())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
#define read_le_u16(p) (* reinterpret_cast<const ui16 *>(p))
|
||||
#define read_le_u32(p) (* reinterpret_cast<const ui32 *>(p))
|
||||
|
||||
#include <QImage>
|
||||
|
||||
namespace BitmapHandler
|
||||
{
|
||||
//Load file from /DATA or /SPRITES
|
||||
|
@ -4,9 +4,10 @@
|
||||
#include "../lib/spells/CSpellHandler.h"
|
||||
#include "../lib/CRandomGenerator.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
|
||||
//===============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
|
||||
INIT_OBJ_TYPE(CGResource);
|
||||
@ -16,14 +17,14 @@ Initializer::Initializer(CGObjectInstance * o)
|
||||
INIT_OBJ_TYPE(CGTownInstance);
|
||||
}
|
||||
|
||||
void initialize(CArmedInstance * o)
|
||||
void Initializer::initialize(CArmedInstance * o)
|
||||
{
|
||||
if(!o) return;
|
||||
|
||||
o->tempOwner = PlayerColor::NEUTRAL;
|
||||
}
|
||||
|
||||
void initialize(CGTownInstance * o)
|
||||
void Initializer::initialize(CGTownInstance * o)
|
||||
{
|
||||
if(!o) return;
|
||||
|
||||
@ -37,7 +38,7 @@ void initialize(CGTownInstance * o)
|
||||
}
|
||||
}
|
||||
|
||||
void initialize(CGArtifact * o)
|
||||
void Initializer::initialize(CGArtifact * o)
|
||||
{
|
||||
if(!o) return;
|
||||
|
||||
@ -46,7 +47,7 @@ void initialize(CGArtifact * o)
|
||||
std::vector<SpellID> out;
|
||||
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);
|
||||
}
|
||||
@ -56,7 +57,7 @@ void initialize(CGArtifact * o)
|
||||
}
|
||||
}
|
||||
|
||||
void initialize(CGMine * o)
|
||||
void Initializer::initialize(CGMine * o)
|
||||
{
|
||||
if(!o) return;
|
||||
|
||||
@ -64,7 +65,7 @@ void initialize(CGMine * o)
|
||||
o->producedQuantity = o->defaultResProduction();
|
||||
}
|
||||
|
||||
void initialize(CGResource * o)
|
||||
void Initializer::initialize(CGResource * o)
|
||||
{
|
||||
if(!o) return;
|
||||
|
||||
|
@ -18,12 +18,23 @@ void setProperty(x*, const QString &, const QVariant &);
|
||||
#define UPDATE_OBJ_PROPERTIES(x) updateProperties(dynamic_cast<x*>(obj))
|
||||
#define SET_PROPERTIES(x) setProperty(dynamic_cast<x*>(obj), key, value)
|
||||
|
||||
//===============DECLARE MAP OBJECTS======================================
|
||||
DECLARE_OBJ_TYPE(CArmedInstance);
|
||||
DECLARE_OBJ_TYPE(CGTownInstance);
|
||||
DECLARE_OBJ_TYPE(CGArtifact);
|
||||
DECLARE_OBJ_TYPE(CGMine);
|
||||
DECLARE_OBJ_TYPE(CGResource);
|
||||
|
||||
class Initializer
|
||||
{
|
||||
public:
|
||||
//===============DECLARE MAP OBJECTS======================================
|
||||
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
|
||||
{
|
||||
@ -90,11 +101,7 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class Initializer
|
||||
{
|
||||
public:
|
||||
Initializer(CGObjectInstance *);
|
||||
};
|
||||
|
||||
|
||||
class PlayerColorDelegate : public QStyledItemDelegate
|
||||
{
|
||||
|
@ -88,7 +88,9 @@ void MapController::sceneForceUpdate(int level)
|
||||
|
||||
void MapController::resetMapHandler()
|
||||
{
|
||||
_mapHandler.reset(new MapHandler(_map.get()));
|
||||
if(!_mapHandler)
|
||||
_mapHandler.reset(new MapHandler());
|
||||
_mapHandler->reset(map());
|
||||
_scenes[0]->initialize(*this);
|
||||
_scenes[1]->initialize(*this);
|
||||
_miniscenes[0]->initialize(*this);
|
||||
@ -121,11 +123,13 @@ void MapController::commitObjectErase(int level)
|
||||
for(auto * obj : _scenes[level]->selectionObjectsView.getSelection())
|
||||
{
|
||||
_map->getEditManager()->removeObject(obj);
|
||||
//invalidate tiles under object
|
||||
_mapHandler->invalidate(_mapHandler->geTilesUnderObject(obj));
|
||||
delete obj;
|
||||
}
|
||||
_scenes[level]->selectionObjectsView.clear();
|
||||
resetMapHandler();
|
||||
_scenes[level]->updateViews();
|
||||
_scenes[level]->objectsView.draw();
|
||||
_scenes[level]->selectionObjectsView.draw();
|
||||
|
||||
_miniscenes[level]->updateViews();
|
||||
main->mapChanged();
|
||||
@ -176,8 +180,14 @@ void MapController::commitObstacleFill(int level)
|
||||
sel.second.placeObstacles(_map.get(), CRandomGenerator::getDefault());
|
||||
}
|
||||
|
||||
resetMapHandler();
|
||||
_scenes[level]->updateViews();
|
||||
for(auto & t : selection)
|
||||
{
|
||||
_mapHandler->invalidate(t.x, t.y, t.z);
|
||||
}
|
||||
|
||||
_scenes[level]->selectionTerrainView.clear();
|
||||
_scenes[level]->selectionTerrainView.draw();
|
||||
_scenes[level]->objectsView.draw();
|
||||
|
||||
_miniscenes[level]->updateViews();
|
||||
main->mapChanged();
|
||||
@ -185,7 +195,8 @@ void MapController::commitObstacleFill(int level)
|
||||
|
||||
void MapController::commitObjectChange(int level)
|
||||
{
|
||||
resetMapHandler();
|
||||
//for(auto * o : _scenes[level]->selectionObjectsView.getSelection())
|
||||
//_mapHandler->invalidate(o);
|
||||
_scenes[level]->objectsView.draw();
|
||||
_scenes[level]->selectionObjectsView.draw();
|
||||
|
||||
@ -219,16 +230,18 @@ void MapController::commitObjectShiftOrCreate(int level)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto prevPositions = _mapHandler->geTilesUnderObject(obj);
|
||||
_map->getEditManager()->moveObject(obj, pos);
|
||||
_mapHandler->invalidate(prevPositions);
|
||||
_mapHandler->invalidate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
_scenes[level]->selectionObjectsView.newObject = nullptr;
|
||||
_scenes[level]->selectionObjectsView.shift = QPoint(0, 0);
|
||||
_scenes[level]->selectionObjectsView.selectionMode = 0;
|
||||
|
||||
resetMapHandler();
|
||||
_scenes[level]->updateViews();
|
||||
_scenes[level]->objectsView.draw();
|
||||
_scenes[level]->selectionObjectsView.draw();
|
||||
|
||||
_miniscenes[level]->updateViews();
|
||||
main->mapChanged();
|
||||
@ -239,9 +252,10 @@ void MapController::commitObjectCreate(int level)
|
||||
auto * newObj = _scenes[level]->selectionObjectsView.newObject;
|
||||
if(!newObj)
|
||||
return;
|
||||
Initializer init(newObj);
|
||||
Initializer init(map(), newObj);
|
||||
|
||||
_map->getEditManager()->insertObject(newObj);
|
||||
_mapHandler->invalidate(newObj);
|
||||
main->mapChanged();
|
||||
}
|
||||
|
||||
|
@ -13,26 +13,37 @@
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
MapHandler::MapHandler(const CMap * Map):
|
||||
map(Map)
|
||||
int MapHandler::index(int x, int y, int z) const
|
||||
{
|
||||
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.x = map->width;
|
||||
sizes.y = map->height;
|
||||
sizes.z = map->twoLevel ? 2 : 1;
|
||||
|
||||
initTerrainGraphics();
|
||||
logGlobal->info("\tPreparing terrain, roads, rivers, borders");
|
||||
initObjectRects();
|
||||
logGlobal->info("\tMaking object rects");
|
||||
}
|
||||
@ -78,22 +89,17 @@ void MapHandler::initTerrainGraphics()
|
||||
loadFlipped(terrainAnimations, terrainImages, terrainFiles);
|
||||
loadFlipped(roadAnimations, roadImages, ROAD_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)
|
||||
{
|
||||
auto & tinfo = map->getTile(int3(x, y, z));
|
||||
//Rect destRect(realTileRect);
|
||||
|
||||
ui8 rotation = tinfo.extTileFlags % 4;
|
||||
|
||||
if(terrainImages.at(tinfo.terType).size() <= tinfo.terView)
|
||||
return;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@ -102,24 +108,11 @@ void MapHandler::drawRoad(QPainter & painter, int x, int y, int 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;
|
||||
|
||||
/*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
|
||||
{
|
||||
ui8 rotation = (tinfo.extTileFlags >> 4) % 4;
|
||||
|
||||
bool hflip = (rotation == 1 || rotation == 3), vflip = (rotation == 2 || rotation == 3);
|
||||
|
||||
if(roadImages.at(tinfo.roadType).size() > tinfo.roadDir)
|
||||
{
|
||||
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;
|
||||
|
||||
ui8 rotation = (tinfo.extTileFlags >> 2) % 4;
|
||||
|
||||
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));
|
||||
@ -162,6 +154,8 @@ void setPlayerColor(QImage * sur, PlayerColor player)
|
||||
|
||||
void MapHandler::initObjectRects()
|
||||
{
|
||||
ttiles.resize(sizes.x * sizes.y * sizes.z);
|
||||
|
||||
//initializing objects / rects
|
||||
for(const CGObjectInstance * elem : map->objects)
|
||||
{
|
||||
@ -184,16 +178,17 @@ void MapHandler::initObjectRects()
|
||||
continue;
|
||||
|
||||
auto image = animation->getImage(0,0);
|
||||
bool real = true;
|
||||
for(int fx=0; fx < obj->getWidth(); ++fx)
|
||||
{
|
||||
for(int fy=0; fy < obj->getHeight(); ++fy)
|
||||
{
|
||||
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());
|
||||
TerrainTileObject toAdd(obj, cr, real/*obj->visitableAt(currTile.x, currTile.y)*/);
|
||||
real = false;
|
||||
QRect cr(image->width() - fx * tileSize - tileSize,
|
||||
image->height() - fy * tileSize - tileSize,
|
||||
image->width(),
|
||||
image->height());
|
||||
|
||||
TileObject toAdd(obj, cr);
|
||||
|
||||
if( map->isInTheMap(currTile) && // within map
|
||||
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
|
||||
)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
TerrainTileObject::TerrainTileObject(CGObjectInstance * obj_, QRect rect_, bool real_)
|
||||
TileObject::TileObject(CGObjectInstance * obj_, QRect rect_)
|
||||
: obj(obj_),
|
||||
rect(rect_),
|
||||
real(real_)
|
||||
rect(rect_)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if(!hero)
|
||||
if(!hero || hero->boat)
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
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
|
||||
std::shared_ptr<Animation> animation = graphics->getAnimation(obj);
|
||||
size_t groupSize = animation->size();
|
||||
@ -387,7 +276,7 @@ MapHandler::AnimBitmapHolder MapHandler::findObjectBitmap(const CGObjectInstance
|
||||
return MapHandler::AnimBitmapHolder();
|
||||
|
||||
animation->playerColored(obj->tempOwner);
|
||||
auto bitmap = animation->getImage((anim + getPhaseShift(obj)) % groupSize);
|
||||
auto bitmap = animation->getImage(anim % groupSize);
|
||||
if(!bitmap)
|
||||
return MapHandler::AnimBitmapHolder();
|
||||
|
||||
@ -396,9 +285,9 @@ MapHandler::AnimBitmapHolder MapHandler::findObjectBitmap(const CGObjectInstance
|
||||
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)
|
||||
@ -418,33 +307,19 @@ void MapHandler::drawObjects(QPainter & painter, int x, int y, int z)
|
||||
if (objData.objBitmap)
|
||||
{
|
||||
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(pos.x * 32 - object.rect.x(), pos.y * 32 - object.rect.y(), *objData.objBitmap);
|
||||
//drawObject(targetSurf, objData.objBitmap, &srcRect, objData.isMoving);
|
||||
painter.drawImage(QPoint(x * tileSize, y * tileSize), *objData.objBitmap, object.rect);
|
||||
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)
|
||||
{
|
||||
//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);
|
||||
}
|
||||
painter.drawImage(QPoint(x * tileSize, y * tileSize), *objData.flagBitmap, object.rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapHandler::drawObject(QPainter & painter, const TerrainTileObject & object)
|
||||
void MapHandler::drawObject(QPainter & painter, const TileObject & object)
|
||||
{
|
||||
//if(object.visi)
|
||||
const CGObjectInstance * obj = object.obj;
|
||||
if (!obj)
|
||||
{
|
||||
@ -458,24 +333,13 @@ void MapHandler::drawObject(QPainter & painter, const TerrainTileObject & object
|
||||
if (objData.objBitmap)
|
||||
{
|
||||
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);
|
||||
//drawObject(targetSurf, objData.objBitmap, &srcRect, objData.isMoving);
|
||||
painter.drawImage(pos.x * tileSize - object.rect.x(), pos.y * tileSize - object.rect.y(), *objData.objBitmap);
|
||||
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)
|
||||
{
|
||||
//Rect dstRect(realPos.x - 2 * tileSize, realPos.y - tileSize, 3 * tileSize, 2 * tileSize);
|
||||
//drawHeroFlag(targetSurf, objData.flagBitmap, nullptr, &dstRect, false);
|
||||
painter.drawImage(pos.x * 32 - object.rect.x(), pos.y * 32 - object.rect.y(), *objData.flagBitmap);
|
||||
painter.drawImage(pos.x * tileSize - object.rect.x(), pos.y * tileSize - 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.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);
|
||||
}
|
||||
}
|
||||
|
@ -13,20 +13,16 @@ class CGObjectInstance;
|
||||
class CGBoat;
|
||||
class PlayerColor;
|
||||
|
||||
struct TerrainTileObject
|
||||
struct TileObject
|
||||
{
|
||||
CGObjectInstance *obj;
|
||||
QRect rect;
|
||||
bool real;
|
||||
|
||||
TerrainTileObject(CGObjectInstance *obj_, QRect rect_, bool visitablePos = false);
|
||||
~TerrainTileObject();
|
||||
TileObject(CGObjectInstance *obj_, QRect rect_);
|
||||
~TileObject();
|
||||
};
|
||||
|
||||
struct TerrainTile2
|
||||
{
|
||||
std::vector<TerrainTileObject> objects; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
|
||||
};
|
||||
using TileObjects = std::vector<TileObject>; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
|
||||
|
||||
class MapHandler
|
||||
{
|
||||
@ -44,21 +40,30 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
ui8 getHeroFrameGroup(ui8 dir, bool isMoving) const;
|
||||
ui8 getPhaseShift(const CGObjectInstance *object) 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;
|
||||
int index(int x, int y, int z) const;
|
||||
int index(const int3 &) const;
|
||||
|
||||
std::shared_ptr<QImage> findFlagBitmapInternal(std::shared_ptr<Animation> animation, int anim, int group, ui8 dir, bool moving) const;
|
||||
|
||||
public:
|
||||
|
||||
std::shared_ptr<QImage> findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) 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
|
||||
{
|
||||
TERRAIN, OBJECTS, ROADS, RIVERS, FOW, HEROES, HERO_FLAGS, FRAME, AFTER_LAST
|
||||
@ -66,59 +71,34 @@ public:
|
||||
|
||||
void initObjectRects();
|
||||
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
|
||||
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 updateWater();
|
||||
|
||||
void drawTerrainTile(QPainter & painter, int x, int y, int z);
|
||||
/// draws a river segment on current tile
|
||||
void drawRiver(QPainter & painter, int x, int y, int z);
|
||||
/// draws a road segment on current tile
|
||||
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)
|
||||
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);
|
||||
std::vector<TerrainTileObject> & 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);
|
||||
std::vector<TileObject> & getObjects(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);
|
||||
};
|
||||
|
@ -319,7 +319,6 @@ void ObjectsLayer::setDirty(int x, int y)
|
||||
|
||||
void ObjectsLayer::setDirty(const CGObjectInstance * object)
|
||||
{
|
||||
dirty.insert(object);
|
||||
}
|
||||
|
||||
SelectionObjectsLayer::SelectionObjectsLayer(MapSceneBase * s): AbstractLayer(s), newObject(nullptr)
|
||||
|
@ -98,7 +98,8 @@ public:
|
||||
void setDirty(const CGObjectInstance * object);
|
||||
|
||||
private:
|
||||
std::set<const CGObjectInstance *> dirty;
|
||||
std::set<const CGObjectInstance *> objDirty;
|
||||
std::set<int3> dirty;
|
||||
};
|
||||
|
||||
|
||||
|
@ -88,6 +88,13 @@ void WindowNewMap::on_okButtong_clicked()
|
||||
std::unique_ptr<CMap> nmap;
|
||||
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);
|
||||
//TODO: fix water and roads
|
||||
generator.disableModificator("RoadPlacer");
|
||||
@ -96,9 +103,16 @@ void WindowNewMap::on_okButtong_clicked()
|
||||
auto progressBarWnd = new GeneratorProgress(generator, this);
|
||||
progressBarWnd->show();
|
||||
|
||||
auto f = std::async(std::launch::async, &CMapGenerator::generate, &generator);
|
||||
progressBarWnd->update();
|
||||
nmap = f.get();
|
||||
try
|
||||
{
|
||||
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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user