1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

Merge pull request #84 from Fayth/test/advMapFading

If no one objects, I will try to merge this.
This commit is contained in:
DjWarmonger 2015-02-18 09:52:09 +01:00
commit 2a082e6c21
11 changed files with 576 additions and 213 deletions

View File

@ -89,9 +89,9 @@ CondSh<EMoveState> stillMoveHero; //used during hero movement
int CPlayerInterface::howManyPeople = 0; int CPlayerInterface::howManyPeople = 0;
static bool objectBlitOrderSorter(const std::pair<const CGObjectInstance*,SDL_Rect> & a, const std::pair<const CGObjectInstance*,SDL_Rect> & b) static bool objectBlitOrderSorter(const TerrainTileObject & a, const TerrainTileObject & b)
{ {
return CMapHandler::compareObjectBlitOrder(a.first, b.first); return CMapHandler::compareObjectBlitOrder(a.obj, b.obj);
} }
CPlayerInterface::CPlayerInterface(PlayerColor Player) CPlayerInterface::CPlayerInterface(PlayerColor Player)
@ -205,9 +205,9 @@ STRONG_INLINE void subRect(const int & x, const int & y, const int & z, const SD
{ {
TerrainTile2 & hlp = CGI->mh->ttiles[x][y][z]; TerrainTile2 & hlp = CGI->mh->ttiles[x][y][z];
for(auto & elem : hlp.objects) for(auto & elem : hlp.objects)
if(elem.first->id == hid) if(elem.obj->id == hid)
{ {
elem.second = r; elem.rect = r;
return; return;
} }
} }
@ -216,7 +216,7 @@ STRONG_INLINE void delObjRect(const int & x, const int & y, const int & z, const
{ {
TerrainTile2 & hlp = CGI->mh->ttiles[x][y][z]; TerrainTile2 & hlp = CGI->mh->ttiles[x][y][z];
for(int h=0; h<hlp.objects.size(); ++h) for(int h=0; h<hlp.objects.size(); ++h)
if(hlp.objects[h].first->id == hid) if(hlp.objects[h].obj->id == hid)
{ {
hlp.objects.erase(hlp.objects.begin()+h); hlp.objects.erase(hlp.objects.begin()+h);
return; return;
@ -239,8 +239,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
// TODO -> we should not need full CGHeroInstance structure to display animation or it should not be handled by playerint (but by the client itself) // TODO -> we should not need full CGHeroInstance structure to display animation or it should not be handled by playerint (but by the client itself)
const TerrainTile2 &tile = CGI->mh->ttiles[hp.x-1][hp.y][hp.z]; const TerrainTile2 &tile = CGI->mh->ttiles[hp.x-1][hp.y][hp.z];
for(auto & elem : tile.objects) for(auto & elem : tile.objects)
if(elem.first->id == details.id) if(elem.obj->id == details.id)
hero = dynamic_cast<const CGHeroInstance *>(elem.first); hero = dynamic_cast<const CGHeroInstance *>(elem.obj);
if(!hero) //still nothing... if(!hero) //still nothing...
return; return;
@ -276,7 +276,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
} }
} }
adventureInt->centerOn(hero); //actualizing screen pos adventureInt->centerOn(hero, true); //actualizing screen pos
adventureInt->minimap.redraw(); adventureInt->minimap.redraw();
adventureInt->heroList.update(hero); adventureInt->heroList.update(hero);
return; //teleport - no fancy moving animation return; //teleport - no fancy moving animation
@ -1676,17 +1676,17 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
{ {
//ho->moveDir = 1; //ho->moveDir = 1;
ho->isStanding = false; ho->isStanding = false;
CGI->mh->ttiles[hp.x-3][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -31, -31))); CGI->mh->ttiles[hp.x-3][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, -31)));
CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 1, -31))); CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 1, -31)));
CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 33, -31))); CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 33, -31)));
CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 65, -31))); CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 65, -31)));
CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -31, 1))); CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 1)));
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 1, 1), ho->id); subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 1, 1), ho->id);
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 33, 1), ho->id); subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 33, 1), ho->id);
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 65, 1), ho->id); subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 65, 1), ho->id);
CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -31, 33))); CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 33)));
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, 1, 33), ho->id); subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, 1, 33), ho->id);
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 33), ho->id); subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 33), ho->id);
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 33), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 33), ho->id);
@ -1704,9 +1704,9 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
{ {
//ho->moveDir = 2; //ho->moveDir = 2;
ho->isStanding = false; ho->isStanding = false;
CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 0, -31))); CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 0, -31)));
CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 32, -31))); CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 32, -31)));
CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 64, -31))); CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 64, -31)));
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 0, 1), ho->id); subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 0, 1), ho->id);
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 32, 1), ho->id); subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 32, 1), ho->id);
@ -1724,20 +1724,20 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
{ {
//ho->moveDir = 3; //ho->moveDir = 3;
ho->isStanding = false; ho->isStanding = false;
CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -1, -31))); CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -1, -31)));
CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 31, -31))); CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 31, -31)));
CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 63, -31))); CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 63, -31)));
CGI->mh->ttiles[hp.x+1][hp.y-2][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, -31))); CGI->mh->ttiles[hp.x+1][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, -31)));
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, -1, 1), ho->id); subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, -1, 1), ho->id);
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 31, 1), ho->id); subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 31, 1), ho->id);
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 63, 1), ho->id); subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 63, 1), ho->id);
CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, 1))); CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 1)));
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, -1, 33), ho->id); subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, -1, 33), ho->id);
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 31, 33), ho->id); subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 31, 33), ho->id);
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 33), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 33), ho->id);
CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, 33))); CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 33)));
std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
@ -1755,12 +1755,12 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, -1, 0), ho->id); subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, -1, 0), ho->id);
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 31, 0), ho->id); subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 31, 0), ho->id);
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 63, 0), ho->id); subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 63, 0), ho->id);
CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, 0))); CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 0)));
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, -1, 32), ho->id); subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, -1, 32), ho->id);
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 31, 32), ho->id); subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 31, 32), ho->id);
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 32), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 32), ho->id);
CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, 32))); CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 32)));
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter); std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter);
@ -1773,17 +1773,17 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, -1, -1), ho->id); subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, -1, -1), ho->id);
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 31, -1), ho->id); subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 31, -1), ho->id);
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 63, -1), ho->id); subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 63, -1), ho->id);
CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, -1))); CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, -1)));
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, -1, 31), ho->id); subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, -1, 31), ho->id);
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 31, 31), ho->id); subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 31, 31), ho->id);
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 31), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 31), ho->id);
CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, 31))); CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 31)));
CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -1, 63))); CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -1, 63)));
CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 31, 63))); CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 31, 63)));
CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 63, 63))); CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 63, 63)));
CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, 63))); CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 63)));
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter); std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter);
@ -1806,9 +1806,9 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 32, 31), ho->id); subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 32, 31), ho->id);
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 64, 31), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 64, 31), ho->id);
CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 0, 63))); CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 0, 63)));
CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 32, 63))); CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 32, 63)));
CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 64, 63))); CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 64, 63)));
std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
@ -1818,20 +1818,20 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
{ {
//ho->moveDir = 7; //ho->moveDir = 7;
ho->isStanding = false; ho->isStanding = false;
CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -31, -1))); CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, -1)));
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 1, -1), ho->id); subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 1, -1), ho->id);
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 33, -1), ho->id); subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 33, -1), ho->id);
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 65, -1), ho->id); subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 65, -1), ho->id);
CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -31, 31))); CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 31)));
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, 1, 31), ho->id); subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, 1, 31), ho->id);
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 31), ho->id); subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 31), ho->id);
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 31), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 31), ho->id);
CGI->mh->ttiles[hp.x-3][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -31, 63))); CGI->mh->ttiles[hp.x-3][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 63)));
CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 1, 63))); CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 1, 63)));
CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 33, 63))); CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 33, 63)));
CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 65, 63))); CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 65, 63)));
std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter); std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter);
@ -1846,12 +1846,12 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
{ {
//ho->moveDir = 8; //ho->moveDir = 8;
ho->isStanding = false; ho->isStanding = false;
CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -31, 0))); CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 0)));
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 1, 0), ho->id); subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 1, 0), ho->id);
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 33, 0), ho->id); subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 33, 0), ho->id);
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 65, 0), ho->id); subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 65, 0), ho->id);
CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, -31, 32))); CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 32)));
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, 1, 32), ho->id); subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, 1, 32), ho->id);
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 32), ho->id); subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 32), ho->id);
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 32), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 32), ho->id);

