From 4d510c172da10ada03bb83495a92d779edd7988e Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sun, 6 Nov 2016 21:39:32 +0300 Subject: [PATCH] Terrain drawing converted to CAnimation. --- client/gui/CAnimation.cpp | 48 +++++- client/gui/CAnimation.h | 4 + client/mapHandler.cpp | 317 ++++++++++++++------------------------ client/mapHandler.h | 36 ++--- 4 files changed, 178 insertions(+), 227 deletions(-) diff --git a/client/gui/CAnimation.cpp b/client/gui/CAnimation.cpp index 55038207c..36780af89 100644 --- a/client/gui/CAnimation.cpp +++ b/client/gui/CAnimation.cpp @@ -96,8 +96,11 @@ public: int width() const override; int height() const override; + void horizontalFlip() override; void verticalFlip() override; + void shiftPalette(int from, int howMany) override; + friend class SDLImageLoader; }; @@ -149,8 +152,11 @@ public: int width() const override; int height() const override; + void horizontalFlip() override; void verticalFlip() override; + void shiftPalette(int from, int howMany) override; + friend class CompImageLoader; }; @@ -849,6 +855,17 @@ int SDLImage::height() const return fullSize.y; } +void SDLImage::horizontalFlip() +{ + SDL_Surface * flipped = CSDL_Ext::horizontalFlip(surf); + + SDL_FreeSurface(surf); + + surf = flipped; + + margins.y = fullSize.y - surf->h - margins.y; +} + void SDLImage::verticalFlip() { SDL_Surface * flipped = CSDL_Ext::verticalFlip(surf); @@ -860,6 +877,23 @@ void SDLImage::verticalFlip() margins.x = fullSize.x - surf->w - margins.x; } +void SDLImage::shiftPalette(int from, int howMany) +{ + //works with at most 16 colors, if needed more -> increase values + assert(howMany < 16); + + if(surf->format->palette) + { + SDL_Color palette[16]; + + for(int i=0; iformat->palette->colors[from + i]; + } + SDL_SetColors(surf, palette, from, howMany); + } +} + SDLImage::~SDLImage() { SDL_FreeSurface(surf); @@ -1091,7 +1125,7 @@ void CompImage::playerColored(PlayerColor player) void CompImage::setFlagColor(PlayerColor player) { - logGlobal->error("CompImage::setFlagColor is not implemented"); + logAnim->error("CompImage::setFlagColor is not implemented"); } int CompImage::width() const @@ -1111,9 +1145,19 @@ CompImage::~CompImage() delete [] palette; } +void CompImage::horizontalFlip() +{ + logAnim->error("CompImage::horizontalFlip is not implemented"); +} + void CompImage::verticalFlip() { - logGlobal->error("CompImage::verticalFlip is not implemented"); + logAnim->error("CompImage::verticalFlip is not implemented"); +} + +void CompImage::shiftPalette(int from, int howMany) +{ + logAnim->error("CompImage::shiftPalette is not implemented"); } diff --git a/client/gui/CAnimation.h b/client/gui/CAnimation.h index 970277b62..bc6f9bab4 100644 --- a/client/gui/CAnimation.h +++ b/client/gui/CAnimation.h @@ -45,6 +45,10 @@ public: virtual int width() const=0; virtual int height() const=0; + //only indexed bitmaps, 16 colors maximum + virtual void shiftPalette(int from, int howMany) = 0; + + virtual void horizontalFlip() = 0; virtual void verticalFlip() = 0; IImage(); diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index afbe255c6..e452b71ce 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -32,50 +32,6 @@ #define ADVOPT (conf.go()->ac) -std::string nameFromType (int typ) -{ - switch(ETerrainType(typ)) - { - case ETerrainType::DIRT: - return std::string("DIRTTL.DEF"); - - case ETerrainType::SAND: - return std::string("SANDTL.DEF"); - - case ETerrainType::GRASS: - return std::string("GRASTL.DEF"); - - case ETerrainType::SNOW: - return std::string("SNOWTL.DEF"); - - case ETerrainType::SWAMP: - return std::string("SWMPTL.DEF"); - - case ETerrainType::ROUGH: - return std::string("ROUGTL.DEF"); - - case ETerrainType::SUBTERRANEAN: - return std::string("SUBBTL.DEF"); - - case ETerrainType::LAVA: - return std::string("LAVATL.DEF"); - - case ETerrainType::WATER: - return std::string("WATRTL.DEF"); - - case ETerrainType::ROCK: - return std::string("ROCKTL.DEF"); - - case ETerrainType::BORDER: - //TODO use me - break; - default: - //TODO do something here - break; - } - return std::string(); -} - static bool objectBlitOrderSorter(const TerrainTileObject & a, const TerrainTileObject & b) { return CMapHandler::compareObjectBlitOrder(a.obj, b.obj); @@ -184,31 +140,81 @@ EMapAnimRedrawStatus CMapHandler::drawTerrainRectNew(SDL_Surface * targetSurface return hasActiveFade ? EMapAnimRedrawStatus::REDRAW_REQUESTED : EMapAnimRedrawStatus::OK; } -void CMapHandler::roadsRiverTerrainInit() +void CMapHandler::initTerrainGraphics() { - //initializing road's and river's DefHandlers + static const std::vector TERRAIN_FILES = + { + "DIRTTL", + "SANDTL", + "GRASTL", + "SNOWTL", + "SWMPTL", - roadDefs.push_back(CDefHandler::giveDefEss("dirtrd.def")); - roadDefs.push_back(CDefHandler::giveDefEss("gravrd.def")); - roadDefs.push_back(CDefHandler::giveDefEss("cobbrd.def")); - staticRiverDefs.push_back(CDefHandler::giveDefEss("clrrvr.def")); - staticRiverDefs.push_back(CDefHandler::giveDefEss("icyrvr.def")); - staticRiverDefs.push_back(CDefHandler::giveDefEss("mudrvr.def")); - staticRiverDefs.push_back(CDefHandler::giveDefEss("lavrvr.def")); - for(auto & elem : staticRiverDefs) + "ROUGTL", + "SUBBTL", + "LAVATL", + "WATRTL", + "ROCKTL" + }; + + static const std::vector ROAD_FILES = { - for(size_t h=0; h < elem->ourImages.size(); ++h) - { - CSDL_Ext::alphaTransform(elem->ourImages[h].bitmap); - } - } - for(auto & elem : roadDefs) + "dirtrd", + "gravrd", + "cobbrd" + }; + + static const std::vector RIVER_FILES = { - for(size_t h=0; h < elem->ourImages.size(); ++h) + "clrrvr", + "icyrvr", + "mudrvr", + "lavrvr" + }; + + auto loadFlipped = [this](int types, TFlippedAnimations & animation, TFlippedCache & cache, const std::vector & files) + { + animation.resize(types); + cache.resize(types); + + //no rotation and basic setup + for(int i = 0; i < types; i++) { - CSDL_Ext::alphaTransform(elem->ourImages[h].bitmap); + animation[i][0] = make_unique(files[i]); + animation[i][0]->preload(); + const size_t views = animation[i][0]->size(0); + cache[i].resize(views); + + for(int j = 0; j < views; j++) + cache[i][j][0] = animation[i][0]->getImage(j); } - } + + for(int rotation = 1; rotation < 4; rotation++) + { + for(int i = 0; i < types; i++) + { + animation[i][rotation] = make_unique(files[i]); + animation[i][rotation]->preload(); + const size_t views = animation[i][rotation]->size(0); + + for(int j = 0; j < views; j++) + { + IImage * image = animation[i][rotation]->getImage(j); + + if(rotation == 2 || rotation == 3) + image->horizontalFlip(); + if(rotation == 1 || rotation == 3) + image->verticalFlip(); + + cache[i][j][rotation] = image; + } + } + } + }; + + loadFlipped(GameConstants::TERRAIN_TYPES, terrainAnimations, terrainImages, TERRAIN_FILES); + loadFlipped(3, roadAnimations, roadImages, ROAD_FILES); + loadFlipped(4, riverAnimations, riverImages, RIVER_FILES); // Create enough room for the whole map and its frame @@ -224,7 +230,7 @@ void CMapHandler::roadsRiverTerrainInit() } } -void CMapHandler::borderAndTerrainBitmapInit() +void CMapHandler::initBorderGraphics() { egdeImages.resize(egdeAnimation->size(0)); for(size_t i = 0; i < egdeImages.size(); i++) @@ -276,17 +282,6 @@ void CMapHandler::borderAndTerrainBitmapInit() } } } - - terrainGraphics.resize(10); - for (int i = 0; i < 10 ; i++) - { - CDefHandler *hlp = CDefHandler::giveDef(nameFromType(i)); - terrainGraphics[i].resize(hlp->ourImages.size()); - hlp->notFreeImgs = true; - for(size_t j=0; j < hlp->ourImages.size(); ++j) - terrainGraphics[i][j] = hlp->ourImages[j].bitmap; - delete hlp; - } } void CMapHandler::initObjectRects() @@ -386,12 +381,11 @@ void CMapHandler::init() offsetY = (mapH - (2*frameH+1)*32)/2; prepareFOWDefs(); - roadsRiverTerrainInit(); //road's and river's DefHandlers; and simple values initialization - borderAndTerrainBitmapInit(); - logGlobal->infoStream()<<"\tPreparing FoW, roads, rivers,borders: "<infoStream()<<"\tPreparing FoW, terrain, roads, rivers, borders: "<infoStream()<<"\tMaking object rects: "<w, sourceSurf->h); - if (alphaBlit) - CSDL_Ext::getBlitterWithRotationAndAlpha(targetSurf)(sourceSurf, sourceRect2, targetSurf, *destRect, rotationInfo); - else - CSDL_Ext::getBlitterWithRotation(targetSurf)(sourceSurf, sourceRect2, targetSurf, *destRect, rotationInfo); - } - else - { - if (alphaBlit) - CSDL_Ext::getBlitterWithRotationAndAlpha(targetSurf)(sourceSurf, *sourceRect, targetSurf, *destRect, rotationInfo); - else - CSDL_Ext::getBlitterWithRotation(targetSurf)(sourceSurf, *sourceRect, targetSurf, *destRect, rotationInfo); - } - } - else - { - if (alphaBlit) - CSDL_Ext::blit8bppAlphaTo24bpp(sourceSurf, sourceRect, targetSurf, destRect); - else - CSDL_Ext::blitSurface(sourceSurf, sourceRect, targetSurf, destRect); - } -} - void CMapHandler::CMapNormalBlitter::drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const { source->draw(targetSurf, destRect, sourceRect); @@ -571,54 +536,6 @@ void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos() topTile.y = parent->sizes.y - tileCount.y; } -void CMapHandler::CMapWorldViewBlitter::drawScaledRotatedElement(EMapCacheType type, SDL_Surface * baseSurf, SDL_Surface * targetSurf, ui8 rotation, - float scale, SDL_Rect * dstRect, SDL_Rect * srcRect /*= nullptr*/) const -{ - auto key = parent->cache.genKey((intptr_t)baseSurf, rotation); - auto scaledSurf = parent->cache.requestWorldViewCache(type, key); - if (scaledSurf) // blitting from cache - { - if (srcRect) - { - dstRect->w = srcRect->w; - dstRect->h = srcRect->h; - } - CSDL_Ext::blitSurface(scaledSurf, srcRect, targetSurf, dstRect); - } - else // creating new - { - auto baseSurfRotated = CSDL_Ext::newSurface(baseSurf->w, baseSurf->h); - if (!baseSurfRotated) - return; - Rect baseRect(0, 0, baseSurf->w, baseSurf->h); - - CSDL_Ext::getBlitterWithRotationAndAlpha(targetSurf)(baseSurf, baseRect, baseSurfRotated, baseRect, rotation); - - SDL_Surface * scaledSurf2 = CSDL_Ext::scaleSurfaceFast(baseSurfRotated, baseSurf->w * scale, baseSurf->h * scale); - - CSDL_Ext::blitSurface(scaledSurf2, srcRect, targetSurf, dstRect); - parent->cache.cacheWorldViewEntry(type, key, scaledSurf2); - SDL_FreeSurface(baseSurfRotated); - } -} - -void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect, bool alphaBlit, ui8 rotationInfo) const -{ - if (rotationInfo != 0) - { - drawScaledRotatedElement(cacheType, sourceSurf, targetSurf, rotationInfo, info->scale, destRect, sourceRect); - } - else - { - auto scaledSurf = parent->cache.requestWorldViewCacheOrCreate(cacheType, (intptr_t) sourceSurf, sourceSurf, info->scale); - - if (alphaBlit) - CSDL_Ext::blit8bppAlphaTo24bpp(scaledSurf, sourceRect, targetSurf, destRect); - else - CSDL_Ext::blitSurface(scaledSurf, sourceRect, targetSurf, destRect); - } -} - void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const { SDL_Surface * scaledSurf = parent->cache.requestWorldViewCacheOrCreate(cacheType, (intptr_t) source, source, info->scale); @@ -710,7 +627,9 @@ void CMapHandler::CMapBlitter::drawTileTerrain(SDL_Surface * targetSurf, const T { Rect destRect(realTileRect); - drawElement(EMapCacheType::TERRAIN, parent->terrainGraphics[tinfo.terType][tinfo.terView], nullptr, targetSurf, &destRect, false, tinfo.extTileFlags % 4); + ui8 rotation = tinfo.extTileFlags % 4; + + drawElement(EMapCacheType::TERRAIN, parent->terrainImages[tinfo.terType][tinfo.terView][rotation], nullptr, targetSurf, &destRect); } void CMapHandler::CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo) @@ -732,7 +651,6 @@ void CMapHandler::CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo) defaultTileRect = Rect(0, 0, tileSize, tileSize); calculateWorldViewCameraPos(); - } SDL_Rect CMapHandler::CMapWorldViewBlitter::clip(SDL_Surface * targetSurf) const @@ -874,26 +792,28 @@ void CMapHandler::CMapBlitter::drawRoad(SDL_Surface * targetSurf, const TerrainT { if (tinfoUpper && tinfoUpper->roadType != ERoadType::NO_ROAD) { + ui8 rotation = (tinfoUpper->extTileFlags >> 4) % 4; Rect source(0, tileSize / 2, tileSize, tileSize / 2); Rect dest(realPos.x, realPos.y, tileSize, tileSize / 2); - drawElement(EMapCacheType::ROADS, parent->roadDefs[tinfoUpper->roadType - 1]->ourImages[tinfoUpper->roadDir].bitmap, - &source, targetSurf, &dest, true, (tinfoUpper->extTileFlags >> 4) % 4); + drawElement(EMapCacheType::ROADS, parent->roadImages[tinfoUpper->roadType - 1][tinfoUpper->roadDir][rotation], + &source, targetSurf, &dest); } if(tinfo.roadType != ERoadType::NO_ROAD) //print road from this tile { + ui8 rotation = (tinfo.extTileFlags >> 4) % 4; Rect source(0, 0, tileSize, halfTileSizeCeil); Rect dest(realPos.x, realPos.y + tileSize / 2, tileSize, tileSize / 2); - drawElement(EMapCacheType::ROADS, parent->roadDefs[tinfo.roadType - 1]->ourImages[tinfo.roadDir].bitmap, - &source, targetSurf, &dest, true, (tinfo.extTileFlags >> 4) % 4); + drawElement(EMapCacheType::ROADS, parent->roadImages[tinfo.roadType - 1][tinfo.roadDir][rotation], + &source, targetSurf, &dest); } } void CMapHandler::CMapBlitter::drawRiver(SDL_Surface * targetSurf, const TerrainTile & tinfo) const { Rect destRect(realTileRect); - drawElement(EMapCacheType::RIVERS, parent->staticRiverDefs[tinfo.riverType-1]->ourImages[tinfo.riverDir].bitmap, - nullptr, targetSurf, &destRect, true, (tinfo.extTileFlags >> 2) % 4); + ui8 rotation = (tinfo.extTileFlags >> 2) % 4; + drawElement(EMapCacheType::RIVERS, parent->riverImages[tinfo.riverType-1][tinfo.riverDir][rotation],nullptr, targetSurf, &destRect); } void CMapHandler::CMapBlitter::drawFow(SDL_Surface * targetSurf) const @@ -1380,44 +1300,46 @@ 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 -{ - //works with at most 16 colors, if needed more -> increase values - assert(howMany < 16); - SDL_Color palette[16]; - - for(int i=0; iformat->palette->colors[from + i]; - } - SDL_SetColors(img,palette,from,howMany); -} - void CMapHandler::updateWater() //shift colors in palettes of water tiles { - for(auto & elem : terrainGraphics[7]) + for(auto & elem : terrainImages[7]) { - shiftColors(elem,246, 9); + for(IImage * img : elem) + img->shiftPalette(246, 9); } - for(auto & elem : terrainGraphics[8]) + + for(auto & elem : terrainImages[8]) { - shiftColors(elem,229, 12); - shiftColors(elem,242, 14); + for(IImage * img : elem) + { + img->shiftPalette(229, 12); + img->shiftPalette(242, 14); + } } - for(auto & elem : staticRiverDefs[0]->ourImages) + + for(auto & elem : riverImages[0]) { - shiftColors(elem.bitmap,183, 12); - shiftColors(elem.bitmap,195, 6); + for(IImage * img : elem) + { + img->shiftPalette(183, 12); + img->shiftPalette(195, 6); + } } - for(auto & elem : staticRiverDefs[2]->ourImages) + + for(auto & elem : riverImages[2]) { - shiftColors(elem.bitmap,228, 12); - shiftColors(elem.bitmap,183, 6); - shiftColors(elem.bitmap,240, 6); + for(IImage * img : elem) + { + img->shiftPalette(228, 12); + img->shiftPalette(183, 6); + img->shiftPalette(240, 6); + } } - for(auto & elem : staticRiverDefs[3]->ourImages) + + for(auto & elem : riverImages[3]) { - shiftColors(elem.bitmap,240, 9); + for(IImage * img : elem) + img->shiftPalette(240, 9); } } @@ -1427,23 +1349,10 @@ CMapHandler::~CMapHandler() delete worldViewBlitter; delete puzzleViewBlitter; - for(auto & elem : roadDefs) - delete elem; - - for(auto & elem : staticRiverDefs) - delete elem; - - for(auto & elem : terrainGraphics) - { - for(int j=0; j < elem.size(); ++j) - SDL_FreeSurface(elem[j]); - } - for (auto & elem : fadeAnims) { delete elem.second.second; } - terrainGraphics.clear(); } CMapHandler::CMapHandler() diff --git a/client/mapHandler.h b/client/mapHandler.h index 7b156b1c3..95787c3e2 100644 --- a/client/mapHandler.h +++ b/client/mapHandler.h @@ -210,10 +210,6 @@ class CMapHandler const MapDrawingInfo * info; // data for drawing passed from outside /// general drawing method, called internally by more specialized ones - virtual void drawElement(EMapCacheType cacheType, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, - SDL_Surface * targetSurf, SDL_Rect * destRect, bool alphaBlit = false, ui8 rotationInfo = 0u) const = 0; - - //todo: support rotation virtual void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const = 0; // first drawing pass @@ -277,11 +273,7 @@ class CMapHandler class CMapNormalBlitter : public CMapBlitter { protected: - void drawElement(EMapCacheType cacheType, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, - SDL_Surface * targetSurf, SDL_Rect * destRect, bool alphaBlit = false, ui8 rotationInfo = 0u) const override; - void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override; - void drawTileOverlay(SDL_Surface * targetSurf,const TerrainTile2 & tile) const override {} void init(const MapDrawingInfo * info) override; SDL_Rect clip(SDL_Surface * targetSurf) const override; @@ -295,11 +287,7 @@ class CMapHandler private: IImage * objectToIcon(Obj id, si32 subId, PlayerColor owner) const; protected: - void drawElement(EMapCacheType cacheType, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, - SDL_Surface * targetSurf, SDL_Rect * destRect, bool alphaBlit = false, ui8 rotationInfo = 0u) const override; - void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override; - void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override; void drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override; void drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const override; @@ -307,11 +295,7 @@ class CMapHandler void drawOverlayEx(SDL_Surface * targetSurf) override; void init(const MapDrawingInfo * info) override; SDL_Rect clip(SDL_Surface * targetSurf) const override; - ui8 getPhaseShift(const CGObjectInstance *object) const override { return 0u; } - - void drawScaledRotatedElement(EMapCacheType type, SDL_Surface * baseSurf, SDL_Surface * targetSurf, ui8 rotation, - float scale, SDL_Rect * dstRect, SDL_Rect * srcRect = nullptr) const; void calculateWorldViewCameraPos(); public: CMapWorldViewBlitter(CMapHandler * parent); @@ -344,8 +328,8 @@ class CMapHandler bool startObjectFade(TerrainTileObject & obj, bool in, int3 pos); void initObjectRects(); - void borderAndTerrainBitmapInit(); - void roadsRiverTerrainInit(); + void initBorderGraphics(); + void initTerrainGraphics(); void prepareFOWDefs(); public: PseudoV< PseudoV< PseudoV > > ttiles; //informations about map tiles @@ -367,9 +351,19 @@ public: int offsetX; int offsetY; - std::vector > terrainGraphics; // [terrain id] [view type] - std::vector roadDefs; - std::vector staticRiverDefs; + //terrain graphics + + typedef std::vector, 4>> TFlippedAnimations; //[type, rotation] + typedef std::vector>> 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] //Fog of War cache (not owned) std::vector FoWfullHide;