View File

@ -336,7 +336,7 @@ void RemoveObject::applyFirstCl( CClient *cl )
{ {
const CGObjectInstance *o = cl->getObj(id); const CGObjectInstance *o = cl->getObj(id);
CGI->mh->hideObject(o); CGI->mh->hideObject(o, true);
//notify interfaces about removal //notify interfaces about removal
for(auto i=cl->playerint.begin(); i!=cl->playerint.end(); i++) for(auto i=cl->playerint.begin(); i!=cl->playerint.end(); i++)
@ -367,7 +367,7 @@ void TryMoveHero::applyFirstCl( CClient *cl )
} }
if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK || !humanKnows) if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK || !humanKnows)
CGI->mh->removeObject(h); CGI->mh->removeObject(h, result == EMBARK && humanKnows);
if(result == DISEMBARK) if(result == DISEMBARK)
@ -381,7 +381,7 @@ void TryMoveHero::applyCl( CClient *cl )
if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK) if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK)
{ {
CGI->mh->printObject(h); CGI->mh->printObject(h, result == DISEMBARK);
} }
if(result == EMBARK) if(result == EMBARK)
@ -908,7 +908,7 @@ void NewObject::applyCl(CClient *cl)
cl->invalidatePaths(); cl->invalidatePaths();
const CGObjectInstance *obj = cl->getObj(id); const CGObjectInstance *obj = cl->getObj(id);
CGI->mh->printObject(obj); CGI->mh->printObject(obj, true);
for(auto i=cl->playerint.begin(); i!=cl->playerint.end(); i++) for(auto i=cl->playerint.begin(); i!=cl->playerint.end(); i++)
{ {

View File

@ -1222,3 +1222,91 @@ void CAnimation::getAnimInfo()
logGlobal->errorStream()<<", "<<anim->images.begin()->second.size()<<" image loaded in group "<< anim->images.begin()->first; logGlobal->errorStream()<<", "<<anim->images.begin()->second.size()<<" image loaded in group "<< anim->images.begin()->first;
} }
} }
float CFadeAnimation::initialCounter() const
{
if (fadingMode == EMode::OUT)
return 1.0f;
return 0.0f;
}
void CFadeAnimation::update()
{
if (!fading)
return;
if (fadingMode == EMode::OUT)
fadingCounter -= delta;
else
fadingCounter += delta;
if (isFinished())
{
fading = false;
if (shouldFreeSurface)
{
SDL_FreeSurface(fadingSurface);
fadingSurface = nullptr;
}
}
}
bool CFadeAnimation::isFinished() const
{
if (fadingMode == EMode::OUT)
return fadingCounter <= 0.0f;
return fadingCounter >= 1.0f;
}
CFadeAnimation::CFadeAnimation()
: fadingSurface(nullptr),
fading(false),
fadingMode(EMode::NONE)
{
}
CFadeAnimation::~CFadeAnimation()
{
if (fadingSurface && shouldFreeSurface)
SDL_FreeSurface(fadingSurface);
}
void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd /* = false */, float animDelta /* = DEFAULT_DELTA */)
{
if (fading)
{
// in that case, immediately finish the previous fade
// (alternatively, we could just return here to ignore the new fade request until this one finished (but we'd need to free the passed bitmap to avoid leaks))
logGlobal->warnStream() << "Tried to init fading animation that is already running.";
if (fadingSurface && shouldFreeSurface)
SDL_FreeSurface(fadingSurface);
}
if (animDelta <= 0.0f)
{
logGlobal->warnStream() << "Fade anim: delta should be positive; " << animDelta << " given.";
animDelta = DEFAULT_DELTA;
}
if (sourceSurface)
fadingSurface = sourceSurface;
delta = animDelta;
fadingMode = mode;
fadingCounter = initialCounter();
fading = true;
shouldFreeSurface = freeSurfaceAtEnd;
}
void CFadeAnimation::draw(SDL_Surface * targetSurface, const SDL_Rect * sourceRect, SDL_Rect * destRect)
{
if (!fading || !fadingSurface || fadingMode == EMode::NONE)
{
fading = false;
return;
}
SDL_SetSurfaceAlphaMod(fadingSurface, fadingCounter * 255);
SDL_BlitSurface(fadingSurface, sourceRect, targetSurface, destRect);
SDL_SetSurfaceAlphaMod(fadingSurface, 255);
}

View File

@ -220,3 +220,31 @@ public:
//total count of frames in group (including not loaded) //total count of frames in group (including not loaded)
size_t size(size_t group=0) const; size_t size(size_t group=0) const;
}; };
class CFadeAnimation
{
public:
enum class EMode
{
NONE, IN, OUT
};
private:
static constexpr float DEFAULT_DELTA = 0.05f;
float delta;
SDL_Surface * fadingSurface;
bool fading;
float fadingCounter;
bool shouldFreeSurface;
float initialCounter() const;
bool isFinished() const;
public:
EMode fadingMode;
CFadeAnimation();
~CFadeAnimation();
void init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd = false, float animDelta = DEFAULT_DELTA);
void update();
void draw(SDL_Surface * targetSurface, const SDL_Rect * sourceRect, SDL_Rect * destRect);
bool isFading() const { return fading; }
};

View File

@ -12,6 +12,7 @@
#include "mapHandler.h" #include "mapHandler.h"
#include "CBitmapHandler.h" #include "CBitmapHandler.h"
#include "gui/CAnimation.h"
#include "gui/SDL_Extensions.h" #include "gui/SDL_Extensions.h"
#include "CGameInfo.h" #include "CGameInfo.h"
#include "../lib/mapObjects/CGHeroInstance.h" #include "../lib/mapObjects/CGHeroInstance.h"
@ -75,9 +76,9 @@ std::string nameFromType (int typ)
return std::string(); return std::string();
} }
static bool objectBlitOrderSorter(const std::pair<const CGObjectInstance*,SDL_Rect> & a, const std::pair<const CGObjectInstance*,SDL_Rect> & b) static bool objectBlitOrderSorter(const TerrainTileObject & a, const TerrainTileObject & b)
{ {
return CMapHandler::compareObjectBlitOrder(a.first, b.first); return CMapHandler::compareObjectBlitOrder(a.obj, b.obj);
} }
struct NeighborTilesInfo struct NeighborTilesInfo
@ -185,10 +186,12 @@ void CMapHandler::prepareFOWDefs()
} }
} }
void CMapHandler::drawTerrainRectNew(SDL_Surface * targetSurface, const MapDrawingInfo * info) EMapAnimRedrawStatus CMapHandler::drawTerrainRectNew(SDL_Surface * targetSurface, const MapDrawingInfo * info, bool redrawOnlyAnim /* = false */)
{ {
assert(info); assert(info);
bool hasActiveFade = updateObjectsFade();
resolveBlitter(info)->blit(targetSurface, info); resolveBlitter(info)->blit(targetSurface, info);
return hasActiveFade ? EMapAnimRedrawStatus::REDRAW_REQUESTED : EMapAnimRedrawStatus::OK;
} }
void CMapHandler::roadsRiverTerrainInit() void CMapHandler::roadsRiverTerrainInit()
@ -346,7 +349,7 @@ void CMapHandler::initObjectRects()
cr.h = 32; cr.h = 32;
cr.x = bitmap->w - fx * 32 - 32; cr.x = bitmap->w - fx * 32 - 32;
cr.y = bitmap->h - fy * 32 - 32; cr.y = bitmap->h - fy * 32 - 32;
std::pair<const CGObjectInstance*,SDL_Rect> toAdd = std::make_pair(obj,cr); TerrainTileObject toAdd(obj,cr);
if( map->isInTheMap(currTile) && // within map if( map->isInTheMap(currTile) && // within map
@ -609,12 +612,12 @@ void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf
auto & objects = tile.objects; auto & objects = tile.objects;
for(auto & object : objects) for(auto & object : objects)
{ {
const CGObjectInstance * obj = object.first; const CGObjectInstance * obj = object.obj;
if (obj->pos.z != pos.z) if (obj->pos.z != pos.z)
continue; continue;
if (!(*info->visibilityMap)[pos.x][pos.y][pos.z]) if (!(*info->visibilityMap)[pos.x][pos.y][pos.z])
continue; // TODO needs to skip this check if we have artifacts-aura-like spell cast continue; // TODO needs to skip this check if we have view-air-like spell cast
if (!obj->visitableAt(pos.x, pos.y)) if (!obj->visitableAt(pos.x, pos.y))
continue; continue;
@ -668,12 +671,6 @@ void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf
} }
} }
void CMapHandler::CMapWorldViewBlitter::drawNormalObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect) const
{
Rect scaledSourceRect(sourceRect->x * info->scale, sourceRect->y * info->scale, tileSize, tileSize);
CMapBlitter::drawNormalObject(targetSurf, sourceSurf, &scaledSourceRect);
}
void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const
{ {
if (moving) if (moving)
@ -682,13 +679,13 @@ void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, S
CMapBlitter::drawHeroFlag(targetSurf, sourceSurf, sourceRect, destRect, false); CMapBlitter::drawHeroFlag(targetSurf, sourceSurf, sourceRect, destRect, false);
} }
void CMapHandler::CMapWorldViewBlitter::drawHero(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const
{ {
if (moving) if (moving)
return; return;
Rect scaledSourceRect(sourceRect->x * info->scale, sourceRect->y * info->scale, sourceRect->w, sourceRect->h); Rect scaledSourceRect(sourceRect->x * info->scale, sourceRect->y * info->scale, sourceRect->w, sourceRect->h);
CMapBlitter::drawHero(targetSurf, sourceSurf, &scaledSourceRect, false); CMapBlitter::drawObject(targetSurf, sourceSurf, &scaledSourceRect, false);
} }
void CMapHandler::CMapBlitter::drawTileTerrain(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile2 & tile) const void CMapHandler::CMapBlitter::drawTileTerrain(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile2 & tile) const
@ -788,21 +785,15 @@ void CMapHandler::CMapBlitter::drawFrame(SDL_Surface * targetSurf) const
drawElement(EMapCacheType::FRAME, parent->ttiles[pos.x][pos.y][topTile.z].terbitmap, nullptr, targetSurf, &destRect); drawElement(EMapCacheType::FRAME, parent->ttiles[pos.x][pos.y][topTile.z].terbitmap, nullptr, targetSurf, &destRect);
} }
void CMapHandler::CMapBlitter::drawNormalObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect) const
{
Rect destRect(realTileRect);
drawElement(EMapCacheType::OBJECTS, sourceSurf, sourceRect, targetSurf, &destRect, true);
}
void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const
{ {
drawElement(EMapCacheType::HERO_FLAGS, sourceSurf, sourceRect, targetSurf, destRect, false); drawElement(EMapCacheType::HERO_FLAGS, sourceSurf, sourceRect, targetSurf, destRect, false);
} }
void CMapHandler::CMapBlitter::drawHero(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const
{ {
Rect dstRect(realTileRect); Rect dstRect(realTileRect);
drawElement(EMapCacheType::HEROES, sourceSurf, sourceRect, targetSurf, &dstRect, true); drawElement(EMapCacheType::OBJECTS, sourceSurf, sourceRect, targetSurf, &dstRect, true);
} }
void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
@ -810,7 +801,20 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra
auto & objects = tile.objects; auto & objects = tile.objects;
for(auto & object : objects) for(auto & object : objects)
{ {
const CGObjectInstance * obj = object.first; if (object.fadeAnimKey >= 0)
{
auto fadeIter = parent->fadeAnims.find(object.fadeAnimKey);
if (fadeIter != parent->fadeAnims.end())
{
// this object is currently fading, so skip normal drawing
Rect r2(realTileRect);
CFadeAnimation * fade = (*fadeIter).second.second;
fade->draw(targetSurf, nullptr, &r2);
continue;
}
}
const CGObjectInstance * obj = object.obj;
if (!graphics->getDef(obj)) if (!graphics->getDef(obj))
processDef(obj->appearance); processDef(obj->appearance);
if (!graphics->getDef(obj) && !obj->appearance.animationFile.empty()) if (!graphics->getDef(obj) && !obj->appearance.animationFile.empty())
@ -819,121 +823,27 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra
if (!canDrawObject(obj)) if (!canDrawObject(obj))
continue; continue;
PlayerColor color = obj->tempOwner; auto objData = findObjectBitmap(obj, info->anim);
if (objData.objBitmap)
SDL_Rect pp = object.second;
pp.h = tileSize;
pp.w = tileSize;
const CGHeroInstance * hero = (obj->ID != Obj::HERO
? nullptr
: static_cast<const CGHeroInstance*>(obj));
//print hero / boat and flag
if((hero && hero->moveDir && hero->type) || (obj->ID == Obj::BOAT)) //it's hero or boat
{ {
const int IMGVAL = 8; //frames per group of movement animation Rect srcRect(object.rect.x, object.rect.y, tileSize, tileSize);
ui8 dir;
std::vector<Cimage> * iv = nullptr;
std::vector<CDefEssential *> Graphics::*flg = nullptr;
SDL_Surface * tb = nullptr; //surface to blitted
if(hero) //hero drawObject(targetSurf, objData.objBitmap, &srcRect, objData.isMoving);
if (objData.flagBitmap)
{ {
if(hero->tempOwner >= PlayerColor::PLAYER_LIMIT) //Neutral hero? if (objData.isMoving)
{ {
logGlobal->errorStream() << "A neutral hero (" << hero->name << ") at " << hero->pos << ". Should not happen!"; srcRect.y += FRAMES_PER_MOVE_ANIM_GROUP * 2 - tileSize;
continue; 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)
dir = hero->moveDir;
//pick graphics of hero (or boat if hero is sailing)
if (hero->boat)
iv = &graphics->boatAnims[hero->boat->subID]->ourImages;
else
iv = &graphics->heroAnims[hero->appearance.animationFile]->ourImages;
//pick appropriate flag set
if(hero->boat)
{
switch (hero->boat->subID)
{
case 0: flg = &Graphics::flags1; break;
case 1: flg = &Graphics::flags2; break;
case 2: flg = &Graphics::flags3; break;
default: logGlobal->errorStream() << "Not supported boat subtype: " << hero->boat->subID;
}
}
else
{
flg = &Graphics::flags4;
}
}
else //boat
{
const CGBoat *boat = static_cast<const CGBoat*>(obj);
dir = boat->direction;
iv = &graphics->boatAnims[boat->subID]->ourImages;
}
if(hero && !hero->isStanding) //hero is moving
{
size_t gg;
for(gg=0; gg<iv->size(); ++gg)
{
if((*iv)[gg].groupNumber == getHeroFrameNum(dir, true))
{
tb = (*iv)[gg+info->getHeroAnim()%IMGVAL].bitmap;
break;
}
}
drawHero(targetSurf, tb, &pp, true);
pp.y += IMGVAL * 2 - tileSize;
Rect destRect(realPos.x, realPos.y - tileSize / 2, tileSize, tileSize);
drawHeroFlag(targetSurf, (graphics->*flg)[color.getNum()]->ourImages[gg + info->getHeroAnim() % IMGVAL + 35].bitmap, &pp, &destRect, true);
}
else //hero / boat stands still
{
size_t gg;
for(gg=0; gg < iv->size(); ++gg)
{
if((*iv)[gg].groupNumber == getHeroFrameNum(dir, false))
{
tb = (*iv)[gg].bitmap;
break;
}
}
drawHero(targetSurf, tb, &pp, false);
//printing flag
if(flg
&& obj->pos.x == pos.x
&& obj->pos.y == pos.y)
{ {
Rect dstRect(realPos.x - 2 * tileSize, realPos.y - tileSize, 3 * tileSize, 2 * tileSize); Rect dstRect(realPos.x - 2 * tileSize, realPos.y - tileSize, 3 * tileSize, 2 * tileSize);
if (dstRect.x - info->drawBounds->x > -tileSize * 2) drawHeroFlag(targetSurf, objData.flagBitmap, nullptr, &dstRect, false);
{
auto surf = (graphics->*flg)[color.getNum()]->ourImages
[getHeroFrameNum(dir, false) * 8 + (info->getHeroAnim() / 4) % IMGVAL].bitmap;
drawHeroFlag(targetSurf, surf, nullptr, &dstRect, false);
}
} }
} }
} }
else //blit normal object
{
const std::vector<Cimage> &ourImages = graphics->getDef(obj)->ourImages;
SDL_Surface *bitmap = ourImages[(info->anim + getPhaseShift(obj)) % ourImages.size()].bitmap;
//setting appropriate flag color
if(color < PlayerColor::PLAYER_LIMIT || color==PlayerColor::NEUTRAL)
CSDL_Ext::setPlayerColor(bitmap, color);
drawNormalObject(targetSurf, bitmap, &pp);
}
} }
} }
@ -1086,6 +996,109 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
SDL_SetClipRect(targetSurf, &prevClip); SDL_SetClipRect(targetSurf, &prevClip);
} }
CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::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->errorStream() << "A neutral hero (" << hero->name << ") at " << hero->pos << ". Should not happen!";
return CMapHandler::AnimBitmapHolder();
}
//pick graphics of hero (or boat if hero is sailing)
CDefEssential * def = nullptr;
if (hero->boat)
def = graphics->boatAnims[hero->boat->subID];
else
def = graphics->heroAnims[hero->appearance.animationFile];
bool moving = !hero->isStanding;
int framesOffset = moving ? anim % FRAMES_PER_MOVE_ANIM_GROUP : 0;
int index = findAnimIndexByGroup(def, getHeroFrameNum(hero->moveDir, moving));
if (index >= 0)
{
auto heroBitmap = def->ourImages[index + framesOffset].bitmap;
auto flagBitmap = findFlagBitmap(hero, anim, &hero->tempOwner, index + 35);
return CMapHandler::AnimBitmapHolder(heroBitmap, flagBitmap, moving);
}
}
return CMapHandler::AnimBitmapHolder();
}
CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findBoatBitmap(const CGBoat * boat, int anim) const
{
auto def = graphics->boatAnims[boat->subID];
int index = findAnimIndexByGroup(def, getHeroFrameNum(boat->direction, false));
if (index < 0)
return CMapHandler::AnimBitmapHolder();
return CMapHandler::AnimBitmapHolder(def->ourImages[index].bitmap);
}
SDL_Surface * CMapHandler::CMapBlitter::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int indexOffset) const
{
if (!hero)
return nullptr;
if (hero->boat)
return findBoatFlagBitmap(hero->boat, anim, color, indexOffset, hero->moveDir);
return findHeroFlagBitmap(hero, anim, color, indexOffset);
}
SDL_Surface * CMapHandler::CMapBlitter::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int indexOffset) const
{
return findFlagBitmapInternal(graphics->flags4[color->getNum()], anim, indexOffset, hero->moveDir, !hero->isStanding);
}
SDL_Surface * CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int indexOffset, ui8 dir) const
{
std::vector<CDefEssential *> Graphics::*flg = nullptr;
switch (boat->subID)
{
case 0: flg = &Graphics::flags1; break;
case 1: flg = &Graphics::flags2; break;
case 2: flg = &Graphics::flags3; break;
default: logGlobal->errorStream() << "Not supported boat subtype: " << boat->subID; return nullptr;
}
return findFlagBitmapInternal((graphics->*flg)[color->getNum()], anim, indexOffset, dir, false);
}
SDL_Surface * CMapHandler::CMapBlitter::findFlagBitmapInternal(const CDefEssential * def, int anim, int indexOffset, ui8 dir, bool moving) const
{
if (moving)
return def->ourImages[indexOffset + anim % FRAMES_PER_MOVE_ANIM_GROUP].bitmap;
return def->ourImages[getHeroFrameNum(dir, false) * FRAMES_PER_MOVE_ANIM_GROUP + (anim / 4) % FRAMES_PER_MOVE_ANIM_GROUP].bitmap;
}
int CMapHandler::CMapBlitter::findAnimIndexByGroup(const CDefEssential * def, int groupNum) const
{
auto iter = std::find_if(def->ourImages.begin(), def->ourImages.end(), [&](const Cimage &img){ return img.groupNumber == groupNum; });
if (iter == def->ourImages.end())
return -1;
return static_cast<int>(iter - def->ourImages.begin());
}
CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findObjectBitmap(const CGObjectInstance * obj, int anim) const
{
if (!obj)
return CMapHandler::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
const std::vector<Cimage> &ourImages = graphics->getDef(obj)->ourImages;
SDL_Surface *bitmap = ourImages[(anim + getPhaseShift(obj)) % ourImages.size()].bitmap;
//setting appropriate flag color
const PlayerColor &color = obj->tempOwner;
if(color < PlayerColor::PLAYER_LIMIT || color==PlayerColor::NEUTRAL)
CSDL_Ext::setPlayerColor(bitmap, color);
return CMapHandler::AnimBitmapHolder(bitmap);
}
ui8 CMapHandler::CMapBlitter::getPhaseShift(const CGObjectInstance *object) const ui8 CMapHandler::CMapBlitter::getPhaseShift(const CGObjectInstance *object) const
{ {
auto i = parent->animationPhase.find(object); auto i = parent->animationPhase.find(object);
@ -1145,12 +1158,79 @@ std::pair<SDL_Surface *, bool> CMapHandler::CMapBlitter::getVisBitmap() const
} }
} }
bool CMapHandler::printObject(const CGObjectInstance *obj) bool CMapHandler::updateObjectsFade()
{
for (auto iter = fadeAnims.begin(); iter != fadeAnims.end(); )
{
int3 pos = (*iter).second.first;
CFadeAnimation * anim = (*iter).second.second;
anim->update();
if (anim->isFading())
++iter;
else // fade finished
{
auto &objs = ttiles[pos.x][pos.y][pos.z].objects;
for (auto objIter = objs.begin(); objIter != objs.end(); ++objIter)
{
if ((*objIter).fadeAnimKey == (*iter).first)
{
if (anim->fadingMode == CFadeAnimation::EMode::OUT)
objs.erase(objIter); // if this was fadeout, remove the object from the map
else
(*objIter).fadeAnimKey = -1; // for fadein, just remove its connection to the finished fade
break;
}
}
iter = fadeAnims.erase(iter);
logAnim->traceStream() << "Fade anim finished, remaining: " << fadeAnims.size();
}
}
return !fadeAnims.empty();
}
bool CMapHandler::startObjectFade(TerrainTileObject & obj, bool in, int3 pos)
{
SDL_Surface * fadeBitmap;
auto objData = normalBlitter->findObjectBitmap(obj.obj, 0);
if (objData.objBitmap)
{
if (objData.isMoving) // ignore fading of moving objects (for now?)
{
logAnim->debugStream() << "Ignoring fade of moving object";
return false;
}
fadeBitmap = CSDL_Ext::newSurface(32, 32); // TODO cache these bitmaps instead of creating new ones?
Rect objSrcRect(obj.rect.x, obj.rect.y, 32, 32);
CSDL_Ext::blit8bppAlphaTo24bpp(objData.objBitmap, &objSrcRect, fadeBitmap, nullptr);
if (objData.flagBitmap)
{
if (obj.obj->pos.x - 1 == pos.x && obj.obj->pos.y - 1 == pos.y) // -1 to draw flag in top-center instead of right-bottom; kind of a hack
{
Rect flagSrcRect(32, 0, 32, 32);
CSDL_Ext::blitSurface(objData.flagBitmap, &flagSrcRect, fadeBitmap, nullptr);
}
}
auto anim = new CFadeAnimation();
anim->init(in ? CFadeAnimation::EMode::IN : CFadeAnimation::EMode::OUT, fadeBitmap, true);
fadeAnims[++fadeAnimCounter] = std::pair<int3, CFadeAnimation*>(pos, anim);
obj.fadeAnimKey = fadeAnimCounter;
return true;
}
return false;
}
bool CMapHandler::printObject(const CGObjectInstance *obj, bool fadein /* = false */)
{ {
if (!graphics->getDef(obj)) if (!graphics->getDef(obj))
processDef(obj->appearance); processDef(obj->appearance);
const SDL_Surface *bitmap = graphics->getDef(obj)->ourImages[0].bitmap; SDL_Surface *bitmap = graphics->getDef(obj)->ourImages[0].bitmap;
const int tilesW = bitmap->w/32; const int tilesW = bitmap->w/32;
const int tilesH = bitmap->h/32; const int tilesH = bitmap->h/32;
@ -1163,10 +1243,17 @@ bool CMapHandler::printObject(const CGObjectInstance *obj)
cr.h = 32; cr.h = 32;
cr.x = fx*32; cr.x = fx*32;
cr.y = fy*32; cr.y = fy*32;
std::pair<const CGObjectInstance*,SDL_Rect> toAdd = std::make_pair(obj, cr); TerrainTileObject toAdd(obj, cr);
if((obj->pos.x + fx - tilesW+1)>=0 && (obj->pos.x + fx - tilesW+1)<ttiles.size()-frameW && (obj->pos.y + fy - tilesH+1)>=0 && (obj->pos.y + fy - tilesH+1)<ttiles[0].size()-frameH) if((obj->pos.x + fx - tilesW+1)>=0 && (obj->pos.x + fx - tilesW+1)<ttiles.size()-frameW && (obj->pos.y + fy - tilesH+1)>=0 && (obj->pos.y + fy - tilesH+1)<ttiles[0].size()-frameH)
{ {
TerrainTile2 & curt = ttiles[obj->pos.x + fx - tilesW+1][obj->pos.y + fy - tilesH+1][obj->pos.z]; int3 pos(obj->pos.x + fx - tilesW + 1, obj->pos.y + fy - tilesH + 1, obj->pos.z);
TerrainTile2 & curt = ttiles[pos.x][pos.y][pos.z];
if (fadein && ADVOPT.objectFading)
{
startObjectFade(toAdd, true, pos);
}
auto i = curt.objects.begin(); auto i = curt.objects.begin();
for(; i != curt.objects.end(); i++) for(; i != curt.objects.end(); i++)
@ -1188,8 +1275,9 @@ bool CMapHandler::printObject(const CGObjectInstance *obj)
return true; return true;
} }
bool CMapHandler::hideObject(const CGObjectInstance *obj) bool CMapHandler::hideObject(const CGObjectInstance *obj, bool fadeout /* = false */)
{ {
// do we actually need to search through the whole map for this?
for (size_t i=0; i<map->width; i++) for (size_t i=0; i<map->width; i++)
{ {
for (size_t j=0; j<map->height; j++) for (size_t j=0; j<map->height; j++)
@ -1198,9 +1286,15 @@ bool CMapHandler::hideObject(const CGObjectInstance *obj)
{ {
for(size_t x=0; x < ttiles[i][j][k].objects.size(); x++) for(size_t x=0; x < ttiles[i][j][k].objects.size(); x++)
{ {
if (ttiles[i][j][k].objects[x].first->id == obj->id) if (ttiles[i][j][k].objects[x].obj->id == obj->id)
{ {
ttiles[i][j][k].objects.erase(ttiles[i][j][k].objects.begin() + x); if (fadeout && ADVOPT.objectFading) // object should be faded == erase is delayed until the end of fadeout
{
if (!startObjectFade(ttiles[i][j][k].objects[x], false, int3(i, j, k)))
ttiles[i][j][k].objects.erase(ttiles[i][j][k].objects.begin() + x);
}
else
ttiles[i][j][k].objects.erase(ttiles[i][j][k].objects.begin() + x);
break; break;
} }
} }
@ -1209,9 +1303,9 @@ bool CMapHandler::hideObject(const CGObjectInstance *obj)
} }
return true; return true;
} }
bool CMapHandler::removeObject(CGObjectInstance *obj) bool CMapHandler::removeObject(CGObjectInstance *obj, bool fadeout /* = false */)
{ {
hideObject(obj); hideObject(obj, fadeout);
return true; return true;
} }
@ -1286,6 +1380,11 @@ ui8 CMapHandler::getDir(const int3 &a, const int3 &b)
return -2; //shouldn't happen return -2; //shouldn't happen
} }
bool CMapHandler::canStartHeroMovement()
{
return fadeAnims.empty(); // don't allow movement during fade animation
}
void shiftColors(SDL_Surface *img, int from, int howMany) //shifts colors in palette void shiftColors(SDL_Surface *img, int from, int howMany) //shifts colors in palette
{ {
//works with at most 16 colors, if needed more -> increase values //works with at most 16 colors, if needed more -> increase values
@ -1331,6 +1430,8 @@ CMapHandler::~CMapHandler()
{ {
delete graphics->FoWfullHide; delete graphics->FoWfullHide;
delete graphics->FoWpartialHide; delete graphics->FoWpartialHide;
// if (fadingOffscreenBitmapSurface)
// delete fadingOffscreenBitmapSurface;
delete normalBlitter; delete normalBlitter;
delete worldViewBlitter; delete worldViewBlitter;
@ -1347,6 +1448,11 @@ CMapHandler::~CMapHandler()
for(int j=0; j < elem.size(); ++j) for(int j=0; j < elem.size(); ++j)
SDL_FreeSurface(elem[j]); SDL_FreeSurface(elem[j]);
} }
for (auto & elem : fadeAnims)
{
delete elem.second.second;
}
terrainGraphics.clear(); terrainGraphics.clear();
} }
@ -1358,6 +1464,7 @@ CMapHandler::CMapHandler()
normalBlitter = new CMapNormalBlitter(this); normalBlitter = new CMapNormalBlitter(this);
worldViewBlitter = new CMapWorldViewBlitter(this); worldViewBlitter = new CMapWorldViewBlitter(this);
puzzleViewBlitter = new CMapPuzzleViewBlitter(this); puzzleViewBlitter = new CMapPuzzleViewBlitter(this);
fadeAnimCounter = 0;
} }
void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terName ) void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terName )
@ -1367,9 +1474,9 @@ void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terN
const TerrainTile &t = map->getTile(pos); const TerrainTile &t = map->getTile(pos);
for(auto & elem : tt.objects) for(auto & elem : tt.objects)
{ {
if(elem.first->ID == Obj::HOLE) //Hole if(elem.obj->ID == Obj::HOLE) //Hole
{ {
out = elem.first->getObjectName(); out = elem.obj->getObjectName();
return; return;
} }
} }
@ -1480,3 +1587,14 @@ bool CMapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObj
return false; return false;
} }
TerrainTileObject::TerrainTileObject(const CGObjectInstance * obj_, SDL_Rect rect_)
: obj(obj_),
rect(rect_),
fadeAnimKey(-1)
{
}
TerrainTileObject::~TerrainTileObject()
{
}

View File

@ -17,14 +17,16 @@
class CGObjectInstance; class CGObjectInstance;
class CGHeroInstance; class CGHeroInstance;
class CGBoat;
class CMap; class CMap;
class CGDefInfo; class CGDefInfo;
class CGObjectInstance;
class CDefHandler; class CDefHandler;
struct TerrainTile; struct TerrainTile;
struct SDL_Surface; struct SDL_Surface;
struct SDL_Rect; struct SDL_Rect;
class CDefEssential; class CDefEssential;
class CFadeAnimation;
class PlayerColor;
enum class EWorldViewIcon enum class EWorldViewIcon
{ {
@ -50,11 +52,34 @@ enum class EWorldViewIcon
}; };
enum class EMapObjectFadingType
{
NONE,
IN,
OUT
};
enum class EMapAnimRedrawStatus
{
OK,
REDRAW_REQUESTED // map blitter requests quick redraw due to current animation
};
struct TerrainTileObject
{
const CGObjectInstance *obj;
SDL_Rect rect;
int fadeAnimKey;
TerrainTileObject(const CGObjectInstance *obj_, SDL_Rect rect_);
~TerrainTileObject();
};
struct TerrainTile2 struct TerrainTile2
{ {
SDL_Surface * terbitmap; //bitmap of terrain SDL_Surface * terbitmap; //bitmap of terrain
std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > objects; //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
TerrainTile2(); TerrainTile2();
}; };
@ -157,10 +182,25 @@ class CMapHandler
intptr_t genKey(intptr_t realPtr, ui8 mod); intptr_t genKey(intptr_t realPtr, ui8 mod);
}; };
/// helper struct to pass around resolved bitmaps of an object; surfaces can be nullptr if object doesn't have bitmap of that type
struct AnimBitmapHolder
{
SDL_Surface * objBitmap; // main object bitmap
SDL_Surface * flagBitmap; // flag bitmap for the object (probably only for heroes and boats with heroes)
bool isMoving; // indicates if the object is moving (again, heroes/boats only)
AnimBitmapHolder(SDL_Surface * objBitmap_ = nullptr, SDL_Surface * flagBitmap_ = nullptr, bool moving = false)
: objBitmap(objBitmap_),
flagBitmap(flagBitmap_),
isMoving(moving)
{}
};
class CMapBlitter class CMapBlitter
{ {
protected: protected:
static constexpr int FRAMES_PER_MOVE_ANIM_GROUP = 8;
CMapHandler * parent; // ptr to enclosing map handler; generally for legacy reasons, probably could/should be refactored out of here CMapHandler * parent; // ptr to enclosing map handler; generally for legacy reasons, probably could/should be refactored out of here
int tileSize; // size of a tile drawn on map [in pixels] int tileSize; // size of a tile drawn on map [in pixels]
int halfTileSizeCeil; // half of the tile size, rounded up int halfTileSizeCeil; // half of the tile size, rounded up
@ -187,10 +227,8 @@ class CMapHandler
virtual void drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const; virtual void drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) 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)
virtual void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const; virtual void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const;
/// current tile: draws non-hero object with given image/position virtual void drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const;
virtual void drawNormalObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect) const;
virtual void drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const; virtual void drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const;
virtual void drawHero(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const;
// second drawing pass // second drawing pass
@ -220,10 +258,22 @@ class CMapHandler
virtual bool canDrawObject(const CGObjectInstance * obj) const; virtual bool canDrawObject(const CGObjectInstance * obj) const;
virtual bool canDrawCurrentTile() const; virtual bool canDrawCurrentTile() 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;
SDL_Surface * findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int indexOffset) const;
SDL_Surface * findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int indexOffset) const;
SDL_Surface * findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int indexOffset, ui8 dir) const;
SDL_Surface * findFlagBitmapInternal(const CDefEssential * def, int anim, int indexOffset, ui8 dir, bool moving) const;
int findAnimIndexByGroup(const CDefEssential * def, int groupNum) const;
public: public:
CMapBlitter(CMapHandler * p) : parent(p) {} CMapBlitter(CMapHandler * p) : parent(p) {}
virtual ~CMapBlitter(){} virtual ~CMapBlitter(){}
void blit(SDL_Surface * targetSurf, const MapDrawingInfo * info); void blit(SDL_Surface * targetSurf, const MapDrawingInfo * info);
/// helper method that chooses correct bitmap(s) for given object
AnimBitmapHolder findObjectBitmap(const CGObjectInstance * obj, int anim) const;
}; };
@ -248,14 +298,13 @@ class CMapHandler
SDL_Surface * targetSurf, SDL_Rect * destRect, bool alphaBlit = false, ui8 rotationInfo = 0u) const override; SDL_Surface * targetSurf, SDL_Rect * destRect, bool alphaBlit = false, ui8 rotationInfo = 0u) const override;
void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override; void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override;
void drawNormalObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect) const override;
void drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override; void drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override;
void drawHero(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const; void drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const override;
void drawFrame(SDL_Surface * targetSurf) const override {} void drawFrame(SDL_Surface * targetSurf) const override {}
void init(const MapDrawingInfo * info) override; void init(const MapDrawingInfo * info) override;
SDL_Rect clip(SDL_Surface * targetSurf) const override; SDL_Rect clip(SDL_Surface * targetSurf) const override;
ui8 getHeroFrameNum(ui8 dir, bool isMoving) const override { return 0u; } // ui8 getHeroFrameNum(ui8 dir, bool isMoving) const override { return 0u; }
ui8 getPhaseShift(const CGObjectInstance *object) const override { return 0u; } ui8 getPhaseShift(const CGObjectInstance *object) const override { return 0u; }
void drawScaledRotatedElement(EMapCacheType type, SDL_Surface * baseSurf, SDL_Surface * targetSurf, ui8 rotation, void drawScaledRotatedElement(EMapCacheType type, SDL_Surface * baseSurf, SDL_Surface * targetSurf, ui8 rotation,
@ -284,7 +333,12 @@ class CMapHandler
CMapBlitter * worldViewBlitter; CMapBlitter * worldViewBlitter;
CMapBlitter * puzzleViewBlitter; CMapBlitter * puzzleViewBlitter;
std::map<int, std::pair<int3, CFadeAnimation*>> fadeAnims;
int fadeAnimCounter;
CMapBlitter * resolveBlitter(const MapDrawingInfo * info) const; CMapBlitter * resolveBlitter(const MapDrawingInfo * info) const;
bool updateObjectsFade();
bool startObjectFade(TerrainTileObject & obj, bool in, int3 pos);
public: public:
PseudoV< PseudoV< PseudoV<TerrainTile2> > > ttiles; //informations about map tiles PseudoV< PseudoV< PseudoV<TerrainTile2> > > ttiles; //informations about map tiles
int3 sizes; //map size (x = width, y = height, z = number of levels) int3 sizes; //map size (x = width, y = height, z = number of levels)
@ -320,9 +374,9 @@ public:
void getTerrainDescr(const int3 &pos, std::string & out, bool terName); //if tername == false => empty string when tile is clear void getTerrainDescr(const int3 &pos, std::string & out, bool terName); //if tername == false => empty string when tile is clear
CGObjectInstance * createObject(int id, int subid, int3 pos, int owner=254); //creates a new object with a certain id and subid CGObjectInstance * createObject(int id, int subid, int3 pos, int owner=254); //creates a new object with a certain id and subid
bool printObject(const CGObjectInstance * obj); //puts appropriate things to ttiles, so obj will be visible on map bool printObject(const CGObjectInstance * obj, bool fadein = false); //puts appropriate things to ttiles, so obj will be visible on map
bool hideObject(const CGObjectInstance * obj); //removes appropriate things from ttiles, so obj will be no longer visible on map (but still will exist) 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 removeObject(CGObjectInstance * obj); //removes object from each place in VCMI (I hope) bool removeObject(CGObjectInstance * obj, bool fadeout = false); //removes object from each place in VCMI (I hope)
void init(); void init();
void calculateBlockedPos(); void calculateBlockedPos();
void initObjectRects(); void initObjectRects();
@ -330,10 +384,12 @@ public:
void roadsRiverTerrainInit(); void roadsRiverTerrainInit();
void prepareFOWDefs(); void prepareFOWDefs();
void drawTerrainRectNew(SDL_Surface * targetSurface, const MapDrawingInfo * info); EMapAnimRedrawStatus drawTerrainRectNew(SDL_Surface * targetSurface, const MapDrawingInfo * info, bool redrawOnlyAnim = false);
void updateWater(); void updateWater();
void validateRectTerr(SDL_Rect * val, const SDL_Rect * ext); //terrainRect helper void validateRectTerr(SDL_Rect * val, const SDL_Rect * ext); //terrainRect helper
static ui8 getDir(const int3 & a, const int3 & b); //returns direction number in range 0 - 7 (0 is left top, clockwise) [direction: form a to b] static ui8 getDir(const int3 & a, const int3 & b); //returns direction number in range 0 - 7 (0 is left top, clockwise) [direction: form a to b]
/// determines if the map is ready to handle new hero movement (not available during fading animations)
bool canStartHeroMovement();
void discardWorldViewCache(); void discardWorldViewCache();

View File

@ -18,6 +18,7 @@
#include "../Graphics.h" #include "../Graphics.h"
#include "../mapHandler.h" #include "../mapHandler.h"
#include "../gui/CAnimation.h"
#include "../gui/CCursorHandler.h" #include "../gui/CCursorHandler.h"
#include "../gui/CGuiHandler.h" #include "../gui/CGuiHandler.h"
#include "../gui/SDL_Extensions.h" #include "../gui/SDL_Extensions.h"
@ -61,7 +62,10 @@ CAdvMapInt *adventureInt;
CTerrainRect::CTerrainRect() CTerrainRect::CTerrainRect()
: curHoveredTile(-1,-1,-1), currentPath(nullptr) : fadeSurface(nullptr),
fadeAnim(new CFadeAnimation()),
curHoveredTile(-1,-1,-1),
currentPath(nullptr)
{ {
tilesw=(ADVOPT.advmapW+31)/32; tilesw=(ADVOPT.advmapW+31)/32;
tilesh=(ADVOPT.advmapH+31)/32; tilesh=(ADVOPT.advmapH+31)/32;
@ -73,6 +77,13 @@ CTerrainRect::CTerrainRect()
addUsedEvents(LCLICK | RCLICK | HOVER | MOVE); addUsedEvents(LCLICK | RCLICK | HOVER | MOVE);
} }
CTerrainRect::~CTerrainRect()
{
if (fadeSurface)
SDL_FreeSurface(fadeSurface);
delete fadeAnim;
}
void CTerrainRect::deactivate() void CTerrainRect::deactivate()
{ {
CIntObject::deactivate(); CIntObject::deactivate();
@ -273,7 +284,13 @@ void CTerrainRect::show(SDL_Surface * to)
if (ADVOPT.smoothMove) if (ADVOPT.smoothMove)
info.movement = int3(moveX, moveY, 0); info.movement = int3(moveX, moveY, 0);
CGI->mh->drawTerrainRectNew(to, &info); lastRedrawStatus = CGI->mh->drawTerrainRectNew(to, &info);
if (fadeAnim->isFading())
{
Rect r(pos);
fadeAnim->update();
fadeAnim->draw(to, nullptr, &r);
}
if (currentPath/* && adventureInt->position.z==currentPath->startPos().z*/) //drawing path if (currentPath/* && adventureInt->position.z==currentPath->startPos().z*/) //drawing path
{ {
@ -298,6 +315,14 @@ void CTerrainRect::showAll(SDL_Surface * to)
} }
} }
void CTerrainRect::showAnim(SDL_Surface * to)
{
if (fadeAnim->isFading())
show(to);
else if (lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
show(to); // currently the same; maybe we should pass some flag to map handler so it redraws ONLY tiles that need redraw instead of full
}
int3 CTerrainRect::whichTileIsIt(const int & x, const int & y) int3 CTerrainRect::whichTileIsIt(const int & x, const int & y)
{ {
int3 ret; int3 ret;
@ -326,6 +351,24 @@ int3 CTerrainRect::tileCountOnScreen()
} }
} }
void CTerrainRect::fadeFromCurrentView()
{
if (!ADVOPT.screenFading)
return;
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
if (!fadeSurface)
fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h);
SDL_BlitSurface(screen, &pos, fadeSurface, nullptr);
fadeAnim->init(CFadeAnimation::EMode::OUT, fadeSurface);
}
bool CTerrainRect::needsAnimUpdate()
{
return fadeAnim->isFading() || lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED;
}
void CResDataBar::clickRight(tribool down, bool previousState) void CResDataBar::clickRight(tribool down, bool previousState)
{ {
} }
@ -647,7 +690,7 @@ void CAdvMapInt::fsleepWake()
void CAdvMapInt::fmoveHero() void CAdvMapInt::fmoveHero()
{ {
const CGHeroInstance *h = curHero(); const CGHeroInstance *h = curHero();
if (!h || !terrain.currentPath) if (!h || !terrain.currentPath || !CGI->mh->canStartHeroMovement())
return; return;
LOCPLINT->moveHero(h, *terrain.currentPath); LOCPLINT->moveHero(h, *terrain.currentPath);
@ -917,6 +960,13 @@ void CAdvMapInt::show(SDL_Surface * to)
updateScreen=false; updateScreen=false;
LOCPLINT->cingconsole->showAll(to); LOCPLINT->cingconsole->showAll(to);
} }
else if (terrain.needsAnimUpdate())
{
terrain.showAnim(to);
for(int i=0;i<4;i++)
blitAt(gems[i]->ourImages[LOCPLINT->playerID.getNum()].bitmap,ADVOPT.gemX[i],ADVOPT.gemY[i],to);
}
infoBar.show(to); infoBar.show(to);
statusbar.showAll(to); statusbar.showAll(to);
} }
@ -928,10 +978,15 @@ void CAdvMapInt::selectionChanged()
select(to); select(to);
} }
void CAdvMapInt::centerOn(int3 on) void CAdvMapInt::centerOn(int3 on, bool fade /* = false */)
{ {
bool switchedLevels = on.z != position.z; bool switchedLevels = on.z != position.z;
if (fade)
{
terrain.fadeFromCurrentView();
}
switch (mode) switch (mode)
{ {
default: default:
@ -962,9 +1017,9 @@ void CAdvMapInt::centerOn(int3 on)
terrain.redraw(); terrain.redraw();
} }
void CAdvMapInt::centerOn(const CGObjectInstance *obj) void CAdvMapInt::centerOn(const CGObjectInstance *obj, bool fade /* = false */)
{ {
centerOn(obj->getSightCenter()); centerOn(obj->getSightCenter(), fade);
} }
void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
@ -1112,6 +1167,9 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
if(k < 0 || k > 8) if(k < 0 || k > 8)
return; return;
if (!CGI->mh->canStartHeroMovement())
return;
int3 dir = directions[k]; int3 dir = directions[k];
if(!isActive() || LOCPLINT->ctrlPressed())//ctrl makes arrow move screen, not hero if(!isActive() || LOCPLINT->ctrlPressed())//ctrl makes arrow move screen, not hero
@ -1381,7 +1439,8 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
{ {
if (terrain.currentPath && terrain.currentPath->endPos() == mapPos)//we'll be moving if (terrain.currentPath && terrain.currentPath->endPos() == mapPos)//we'll be moving
{ {
LOCPLINT->moveHero(currentHero,*terrain.currentPath); if (CGI->mh->canStartHeroMovement())
LOCPLINT->moveHero(currentHero,*terrain.currentPath);
return; return;
} }
else/* if(mp.z == currentHero->pos.z)*/ //remove old path and find a new one if we clicked on the map level on which hero is present else/* if(mp.z == currentHero->pos.z)*/ //remove old path and find a new one if we clicked on the map level on which hero is present

View File

@ -15,6 +15,8 @@ class CGTownInstance;
class CHeroWindow; class CHeroWindow;
class CSpell; class CSpell;
class IShipyard; class IShipyard;
enum class EMapAnimRedrawStatus;
class CFadeAnimation;
/*****************************/ /*****************************/
@ -48,12 +50,16 @@ public:
class CTerrainRect class CTerrainRect
: public CIntObject : public CIntObject
{ {
SDL_Surface * fadeSurface;
EMapAnimRedrawStatus lastRedrawStatus;
CFadeAnimation * fadeAnim;
public: public:
int tilesw, tilesh; //width and height of terrain to blit in tiles int tilesw, tilesh; //width and height of terrain to blit in tiles
int3 curHoveredTile; int3 curHoveredTile;
int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels) int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels)
CTerrainRect(); CTerrainRect();
virtual ~CTerrainRect();
CGPath * currentPath; CGPath * currentPath;
void deactivate(); void deactivate();
void clickLeft(tribool down, bool previousState); void clickLeft(tribool down, bool previousState);
@ -62,11 +68,15 @@ public:
void mouseMoved (const SDL_MouseMotionEvent & sEvent); void mouseMoved (const SDL_MouseMotionEvent & sEvent);
void show(SDL_Surface * to); void show(SDL_Surface * to);
void showAll(SDL_Surface * to); void showAll(SDL_Surface * to);
void showAnim(SDL_Surface * to);
void showPath(const SDL_Rect * extRect, SDL_Surface * to); void showPath(const SDL_Rect * extRect, SDL_Surface * to);
int3 whichTileIsIt(const int & x, const int & y); //x,y are cursor position int3 whichTileIsIt(const int & x, const int & y); //x,y are cursor position
int3 whichTileIsIt(); //uses current cursor pos int3 whichTileIsIt(); //uses current cursor pos
/// @returns number of visible tiles on screen respecting current map scaling /// @returns number of visible tiles on screen respecting current map scaling
int3 tileCountOnScreen(); int3 tileCountOnScreen();
/// animates view by caching current surface and crossfading it with normal screen
void fadeFromCurrentView();
bool needsAnimUpdate();
}; };
/// Resources bar which shows information about how many gold, crystals,... you have /// Resources bar which shows information about how many gold, crystals,... you have
@ -176,8 +186,8 @@ public:
void select(const CArmedInstance *sel, bool centerView = true); void select(const CArmedInstance *sel, bool centerView = true);
void selectionChanged(); void selectionChanged();
void centerOn(int3 on); void centerOn(int3 on, bool fade = false);
void centerOn(const CGObjectInstance *obj); void centerOn(const CGObjectInstance *obj, bool fade = false);
int3 verifyPos(int3 ver); int3 verifyPos(int3 ver);
void handleRightClick(std::string text, tribool down); void handleRightClick(std::string text, tribool down);
void keyPressed(const SDL_KeyboardEvent & key); void keyPressed(const SDL_KeyboardEvent & key);

View File

@ -4,7 +4,7 @@
{ {
"resolution": { "x": 800, "y": 600 }, "resolution": { "x": 800, "y": 600 },
"InGameConsole": { "maxInputPerLine": 60, "maxOutputPerLine": 39 }, "InGameConsole": { "maxInputPerLine": 60, "maxOutputPerLine": 39 },
"AdvMap": { "x": 7, "y": 7, "width": 594, "height": 546, "smoothMove": 1, "puzzleSepia": 1 }, "AdvMap": { "x": 7, "y": 7, "width": 594, "height": 546, "smoothMove": 1, "puzzleSepia": 1, "objectFading" : 1, "screenFading" : 1 },
"InfoBox": { "x": 605, "y": 389 }, "InfoBox": { "x": 605, "y": 389 },
"gem0": { "x": 6, "y": 508, "graphic": "agemLL.def" }, "gem0": { "x": 6, "y": 508, "graphic": "agemLL.def" },
"gem1": { "x": 556, "y": 508, "graphic": "agemLR.def" }, "gem1": { "x": 556, "y": 508, "graphic": "agemLR.def" },

View File

@ -228,6 +228,8 @@ void config::CConfigHandler::init()
current->ac.advmapH = g["AdvMap"]["height"].Float(); current->ac.advmapH = g["AdvMap"]["height"].Float();
current->ac.smoothMove = g["AdvMap"]["smoothMove"].Float(); current->ac.smoothMove = g["AdvMap"]["smoothMove"].Float();
current->ac.puzzleSepia = g["AdvMap"]["puzzleSepia"].Float(); current->ac.puzzleSepia = g["AdvMap"]["puzzleSepia"].Float();
current->ac.screenFading = g["AdvMap"]["screenFading"].isNull() ? true : g["AdvMap"]["screenFading"].Float(); // enabled by default
current->ac.objectFading = g["AdvMap"]["objectFading"].isNull() ? true : g["AdvMap"]["objectFading"].Float();
current->ac.infoboxX = g["InfoBox"]["x"].Float(); current->ac.infoboxX = g["InfoBox"]["x"].Float();
current->ac.infoboxY = g["InfoBox"]["y"].Float(); current->ac.infoboxY = g["InfoBox"]["y"].Float();

View File

@ -133,6 +133,8 @@ namespace config
int advmapX, advmapY, advmapW, advmapH; int advmapX, advmapY, advmapW, advmapH;
bool smoothMove; bool smoothMove;
bool puzzleSepia; bool puzzleSepia;
bool screenFading;
bool objectFading;
//general properties //general properties
std::string mainGraphic; std::string mainGraphic;
std::string worldViewGraphic; std::string worldViewGraphic;