diff --git a/client/CBitmapHandler.cpp b/client/CBitmapHandler.cpp index be1edb09d..3f4ff56ae 100644 --- a/client/CBitmapHandler.cpp +++ b/client/CBitmapHandler.cpp @@ -167,6 +167,10 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna { CSDL_Ext::setDefaultColorKeyPresize(ret); } + else if (ret->format->Amask) + { + SDL_SetSurfaceBlendMode(ret, SDL_BLENDMODE_BLEND); + } else // always set { CSDL_Ext::setDefaultColorKey(ret); diff --git a/client/Graphics.cpp b/client/Graphics.cpp index 6b3de836b..48a714dc0 100644 --- a/client/Graphics.cpp +++ b/client/Graphics.cpp @@ -3,7 +3,6 @@ #include "../lib/filesystem/Filesystem.h" #include "../lib/filesystem/CBinaryReader.h" -#include "CDefHandler.h" #include "gui/SDL_Extensions.h" #include "gui/CAnimation.h" #include @@ -130,18 +129,9 @@ Graphics::Graphics() { #if 0 - #define GET_DATA(TYPE,DESTINATION,FUNCTION_TO_GET) \ - (std::bind(&setData,&DESTINATION,FUNCTION_TO_GET)) - - #define GET_DEF_ESS(DESTINATION, DEF_NAME) \ - (GET_DATA \ - (CDefEssential*,DESTINATION,\ - std::function(std::bind(CDefHandler::giveDefEss,DEF_NAME)))) - std::vector tasks; //preparing list of graphics to load tasks += std::bind(&Graphics::loadFonts,this); tasks += std::bind(&Graphics::loadPaletteAndColors,this); - tasks += std::bind(&Graphics::loadHeroFlags,this); tasks += std::bind(&Graphics::initializeBattleGraphics,this); tasks += std::bind(&Graphics::loadErmuToPicture,this); tasks += std::bind(&Graphics::initializeImageLists,this); @@ -151,7 +141,6 @@ Graphics::Graphics() #else loadFonts(); loadPaletteAndColors(); - loadHeroFlags(); initializeBattleGraphics(); loadErmuToPicture(); initializeImageLists(); @@ -165,168 +154,119 @@ void Graphics::load() heroMoveArrows = std::make_shared("ADAG"); heroMoveArrows->preload(); - loadHeroAnims(); + loadHeroAnimations(); + loadHeroFlagAnimations(); + loadFogOfWar(); } -void Graphics::loadHeroAnims() +void Graphics::loadHeroAnimations() { - //first - group number to be rotated1, second - group number after rotation1 - std::vector > rotations = + for(auto & elem : CGI->heroh->classes.heroClasses) + { + for (auto & templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->id)->getTemplates()) + { + if (!heroAnimations.count(templ.animationFile)) + heroAnimations[templ.animationFile] = loadHeroAnimation(templ.animationFile); + } + } + + boatAnimations[0] = loadHeroAnimation("AB01_.DEF"); + boatAnimations[1] = loadHeroAnimation("AB02_.DEF"); + boatAnimations[2] = loadHeroAnimation("AB03_.DEF"); + + + mapObjectAnimations["AB01_.DEF"] = boatAnimations[0]; + mapObjectAnimations["AB02_.DEF"] = boatAnimations[1]; + mapObjectAnimations["AB03_.DEF"] = boatAnimations[2]; +} +void Graphics::loadHeroFlagAnimations() +{ + static const std::vector HERO_FLAG_ANIMATIONS = + { + "AF00", "AF01","AF02","AF03", + "AF04", "AF05","AF06","AF07" + }; + + static const std::vector< std::vector > BOAT_FLAG_ANIMATIONS = + { + { + "ABF01L", "ABF01G", "ABF01R", "ABF01D", + "ABF01B", "ABF01P", "ABF01W", "ABF01K" + }, + { + "ABF02L", "ABF02G", "ABF02R", "ABF02D", + "ABF02B", "ABF02P", "ABF02W", "ABF02K" + }, + { + "ABF03L", "ABF03G", "ABF03R", "ABF03D", + "ABF03B", "ABF03P", "ABF03W", "ABF03K" + } + }; + + for(const auto & name : HERO_FLAG_ANIMATIONS) + heroFlagAnimations.push_back(loadHeroFlagAnimation(name)); + + for(int i = 0; i < BOAT_FLAG_ANIMATIONS.size(); i++) + for(const auto & name : BOAT_FLAG_ANIMATIONS[i]) + boatFlagAnimations[i].push_back(loadHeroFlagAnimation(name)); +} + +std::shared_ptr Graphics::loadHeroFlagAnimation(const std::string & name) +{ + //first - group number to be rotated, second - group number after rotation + static const std::vector > rotations = { {6,10}, {7,11}, {8,12}, {1,13}, {2,14}, {3,15} }; - for(auto & elem : CGI->heroh->classes.heroClasses) + std::shared_ptr anim = std::make_shared(name); + anim->preload(); + + for(const auto & rotation : rotations) { - for (auto & templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->id)->getTemplates()) + const int sourceGroup = rotation.first; + const int targetGroup = rotation.second; + + for(size_t frame = 0; frame < anim->size(sourceGroup); ++frame) { - if (!heroAnims.count(templ.animationFile)) - heroAnims[templ.animationFile] = loadHeroAnim(templ.animationFile, rotations); + anim->duplicateImage(sourceGroup, frame, targetGroup); + + IImage * image = anim->getImage(frame, targetGroup); + image->verticalFlip(); } } - boatAnims.push_back(loadHeroAnim("AB01_.DEF", rotations)); - boatAnims.push_back(loadHeroAnim("AB02_.DEF", rotations)); - boatAnims.push_back(loadHeroAnim("AB03_.DEF", rotations)); -} - -CDefEssential * Graphics::loadHeroAnim( const std::string &name, const std::vector > &rotations) -{ - CDefEssential *anim = CDefHandler::giveDefEss(name); - int pom = 0; //how many groups has been rotated - for(int o=7; pom<6; ++o) - { - for(int p=0;p<6;p++) - { - if(anim->ourImages[o].groupNumber == rotations[p].first) - { - for(int e=0; e<8; ++e) - { - Cimage nci; - nci.bitmap = CSDL_Ext::verticalFlip(anim->ourImages[o+e].bitmap); - nci.groupNumber = rotations[p].second; - nci.imName = std::string(); - anim->ourImages.push_back(nci); - if(pom>2) //we need only one frame for groups 13/14/15 - break; - } - if(pom<3) //there are eight frames of animtion of groups 6/7/8 so for speed we'll skip them - o+=8; - else //there is only one frame of 1/2/3 - o+=1; - ++pom; - if(p==2 && pom<4) //group1 starts at index 1 - o = 1; - } - } - } - for(auto & elem : anim->ourImages) - { - CSDL_Ext::alphaTransform(elem.bitmap); - } return anim; } -void Graphics::loadHeroFlagsDetail(std::pair Graphics::*, std::vector > &pr, bool mode) +std::shared_ptr Graphics::loadHeroAnimation(const std::string &name) { - for(int i=0;i<8;i++) - (this->*pr.first).push_back(CDefHandler::giveDefEss(pr.second[i])); - //first - group number to be rotated1, second - group number after rotation1 - std::vector > rotations = + //first - group number to be rotated, second - group number after rotation + static const std::vector > rotations = { - {6,10}, {7,11}, {8,12} + {6,10}, {7,11}, {8,12}, {1,13}, + {2,14}, {3,15} }; - for(int q=0; q<8; ++q) + std::shared_ptr anim = std::make_shared(name); + anim->preload(); + + + for(const auto & rotation : rotations) { - std::vector &curImgs = (this->*pr.first)[q]->ourImages; - for(size_t o=0; osize(sourceGroup); ++frame) { - for(auto & rotation : rotations) - { - if(curImgs[o].groupNumber==rotation.first) - { - for(int e=0; e<8; ++e) - { - Cimage nci; - nci.bitmap = CSDL_Ext::verticalFlip(curImgs[o+e].bitmap); - nci.groupNumber = rotation.second; - nci.imName = std::string(); - curImgs.push_back(nci); - } - o+=8; - } - } - } - if (mode) - { - for(size_t o=0; oduplicateImage(sourceGroup, frame, targetGroup); + IImage * image = anim->getImage(frame, targetGroup); + image->verticalFlip(); } } -} -void Graphics::loadHeroFlags() -{ - CStopWatch th; - std::pair Graphics::*, std::vector > pr[4] = - { - { - &Graphics::flags1, - {"ABF01L.DEF","ABF01G.DEF","ABF01R.DEF","ABF01D.DEF","ABF01B.DEF", - "ABF01P.DEF","ABF01W.DEF","ABF01K.DEF"} - }, - { - &Graphics::flags2, - {"ABF02L.DEF","ABF02G.DEF","ABF02R.DEF","ABF02D.DEF","ABF02B.DEF", - "ABF02P.DEF","ABF02W.DEF","ABF02K.DEF"} - - }, - { - &Graphics::flags3, - {"ABF03L.DEF","ABF03G.DEF","ABF03R.DEF","ABF03D.DEF","ABF03B.DEF", - "ABF03P.DEF","ABF03W.DEF","ABF03K.DEF"} - }, - { - &Graphics::flags4, - {"AF00.DEF","AF01.DEF","AF02.DEF","AF03.DEF","AF04.DEF", - "AF05.DEF","AF06.DEF","AF07.DEF"} - } - }; - - #if 0 - boost::thread_group grupa; - for(int g=3; g>=0; --g) - { - grupa.create_thread(std::bind(&Graphics::loadHeroFlagsDetail, this, std::ref(pr[g]), true)); - } - grupa.join_all(); - #else - for(auto p: pr) - { - loadHeroFlagsDetail(p,true); - } - #endif - logGlobal->infoStream() << "Loading and transforming heroes' flags: "<("TSHRC"); + fogOfWarFullHide->preload(); + fogOfWarPartialHide = std::make_shared("TSHRE"); + fogOfWarPartialHide->preload(); + + static const int rotations [] = {22, 15, 2, 13, 12, 16, 28, 17, 20, 19, 7, 24, 26, 25, 30, 32, 27}; + + size_t size = fogOfWarPartialHide->size(0);//group size after next rotation + + for(const int rotation : rotations) + { + fogOfWarPartialHide->duplicateImage(0, rotation, 0); + IImage * image = fogOfWarPartialHide->getImage(size, 0); + image->verticalFlip(); + size++; + } +} + void Graphics::loadFonts() { const JsonNode config(ResourceID("config/fonts.json")); @@ -374,32 +334,47 @@ void Graphics::loadFonts() std::string filename = bmpConf[i].String(); if (!hanConf[filename].isNull()) - fonts[i] = new CBitmapHanFont(hanConf[filename]); + fonts[i] = std::make_shared(hanConf[filename]); else if (!ttfConf[filename].isNull()) // no ttf override - fonts[i] = new CTrueTypeFont(ttfConf[filename]); + fonts[i] = std::make_shared(ttfConf[filename]); else - fonts[i] = new CBitmapFont(filename); + fonts[i] = std::make_shared(filename); } } -CDefEssential * Graphics::getDef( const CGObjectInstance * obj ) +std::shared_ptr Graphics::getAnimation(const CGObjectInstance* obj) { - if (obj->appearance.animationFile.empty()) + return getAnimation(obj->appearance); +} + +std::shared_ptr Graphics::getAnimation(const ObjectTemplate & info) +{ + //the only(?) invisible object + if(info.id == Obj::EVENT) { - logGlobal->warnStream() << boost::format("Def name for obj %d (%d,%d) is empty!") % obj->id % obj->ID % obj->subID; - return nullptr; + return std::shared_ptr(); } - return advmapobjGraphics[obj->appearance.animationFile]; -} -CDefEssential * Graphics::getDef( const ObjectTemplate & info ) -{ - if (info.animationFile.empty()) + if(info.animationFile.empty()) { logGlobal->warnStream() << boost::format("Def name for obj (%d,%d) is empty!") % info.id % info.subid; - return nullptr; + return std::shared_ptr(); } - return advmapobjGraphics[info.animationFile]; + + std::shared_ptr ret = mapObjectAnimations[info.animationFile]; + + //already loaded + if(ret) + { + ret->preload(); + return ret; + } + + ret = std::make_shared(info.animationFile); + mapObjectAnimations[info.animationFile] = ret; + + ret->preload(); + return ret; } void Graphics::loadErmuToPicture() diff --git a/client/Graphics.h b/client/Graphics.h index 4481a6098..447f0cdaa 100644 --- a/client/Graphics.h +++ b/client/Graphics.h @@ -1,6 +1,5 @@ #pragma once - #include "gui/Fonts.h" #include "../lib/GameConstants.h" #include "gui/Geometries.h" @@ -15,11 +14,9 @@ * */ -class CDefEssential; struct SDL_Surface; class CGHeroInstance; class CGTownInstance; -class CDefHandler; class CHeroClass; struct SDL_Color; struct InfoAboutHero; @@ -40,19 +37,25 @@ class Graphics void initializeBattleGraphics(); void loadPaletteAndColors(); - void loadHeroFlags(); - void loadHeroFlagsDetail(std::pair Graphics::*, std::vector > &pr, bool mode); - void loadHeroAnims(); - CDefEssential * loadHeroAnim(const std::string &name, const std::vector > &rotations); - void loadErmuToPicture(); + void loadHeroAnimations(); + //loads animation and adds required rotated frames + std::shared_ptr loadHeroAnimation(const std::string &name); + + void loadHeroFlagAnimations(); + + //loads animation and adds required rotated frames + std::shared_ptr loadHeroFlagAnimation(const std::string &name); + + void loadErmuToPicture(); + void loadFogOfWar(); void loadFonts(); void initializeImageLists(); public: //Fonts static const int FONTS_NUMBER = 9; - IFont * fonts[FONTS_NUMBER]; + std::array< std::shared_ptr, FONTS_NUMBER> fonts; //various graphics SDL_Color * playerColors; //array [8] @@ -60,18 +63,25 @@ public: SDL_Color * playerColorPalette; //palette to make interface colors good - array of size [256] SDL_Color * neutralColorPalette; - std::vector flags1, flags2, flags3, flags4; //flags blitted on heroes when , std::shared_ptr heroMoveArrows; - std::map heroAnims; // [hero class def name] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing - std::vector boatAnims; // [boat type: 0 - 3] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing - CDefHandler * FoWfullHide; //for Fog of War - CDefHandler * FoWpartialHide; //for For of War + + // [hero class def name] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing + std::map< std::string, std::shared_ptr > heroAnimations; + std::vector< std::shared_ptr > heroFlagAnimations; + + // [boat type: 0 .. 2] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing + std::array< std::shared_ptr, 3> boatAnimations; + + std::array< std::vector >, 3> boatFlagAnimations; + + //all other objects (not hero or boat) + std::map< std::string, std::shared_ptr > mapObjectAnimations; + + std::shared_ptr fogOfWarFullHide; + std::shared_ptr fogOfWarPartialHide; std::map imageLists; - std::map advmapobjGraphics; - CDefEssential * getDef(const CGObjectInstance * obj); - CDefEssential * getDef(const ObjectTemplate & info); //towns std::map ERMUtoPicture[GameConstants::F_NUMBER]; //maps building ID to it's picture's name for each town type //for battles @@ -83,6 +93,9 @@ public: void load(); void blueToPlayersAdv(SDL_Surface * sur, PlayerColor player); //replaces blue interface colour with a color of player + + std::shared_ptr getAnimation(const CGObjectInstance * obj); + std::shared_ptr getAnimation(const ObjectTemplate & info); }; extern Graphics * graphics; diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 48b36d0e0..a264c7b45 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -369,7 +369,7 @@ void TryMoveHero::applyFirstCl(CClient *cl) } if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK || !humanKnows) - CGI->mh->removeObject(h, result == EMBARK && humanKnows); + CGI->mh->hideObject(h, result == EMBARK && humanKnows); if(result == DISEMBARK) diff --git a/client/gui/CAnimation.cpp b/client/gui/CAnimation.cpp index 5e0f847c7..2ea5f511f 100644 --- a/client/gui/CAnimation.cpp +++ b/client/gui/CAnimation.cpp @@ -23,10 +23,143 @@ * */ +class SDLImageLoader; +class CompImageLoader; + typedef std::map > source_map; typedef std::map image_map; typedef std::map group_map; + /// Class for def loading, methods are based on CDefHandler +/// After loading will store general info (palette and frame offsets) and pointer to file itself +class CDefFile +{ +private: + + struct SSpriteDef + { + ui32 size; + ui32 format; /// format in which pixel data is stored + ui32 fullWidth; /// full width and height of frame, including borders + ui32 fullHeight; + ui32 width; /// width and height of pixel data, borders excluded + ui32 height; + si32 leftMargin; + si32 topMargin; + } PACKED_STRUCT; + //offset[group][frame] - offset of frame data in file + std::map > offset; + + std::unique_ptr data; + std::unique_ptr palette; + +public: + CDefFile(std::string Name); + ~CDefFile(); + + //load frame as SDL_Surface + template + void loadFrame(size_t frame, size_t group, ImageLoader &loader) const; + + const std::map getEntries() const; +}; + + +/* + * Wrapper around SDL_Surface + */ +class SDLImage : public IImage +{ +public: + //Surface without empty borders + SDL_Surface * surf; + //size of left and top borders + Point margins; + //total size including borders + Point fullSize; + +public: + //Load image from def file + SDLImage(CDefFile *data, size_t frame, size_t group=0, bool compressed=false); + //Load from bitmap file + SDLImage(std::string filename, bool compressed=false); + //Create using existing surface, extraRef will increase refcount on SDL_Surface + SDLImage(SDL_Surface * from, bool extraRef); + ~SDLImage(); + + void draw(SDL_Surface * where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override; + void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override; + std::unique_ptr scaleFast(float scale) const override; + + void playerColored(PlayerColor player) override; + void setFlagColor(PlayerColor player) override; + int width() const override; + int height() const override; + + void horizontalFlip() override; + void verticalFlip() override; + + void shiftPalette(int from, int howMany) override; + + friend class SDLImageLoader; +}; + +/* + * RLE-compressed image data for 8-bit images with alpha-channel, currently far from finished + * primary purpose is not high compression ratio but fast drawing. + * Consist of repeatable segments with format similar to H3 def compression: + * 1st byte: + * if (byte == 0xff) + * raw data, opaque and semi-transparent data always in separate blocks + * else + * RLE-compressed image data with this color + * 2nd byte = size of segment + * raw data (if any) + */ +class CompImage : public IImage +{ + //x,y - margins, w,h - sprite size + Rect sprite; + //total size including borders + Point fullSize; + + //RLE-d data + ui8 * surf; + //array of offsets for each line + ui32 * line; + //palette + SDL_Color *palette; + + //Used internally to blit one block of data + template + void BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha) const; + void BlitBlockWithBpp(ui8 bpp, ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha, bool rotated) const; + +public: + //Load image from def file + CompImage(const CDefFile *data, size_t frame, size_t group=0); + //TODO: load image from SDL_Surface + CompImage(SDL_Surface * surf); + ~CompImage(); + + void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override; + void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override; + + std::unique_ptr scaleFast(float scale) const override; + + void playerColored(PlayerColor player) override; + void setFlagColor(PlayerColor player) override; + int width() const override; + int height() const override; + + void horizontalFlip() override; + void verticalFlip() override; + + void shiftPalette(int from, int howMany) override; + + friend class CompImageLoader; +}; + class SDLImageLoader { SDLImage * image; @@ -214,7 +347,7 @@ void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const //pixel data is not compressed, copy data to surface for (ui32 i=0; iw, surf->h); - //TODO: rotation and scaling - if (src) - { - sourceRect = sourceRect & *src; - } Rect destRect(posX, posY, surf->w, surf->h); - destRect += sourceRect.topLeft(); - sourceRect -= margins; + + draw(where, &destRect, src); +} + +void SDLImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alpha) const +{ + if (!surf) + return; + + Rect sourceRect(0, 0, surf->w, surf->h); + + Point destShift(0, 0); + + if(src) + { + if(src->x < margins.x) + destShift.x += margins.x - src->x; + + if(src->y < margins.y) + destShift.y += margins.y - src->y; + + sourceRect = Rect(*src) & Rect(margins.x, margins.y, surf->w, surf->h); + + sourceRect -= margins; + } + else + destShift = margins; + + Rect destRect(destShift.x, destShift.y, surf->w, surf->h); + + if(dest) + { + destRect.x += dest->x; + destRect.y += dest->y; + } if(surf->format->BitsPerPixel == 8) { CSDL_Ext::blit8bppAlphaTo24bpp(surf, &sourceRect, where, &destRect); } - else if(surf->format->Amask == 0) - { - SDL_BlitSurface(surf, &sourceRect, where, &destRect); - } else { - SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND); - SDL_BlitSurface(surf, &sourceRect, where, &destRect); - SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE); + SDL_UpperBlit(surf, &sourceRect, where, &destRect); } } +std::unique_ptr SDLImage::scaleFast(float scale) const +{ + auto scaled = CSDL_Ext::scaleSurfaceFast(surf, surf->w * scale, surf->h * scale); + + if (scaled->format && scaled->format->palette) // fix color keying, because SDL loses it at this point + CSDL_Ext::setColorKey(scaled, scaled->format->palette->colors[0]); + else if(scaled->format && scaled->format->Amask) + SDL_SetSurfaceBlendMode(scaled, SDL_BLENDMODE_BLEND);//just in case + else + CSDL_Ext::setDefaultColorKey(scaled);//just in case + + SDLImage * ret = new SDLImage(scaled, false); + + ret->fullSize.x = (int) round((float)fullSize.x * scale); + ret->fullSize.y = (int) round((float)fullSize.y * scale); + + ret->margins.x = (int) round((float)margins.x * scale); + ret->margins.y = (int) round((float)margins.y * scale); + + return std::unique_ptr(ret); +} + void SDLImage::playerColored(PlayerColor player) { graphics->blueToPlayersAdv(surf, player); } +void SDLImage::setFlagColor(PlayerColor player) +{ + if(player < PlayerColor::PLAYER_LIMIT || player==PlayerColor::NEUTRAL) + CSDL_Ext::setPlayerColor(surf, player); +} + int SDLImage::width() const { return fullSize.x; @@ -677,6 +859,43 @@ int SDLImage::height() const return fullSize.y; } +void SDLImage::horizontalFlip() +{ + margins.y = fullSize.y - surf->h - margins.y; + + //todo: modify in-place + SDL_Surface * flipped = CSDL_Ext::horizontalFlip(surf); + SDL_FreeSurface(surf); + surf = flipped; +} + +void SDLImage::verticalFlip() +{ + margins.x = fullSize.x - surf->w - margins.x; + + //todo: modify in-place + SDL_Surface * flipped = CSDL_Ext::verticalFlip(surf); + SDL_FreeSurface(surf); + surf = flipped; +} + +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); @@ -699,6 +918,12 @@ CompImage::CompImage(SDL_Surface * surf) } void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alpha) const +{ + Rect dest(posX,posY, width(), height()); + draw(where, &dest, src, alpha); +} + +void CompImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alpha) const { int rotation = 0; //TODO //rotation & 2 = horizontal rotation @@ -713,11 +938,18 @@ void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alph sourceRect = sourceRect & Rect(0, 0, where->w, where->h); //Starting point on SDL surface - Point dest(posX+sourceRect.x, posY+sourceRect.y); + Point dst(sourceRect.x,sourceRect.y); + + if (dest) + { + dst.x += dest->x; + dst.y += dest->y; + } + if (rotation & 2) - dest.y += sourceRect.h; + dst.y += sourceRect.h; if (rotation & 4) - dest.x += sourceRect.w; + dst.x += sourceRect.w; sourceRect -= sprite.topLeft(); @@ -748,10 +980,10 @@ void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alph //Calculate position for blitting: pixels + Y + X ui8* blitPos = (ui8*) where->pixels; if (rotation & 4) - blitPos += (dest.y - currY) * where->pitch; + blitPos += (dst.y - currY) * where->pitch; else - blitPos += (dest.y + currY) * where->pitch; - blitPos += dest.x * bpp; + blitPos += (dst.y + currY) * where->pitch; + blitPos += dst.x * bpp; //Blit blocks that must be fully visible while (currX + size < sourceRect.w) @@ -769,6 +1001,16 @@ void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alph } } + +std::unique_ptr CompImage::scaleFast(float scale) const +{ + //todo: CompImage::scaleFast + + logAnim->error("CompImage::scaleFast is not implemented"); + + return nullptr; +} + #define CASEBPP(x,y) case x: BlitBlock(type, size, data, dest, alpha); break //FIXME: better way to get blitter @@ -883,6 +1125,11 @@ void CompImage::playerColored(PlayerColor player) } } +void CompImage::setFlagColor(PlayerColor player) +{ + logAnim->error("CompImage::setFlagColor is not implemented"); +} + int CompImage::width() const { return fullSize.x; @@ -900,6 +1147,22 @@ CompImage::~CompImage() delete [] palette; } +void CompImage::horizontalFlip() +{ + logAnim->error("CompImage::horizontalFlip is not implemented"); +} + +void CompImage::verticalFlip() +{ + logAnim->error("CompImage::verticalFlip is not implemented"); +} + +void CompImage::shiftPalette(int from, int howMany) +{ + logAnim->error("CompImage::shiftPalette is not implemented"); +} + + /************************************************************************* * CAnimation for animations handling, can load part of file if needed * *************************************************************************/ @@ -916,6 +1179,7 @@ IImage * CAnimation::getFromExtraDef(std::string filename) pos = filename.find(':', pos); if (pos != -1) { + pos++; group = frame; frame = atoi(filename.c_str()+pos); } @@ -963,7 +1227,7 @@ bool CAnimation::loadFrame(CDefFile * file, size_t frame, size_t group) } else //load from separate file { - std::string filename = source[group][frame].Struct().find("file")->second.String(); + std::string filename = source[group][frame]["file"].String(); IImage * img = getFromExtraDef(filename); if (!img) @@ -1105,6 +1369,25 @@ CAnimation::~CAnimation() } } +void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup) +{ + //todo: clone actual loaded Image object + JsonNode clone(source[sourceGroup][sourceFrame]); + + if(clone.getType() == JsonNode::DATA_NULL) + { + std::string temp = name+":"+boost::lexical_cast(sourceGroup)+":"+boost::lexical_cast(sourceFrame); + clone["file"].String() = temp; + } + + source[targetGroup].push_back(clone); + + size_t index = source[targetGroup].size() - 1; + + if(preloaded) + load(index, targetGroup); +} + void CAnimation::setCustom(std::string filename, size_t frame, size_t group) { if (source[group].size() <= frame) @@ -1148,8 +1431,11 @@ void CAnimation::unload() void CAnimation::preload() { - preloaded = true; - load(); + if(!preloaded) + { + preloaded = true; + load(); + } } void CAnimation::loadGroup(size_t group) diff --git a/client/gui/CAnimation.h b/client/gui/CAnimation.h index 995863240..5765189f5 100644 --- a/client/gui/CAnimation.h +++ b/client/gui/CAnimation.h @@ -15,43 +15,8 @@ */ struct SDL_Surface; -class SDLImageLoader; -class CompImageLoader; class JsonNode; - -/// Class for def loading, methods are based on CDefHandler -/// After loading will store general info (palette and frame offsets) and pointer to file itself -class CDefFile -{ -private: - - struct SSpriteDef - { - ui32 size; - ui32 format; /// format in which pixel data is stored - ui32 fullWidth; /// full width and height of frame, including borders - ui32 fullHeight; - ui32 width; /// width and height of pixel data, borders excluded - ui32 height; - si32 leftMargin; - si32 topMargin; - } PACKED_STRUCT; - //offset[group][frame] - offset of frame data in file - std::map > offset; - - std::unique_ptr data; - std::unique_ptr palette; - -public: - CDefFile(std::string Name); - ~CDefFile(); - - //load frame as SDL_Surface - template - void loadFrame(size_t frame, size_t group, ImageLoader &loader) const; - - const std::map getEntries() const; -}; +class CDefFile; /* * Base class for images, can be used for non-animation pictures as well @@ -62,7 +27,10 @@ class IImage public: //draws image on surface "where" at position - virtual void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const=0; + virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, Rect * src = nullptr, ui8 alpha = 255) const=0; + virtual void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha = 255) const = 0; + + virtual std::unique_ptr scaleFast(float scale) const = 0; //decrease ref count, returns true if image can be deleted (refCount <= 0) bool decreaseRef(); @@ -70,90 +38,23 @@ public: //Change palette to specific player virtual void playerColored(PlayerColor player)=0; + + //set special color for flag + virtual void setFlagColor(PlayerColor player)=0; + 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(); virtual ~IImage() {}; }; -/* - * Wrapper around SDL_Surface - */ -class SDLImage : public IImage -{ -public: - //Surface without empty borders - SDL_Surface * surf; - //size of left and top borders - Point margins; - //total size including borders - Point fullSize; - -public: - //Load image from def file - SDLImage(CDefFile *data, size_t frame, size_t group=0, bool compressed=false); - //Load from bitmap file - SDLImage(std::string filename, bool compressed=false); - //Create using existing surface, extraRef will increase refcount on SDL_Surface - SDLImage(SDL_Surface * from, bool extraRef); - ~SDLImage(); - - void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override; - - void playerColored(PlayerColor player) override; - int width() const override; - int height() const override; - - friend class SDLImageLoader; -}; - -/* - * RLE-compressed image data for 8-bit images with alpha-channel, currently far from finished - * primary purpose is not high compression ratio but fast drawing. - * Consist of repeatable segments with format similar to H3 def compression: - * 1st byte: - * if (byte == 0xff) - * raw data, opaque and semi-transparent data always in separate blocks - * else - * RLE-compressed image data with this color - * 2nd byte = size of segment - * raw data (if any) - */ -class CompImage : public IImage -{ - //x,y - margins, w,h - sprite size - Rect sprite; - //total size including borders - Point fullSize; - - //RLE-d data - ui8 * surf; - //array of offsets for each line - ui32 * line; - //palette - SDL_Color *palette; - - //Used internally to blit one block of data - template - void BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha) const; - void BlitBlockWithBpp(ui8 bpp, ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha, bool rotated) const; - -public: - //Load image from def file - CompImage(const CDefFile *data, size_t frame, size_t group=0); - //TODO: load image from SDL_Surface - CompImage(SDL_Surface * surf); - ~CompImage(); - - void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override; - void playerColored(PlayerColor player) override; - int width() const override; - int height() const override; - - friend class CompImageLoader; -}; - - /// Class for handling animation class CAnimation { @@ -198,6 +99,10 @@ public: CAnimation(); ~CAnimation(); + //duplicates frame at [sourceGroup, sourceFrame] as last frame in targetGroup + //and loads it if animation is preloaded + void duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup); + //add custom surface to the selected position. void setCustom(std::string filename, size_t frame, size_t group=0); diff --git a/client/gui/SDL_Extensions.cpp b/client/gui/SDL_Extensions.cpp index 029bba878..069859d25 100644 --- a/client/gui/SDL_Extensions.cpp +++ b/client/gui/SDL_Extensions.cpp @@ -79,6 +79,10 @@ void blitAt(SDL_Surface * src, const SDL_Rect & pos, SDL_Surface * dst) SDL_Surface * CSDL_Ext::verticalFlip(SDL_Surface * toRot) { SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags); + + SDL_LockSurface(ret); + SDL_LockSurface(toRot); + const int bpp = ret->format->BytesPerPixel; char * src = reinterpret_cast(toRot->pixels); @@ -86,26 +90,29 @@ SDL_Surface * CSDL_Ext::verticalFlip(SDL_Surface * toRot) for(int i=0; ih; i++) { - char * srcPxl = src; - char * dstPxl = dst + ret->w * bpp; + //FIXME: optimization bugged +// if (bpp == 1) +// { +// // much faster for 8-bit surfaces (majority of our data) +// std::reverse_copy(src, src + toRot->pitch, dst); +// } +// else +// { + char * srcPxl = src; + char * dstPxl = dst + ret->w * bpp; - if (bpp == 1) - { - // much faster for 8-bit surfaces (majority of our data) - std::reverse_copy(src, src + ret->pitch, dst); - } - else - { for(int j=0; jw; j++) { dstPxl -= bpp; std::copy(srcPxl, srcPxl + bpp, dstPxl); srcPxl += bpp; } - } +// } src += toRot->pitch; dst += ret->pitch; } + SDL_UnlockSurface(ret); + SDL_UnlockSurface(toRot); return ret; } @@ -113,6 +120,8 @@ SDL_Surface * CSDL_Ext::verticalFlip(SDL_Surface * toRot) SDL_Surface * CSDL_Ext::horizontalFlip(SDL_Surface * toRot) { SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags); + SDL_LockSurface(ret); + SDL_LockSurface(toRot); char * src = reinterpret_cast(toRot->pixels); char * dst = reinterpret_cast(ret->pixels) + ret->h * ret->pitch; @@ -122,6 +131,8 @@ SDL_Surface * CSDL_Ext::horizontalFlip(SDL_Surface * toRot) std::copy(src, src + toRot->pitch, dst); src += toRot->pitch; } + SDL_UnlockSurface(ret); + SDL_UnlockSurface(toRot); return ret; }; @@ -171,180 +182,6 @@ void CSDL_Ext::alphaTransform(SDL_Surface *src) SDL_SetColorKey(src, SDL_TRUE, 0); } -static void prepareOutRect(SDL_Rect *src, SDL_Rect *dst, const SDL_Rect & clip_rect) -{ - const int xoffset = std::max(clip_rect.x - dst->x, 0), - yoffset = std::max(clip_rect.y - dst->y, 0); - - src->x += xoffset; - src->y += yoffset; - dst->x += xoffset; - dst->y += yoffset; - - src->w = dst->w = std::max(0,std::min(dst->w - xoffset, clip_rect.x + clip_rect.w - dst->x)); - src->h = dst->h = std::max(0,std::min(dst->h - yoffset, clip_rect.y + clip_rect.h - dst->y)); -} - -template -void CSDL_Ext::blitWithRotateClip(SDL_Surface *src,SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect, ui8 rotation)//srcRect is not used, works with 8bpp sources and 24bpp dests -{ - if(!rotation) - { - CSDL_Ext::blitSurface(src, srcRect, dst, dstRect); - } - else - { - static void (*blitWithRotate[])(const SDL_Surface *, const SDL_Rect *, SDL_Surface *, const SDL_Rect *) = {blitWithRotate1, blitWithRotate2, blitWithRotate3}; - prepareOutRect(srcRect, dstRect, dst->clip_rect); - blitWithRotate[rotation-1](src, srcRect, dst, dstRect); - } -} - -template -void CSDL_Ext::blitWithRotateClipVal( SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation ) -{ - blitWithRotateClip(src, &srcRect, dst, &dstRect, rotation); -} - -template -void CSDL_Ext::blitWithRotateClipWithAlpha(SDL_Surface *src,SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect, ui8 rotation)//srcRect is not used, works with 8bpp sources and 24bpp dests -{ - if(!rotation) - { - blit8bppAlphaTo24bpp(src, srcRect, dst, dstRect); - } - else - { - static void (*blitWithRotate[])(const SDL_Surface *, const SDL_Rect *, SDL_Surface *, const SDL_Rect *) = {blitWithRotate1WithAlpha, blitWithRotate2WithAlpha, blitWithRotate3WithAlpha}; - prepareOutRect(srcRect, dstRect, dst->clip_rect); - blitWithRotate[rotation-1](src, srcRect, dst, dstRect); - } -} - -template -void CSDL_Ext::blitWithRotateClipValWithAlpha( SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation ) -{ - blitWithRotateClipWithAlpha(src, &srcRect, dst, &dstRect, rotation); -} - -template -void CSDL_Ext::blitWithRotate1(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests -{ - Uint8 *sp = getPxPtr(src, src->w - srcRect->w - srcRect->x, srcRect->y); - Uint8 *dporg = (Uint8 *)dst->pixels + dstRect->y*dst->pitch + (dstRect->x+dstRect->w)*bpp; - const SDL_Color * const colors = src->format->palette->colors; - - for(int i=dstRect->h; i>0; i--, dporg += dst->pitch) - { - Uint8 *dp = dporg; - for(int j=dstRect->w; j>0; j--, sp++) - ColorPutter::PutColor(dp, colors[*sp]); - - sp += src->w - dstRect->w; - } -} - -template -void CSDL_Ext::blitWithRotate2(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests -{ - Uint8 *sp = getPxPtr(src, srcRect->x, src->h - srcRect->h - srcRect->y); - Uint8 *dporg = (Uint8 *)dst->pixels + (dstRect->y + dstRect->h - 1)*dst->pitch + dstRect->x*bpp; - const SDL_Color * const colors = src->format->palette->colors; - - for(int i=dstRect->h; i>0; i--, dporg -= dst->pitch) - { - Uint8 *dp = dporg; - - for(int j=dstRect->w; j>0; j--, sp++) - ColorPutter::PutColor(dp, colors[*sp]); - - sp += src->w - dstRect->w; - } -} - -template -void CSDL_Ext::blitWithRotate3(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests -{ - Uint8 *sp = (Uint8 *)src->pixels + (src->h - srcRect->h - srcRect->y)*src->pitch + (src->w - srcRect->w - srcRect->x); - Uint8 *dporg = (Uint8 *)dst->pixels +(dstRect->y + dstRect->h - 1)*dst->pitch + (dstRect->x+dstRect->w)*bpp; - const SDL_Color * const colors = src->format->palette->colors; - - for(int i=dstRect->h; i>0; i--, dporg -= dst->pitch) - { - Uint8 *dp = dporg; - for(int j=dstRect->w; j>0; j--, sp++) - ColorPutter::PutColor(dp, colors[*sp]); - - sp += src->w - dstRect->w; - } -} - -template -void CSDL_Ext::blitWithRotate1WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests -{ - Uint8 *sp = (Uint8 *)src->pixels + srcRect->y*src->pitch + (src->w - srcRect->w - srcRect->x); - Uint8 *dporg = (Uint8 *)dst->pixels + dstRect->y*dst->pitch + (dstRect->x+dstRect->w)*bpp; - const SDL_Color * const colors = src->format->palette->colors; - - for(int i=dstRect->h; i>0; i--, dporg += dst->pitch) - { - Uint8 *dp = dporg; - for(int j=dstRect->w; j>0; j--, sp++) - { - if(*sp) - ColorPutter::PutColor(dp, colors[*sp]); - else - dp -= bpp; - } - - sp += src->w - dstRect->w; - } -} - -template -void CSDL_Ext::blitWithRotate2WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests -{ - Uint8 *sp = (Uint8 *)src->pixels + (src->h - srcRect->h - srcRect->y)*src->pitch + srcRect->x; - Uint8 *dporg = (Uint8 *)dst->pixels + (dstRect->y + dstRect->h - 1)*dst->pitch + dstRect->x*bpp; - const SDL_Color * const colors = src->format->palette->colors; - - for(int i=dstRect->h; i>0; i--, dporg -= dst->pitch) - { - Uint8 *dp = dporg; - - for(int j=dstRect->w; j>0; j--, sp++) - { - if(*sp) - ColorPutter::PutColor(dp, colors[*sp]); - else - dp += bpp; - } - - sp += src->w - dstRect->w; - } -} - -template -void CSDL_Ext::blitWithRotate3WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect)//srcRect is not used, works with 8bpp sources and 24/32 bpp dests -{ - Uint8 *sp = (Uint8 *)src->pixels + (src->h - srcRect->h - srcRect->y)*src->pitch + (src->w - srcRect->w - srcRect->x); - Uint8 *dporg = (Uint8 *)dst->pixels +(dstRect->y + dstRect->h - 1)*dst->pitch + (dstRect->x+dstRect->w)*bpp; - const SDL_Color * const colors = src->format->palette->colors; - - for(int i=dstRect->h; i>0; i--, dporg -= dst->pitch) - { - Uint8 *dp = dporg; - for(int j=dstRect->w; j>0; j--, sp++) - { - if(*sp) - ColorPutter::PutColor(dp, colors[*sp]); - else - dp -= bpp; - } - - sp += src->w - dstRect->w; - } -} template int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect) { @@ -666,38 +503,6 @@ void CSDL_Ext::SDL_PutPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int SDL_PutPixelWithoutRefresh(ekran, x, y, R, G, B, A); } -BlitterWithRotationVal CSDL_Ext::getBlitterWithRotation(SDL_Surface *dest) -{ - switch(dest->format->BytesPerPixel) - { - case 2: return blitWithRotateClipVal<2>; - case 3: return blitWithRotateClipVal<3>; - case 4: return blitWithRotateClipVal<4>; - default: - logGlobal->errorStream() << (int)dest->format->BitsPerPixel << " bpp is not supported!!!"; - break; - } - - assert(0); - return nullptr; -} - -BlitterWithRotationVal CSDL_Ext::getBlitterWithRotationAndAlpha(SDL_Surface *dest) -{ - switch(dest->format->BytesPerPixel) - { - case 2: return blitWithRotateClipValWithAlpha<2>; - case 3: return blitWithRotateClipValWithAlpha<3>; - case 4: return blitWithRotateClipValWithAlpha<4>; - default: - logGlobal->errorStream() << (int)dest->format->BitsPerPixel << " bpp is not supported!!!"; - break; - } - - assert(0); - return nullptr; -} - template void CSDL_Ext::applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mode ) { @@ -894,11 +699,11 @@ SDL_Surface * CSDL_Ext::scaleSurface(SDL_Surface *surf, int width, int height) return ret; } -void CSDL_Ext::blitSurface( SDL_Surface * src, SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect ) +void CSDL_Ext::blitSurface( SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect ) { if (dst != screen) { - SDL_BlitSurface(src, srcRect, dst, dstRect); + SDL_UpperBlit(src, srcRect, dst, dstRect); } else { @@ -912,7 +717,7 @@ void CSDL_Ext::blitSurface( SDL_Surface * src, SDL_Rect * srcRect, SDL_Surface * betterDst = Rect(0, 0, dst->w, dst->h); } - SDL_BlitSurface(src, srcRect, dst, &betterDst); + SDL_UpperBlit(src, srcRect, dst, &betterDst); } } diff --git a/client/gui/SDL_Extensions.h b/client/gui/SDL_Extensions.h index 0f9a5e7d4..773d2db1a 100644 --- a/client/gui/SDL_Extensions.h +++ b/client/gui/SDL_Extensions.h @@ -7,7 +7,7 @@ * Full text of license available in license.txt file, in main folder * */ - + #pragma once #include #include @@ -88,7 +88,7 @@ public: /** green color used for in-game console */ static const SDL_Color GREEN; - + /** default key color for all 8 & 24 bit graphics */ static const SDL_Color DEFAULT_KEY_COLOR; }; @@ -167,7 +167,7 @@ namespace CSDL_Ext } }; - void blitSurface(SDL_Surface * src, SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect); + void blitSurface(SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect); void fillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); void fillRectBlack(SDL_Surface * dst, SDL_Rect * dstrect); //fill dest image with source texture. @@ -185,21 +185,6 @@ namespace CSDL_Ext Uint8 *getPxPtr(const SDL_Surface * const &srf, const int x, const int y); TColorPutter getPutterFor(SDL_Surface * const &dest, int incrementing); //incrementing: -1, 0, 1 TColorPutterAlpha getPutterAlphaFor(SDL_Surface * const &dest, int incrementing); //incrementing: -1, 0, 1 - BlitterWithRotationVal getBlitterWithRotation(SDL_Surface *dest); - BlitterWithRotationVal getBlitterWithRotationAndAlpha(SDL_Surface *dest); - - template void blitWithRotateClip(SDL_Surface *src,SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect, ui8 rotation);//srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect - template void blitWithRotateClipVal(SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation);//srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect - - template void blitWithRotateClipWithAlpha(SDL_Surface *src,SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect, ui8 rotation);//srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect - template void blitWithRotateClipValWithAlpha(SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation);//srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect - - template void blitWithRotate1(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect);//srcRect is not used, works with 8bpp sources and 24bpp dests - template void blitWithRotate2(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect);//srcRect is not used, works with 8bpp sources and 24bpp dests - template void blitWithRotate3(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect);//srcRect is not used, works with 8bpp sources and 24bpp dests - template void blitWithRotate1WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect);//srcRect is not used, works with 8bpp sources and 24bpp dests - template void blitWithRotate2WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect);//srcRect is not used, works with 8bpp sources and 24bpp dests - template void blitWithRotate3WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect);//srcRect is not used, works with 8bpp sources and 24bpp dests template int blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect); //blits 8 bpp surface with alpha channel to 24 bpp surface @@ -228,10 +213,10 @@ namespace CSDL_Ext template void applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mode ); void applyEffect(SDL_Surface * surf, const SDL_Rect * rect, int mode); //mode: 0 - sepia, 1 - grayscale - + void startTextInput(SDL_Rect * where); void stopTextInput(); - + void setColorKey(SDL_Surface * surface, SDL_Color color); ///set key-color to 0,255,255 void setDefaultColorKey(SDL_Surface * surface); diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index 24c26ac32..aa3012ab3 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -22,7 +22,6 @@ #include "../lib/CTownHandler.h" #include "Graphics.h" #include "../lib/mapping/CMap.h" -#include "CDefHandler.h" #include "../lib/CConfigHandler.h" #include "../lib/CGeneralTextHandler.h" #include "../lib/GameConstants.h" @@ -32,50 +31,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); @@ -146,26 +101,11 @@ struct NeighborTilesInfo void CMapHandler::prepareFOWDefs() { - graphics->FoWfullHide = CDefHandler::giveDef("TSHRC.DEF"); - graphics->FoWpartialHide = CDefHandler::giveDef("TSHRE.DEF"); - - //adding necessary rotations - static const int missRot [] = {22, 15, 2, 13, 12, 16, 28, 17, 20, 19, 7, 24, 26, 25, 30, 32, 27}; - - Cimage nw; - for(auto & elem : missRot) - { - nw = graphics->FoWpartialHide->ourImages[elem]; - nw.bitmap = CSDL_Ext::verticalFlip(nw.bitmap); - graphics->FoWpartialHide->ourImages.push_back(nw); - } - //necessaary rotations added - - //alpha - transformation - for(auto & elem : graphics->FoWpartialHide->ourImages) - { - CSDL_Ext::alphaTransform(elem.bitmap); - } + //assume all frames in group 0 + size_t size = graphics->fogOfWarFullHide->size(0); + FoWfullHide.resize(size); + for(size_t frame = 0; frame < size; frame++) + FoWfullHide[frame] = graphics->fogOfWarFullHide->getImage(frame); //initialization of type of full-hide image hideBitmap.resize(sizes.x); @@ -180,10 +120,15 @@ void CMapHandler::prepareFOWDefs() elem[j].resize(sizes.z); for(int k = 0; k < sizes.z; ++k) { - elem[j][k] = CRandomGenerator::getDefault().nextInt(graphics->FoWfullHide->ourImages.size() - 1); + elem[j][k] = CRandomGenerator::getDefault().nextInt(size - 1); } } } + + size = graphics->fogOfWarPartialHide->size(0); + FoWpartialHide.resize(size); + for(size_t frame = 0; frame < size; frame++) + FoWpartialHide[frame] = graphics->fogOfWarPartialHide->getImage(frame); } EMapAnimRedrawStatus CMapHandler::drawTerrainRectNew(SDL_Surface * targetSurface, const MapDrawingInfo * info, bool redrawOnlyAnim /* = false */) @@ -194,31 +139,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 @@ -234,33 +229,34 @@ void CMapHandler::roadsRiverTerrainInit() } } -void CMapHandler::borderAndTerrainBitmapInit() +void CMapHandler::initBorderGraphics() { - CDefHandler * bord = CDefHandler::giveDef("EDG.DEF"); - bord->notFreeImgs = true; - terrainGraphics.resize(10); - for (int i = 0; i < 10 ; i++) + egdeImages.resize(egdeAnimation->size(0)); + for(size_t i = 0; i < egdeImages.size(); i++) + egdeImages[i] = egdeAnimation->getImage(i); + + edgeFrames.resize(sizes.x, frameW, frameW); + for (int i=0-frameW;iourImages.size()); - hlp->notFreeImgs = true; - for(size_t j=0; j < hlp->ourImages.size(); ++j) - terrainGraphics[i][j] = hlp->ourImages[j].bitmap; - delete hlp; + edgeFrames[i].resize(sizes.y, frameH, frameH); } + for (int i=0-frameW;i (sizes.x-1) || j < 0 || j > (sizes.y-1)) { - int terBitmapNum = -1; - - auto & rand = CRandomGenerator::getDefault(); - if(i==-1 && j==-1) terBitmapNum = 16; else if(i==-1 && j==(sizes.y)) @@ -280,45 +276,11 @@ void CMapHandler::borderAndTerrainBitmapInit() else terBitmapNum = rand.nextInt(15); - if(terBitmapNum != -1) - { - ttiles[i][j][k].terbitmap = bord->ourImages[terBitmapNum].bitmap; - continue; - } } + edgeFrames[i][j][k] = terBitmapNum; } } } - delete bord; -} - -static void processDef (const ObjectTemplate & objTempl) -{ - if(objTempl.id == Obj::EVENT) - { - graphics->advmapobjGraphics[objTempl.animationFile] = nullptr; - return; - } - CDefEssential * ourDef = graphics->getDef(objTempl); - if(!ourDef) //if object has already set handler (eg. heroes) it should not be overwritten - { - if(objTempl.animationFile.size()) - { - graphics->advmapobjGraphics[objTempl.animationFile] = CDefHandler::giveDefEss(objTempl.animationFile); - } - else - { - logGlobal->warnStream() << "No def name for " << objTempl.id << " " << objTempl.subid; - return; - } - ourDef = graphics->getDef(objTempl); - - } - //alpha transformation - for(auto & elem : ourDef->ourImages) - { - CSDL_Ext::alphaTransform(elem.bitmap); - } } void CMapHandler::initObjectRects() @@ -333,12 +295,19 @@ void CMapHandler::initObjectRects() { continue; } - if (!graphics->getDef(obj)) //try to load it - processDef(obj->appearance); - if (!graphics->getDef(obj)) // stil no graphics? exit + + std::shared_ptr animation = graphics->getAnimation(obj); + + //no animation at all + if(!animation) continue; - const SDL_Surface *bitmap = graphics->getDef(obj)->ourImages[0].bitmap; + //empty animation + if(animation->size(0) == 0) + continue; + + IImage * image = animation->getImage(0,0); + for(int fx=0; fx < obj->getWidth(); ++fx) { for(int fy=0; fy < obj->getHeight(); ++fy) @@ -347,8 +316,8 @@ void CMapHandler::initObjectRects() SDL_Rect cr; cr.w = 32; cr.h = 32; - cr.x = bitmap->w - fx * 32 - 32; - cr.y = bitmap->h - fy * 32 - 32; + cr.x = image->width() - fx * 32 - 32; + cr.y = image->height() - fy * 32 - 32; TerrainTileObject toAdd(obj,cr); @@ -381,9 +350,6 @@ void CMapHandler::init() CStopWatch th; th.getDiff(); - graphics->advmapobjGraphics["AB01_.DEF"] = graphics->boatAnims[0]; - graphics->advmapobjGraphics["AB02_.DEF"] = graphics->boatAnims[1]; - graphics->advmapobjGraphics["AB03_.DEF"] = graphics->boatAnims[2]; // Size of visible terrain. int mapW = conf.go()->ac.advmapW; int mapH = conf.go()->ac.advmapH; @@ -414,12 +380,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); - } + source->draw(targetSurf, destRect, sourceRect); } void CMapHandler::CMapNormalBlitter::init(const MapDrawingInfo * drawingInfo) @@ -594,51 +535,12 @@ 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 +void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) 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); + IImage * scaled = parent->cache.requestWorldViewCacheOrCreate(cacheType, source); - 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); - } -} - -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); - } + if(scaled) + scaled->draw(targetSurf, destRect, sourceRect); } void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const @@ -701,31 +603,30 @@ void CMapHandler::CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf) } } -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, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const { if (moving) return; - CMapBlitter::drawHeroFlag(targetSurf, sourceSurf, sourceRect, destRect, false); + CMapBlitter::drawHeroFlag(targetSurf, source, sourceRect, destRect, false); } -void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const +void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const { if (moving) return; Rect scaledSourceRect(sourceRect->x * info->scale, sourceRect->y * info->scale, sourceRect->w, sourceRect->h); - CMapBlitter::drawObject(targetSurf, sourceSurf, &scaledSourceRect, false); + CMapBlitter::drawObject(targetSurf, source, &scaledSourceRect, false); } void CMapHandler::CMapBlitter::drawTileTerrain(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile2 & tile) const { Rect destRect(realTileRect); - if(tile.terbitmap) //if custom terrain graphic - use it - drawElement(EMapCacheType::TERRAIN_CUSTOM, tile.terbitmap, nullptr, targetSurf, &destRect); - else //use default terrain graphic - 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) @@ -747,7 +648,6 @@ void CMapHandler::CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo) defaultTileRect = Rect(0, 0, tileSize, tileSize); calculateWorldViewCameraPos(); - } SDL_Rect CMapHandler::CMapWorldViewBlitter::clip(SDL_Surface * targetSurf) const @@ -812,7 +712,7 @@ CMapHandler::CMapPuzzleViewBlitter::CMapPuzzleViewBlitter(CMapHandler * parent) void CMapHandler::CMapBlitter::drawFrame(SDL_Surface * targetSurf) const { Rect destRect(realTileRect); - drawElement(EMapCacheType::FRAME, parent->ttiles[pos.x][pos.y][topTile.z].terbitmap, nullptr, targetSurf, &destRect); + drawElement(EMapCacheType::FRAME, parent->egdeImages[parent->edgeFrames[pos.x][pos.y][topTile.z]], nullptr, targetSurf, &destRect); } void CMapHandler::CMapBlitter::drawOverlayEx(SDL_Surface * targetSurf) @@ -820,15 +720,15 @@ void CMapHandler::CMapBlitter::drawOverlayEx(SDL_Surface * targetSurf) //nothing to do here } -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, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const { - drawElement(EMapCacheType::HERO_FLAGS, sourceSurf, sourceRect, targetSurf, destRect, false); + drawElement(EMapCacheType::HERO_FLAGS, source, sourceRect, targetSurf, destRect); } -void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const +void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const { Rect dstRect(realTileRect); - drawElement(EMapCacheType::OBJECTS, sourceSurf, sourceRect, targetSurf, &dstRect, true); + drawElement(EMapCacheType::OBJECTS, source, sourceRect, targetSurf, &dstRect); } void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const @@ -858,18 +758,6 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra continue; } - if (!graphics->getDef(obj)) - processDef(obj->appearance); - if (!graphics->getDef(obj)) - { - if (!obj->appearance.animationFile.empty()) - logGlobal->errorStream() << "Failed to load image " << obj->appearance.animationFile; - else - logGlobal->warnStream() << boost::format("Def name for obj %d (%d,%d) is empty!") % obj->id % obj->ID % obj->subID; - - continue; - } - if (!canDrawObject(obj)) continue; @@ -901,33 +789,47 @@ 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 { + const NeighborTilesInfo neighborInfo(pos, parent->sizes, *info->visibilityMap); + + int retBitmapID = neighborInfo.getBitmapID();// >=0 -> partial hide, <0 - full hide + if (retBitmapID < 0) + retBitmapID = - parent->hideBitmap[pos.x][pos.y][pos.z] - 1; //fully hidden + + const IImage * image = nullptr; + + if (retBitmapID >= 0) + image = parent->FoWpartialHide.at(retBitmapID); + else + image = parent->FoWfullHide.at(-retBitmapID - 1); + Rect destRect(realTileRect); - std::pair hide = getVisBitmap(); - drawElement(EMapCacheType::FOW, hide.first, nullptr, targetSurf, &destRect, hide.second); + drawElement(EMapCacheType::FOW, image, nullptr, targetSurf, &destRect); } void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingInfo * info) @@ -1062,20 +964,24 @@ CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findHeroBitmap(const CGH } //pick graphics of hero (or boat if hero is sailing) - CDefEssential * def = nullptr; + std::shared_ptr animation; if (hero->boat) - def = graphics->boatAnims[hero->boat->subID]; + animation = graphics->boatAnimations[hero->boat->subID]; else - def = graphics->heroAnims[hero->appearance.animationFile]; + animation = graphics->heroAnimations[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) + int group = getHeroFrameGroup(hero->moveDir, moving); + + if(animation->size(group) > 0) { - auto heroBitmap = def->ourImages[index + framesOffset].bitmap; - auto flagBitmap = findFlagBitmap(hero, anim, &hero->tempOwner, index + 35); - return CMapHandler::AnimBitmapHolder(heroBitmap, flagBitmap, moving); + int frame = anim % animation->size(group); + IImage * heroImage = animation->getImage(frame, group); + + //get flag overlay only if we have main image + IImage * flagImage = findFlagBitmap(hero, anim, &hero->tempOwner, group); + + return CMapHandler::AnimBitmapHolder(heroImage, flagImage, moving); } } return CMapHandler::AnimBitmapHolder(); @@ -1083,54 +989,57 @@ CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findHeroBitmap(const CGH 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) + auto animation = graphics->boatAnimations.at(boat->subID); + int group = getHeroFrameGroup(boat->direction, false); + if(animation->size(group) > 0) + return CMapHandler::AnimBitmapHolder(animation->getImage(anim % animation->size(group), group)); + else 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 +IImage * CMapHandler::CMapBlitter::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const { if (!hero) return nullptr; if (hero->boat) - return findBoatFlagBitmap(hero->boat, anim, color, indexOffset, hero->moveDir); - return findHeroFlagBitmap(hero, anim, color, indexOffset); + return findBoatFlagBitmap(hero->boat, anim, color, group, hero->moveDir); + return findHeroFlagBitmap(hero, anim, color, group); } -SDL_Surface * CMapHandler::CMapBlitter::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int indexOffset) const +IImage * CMapHandler::CMapBlitter::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const { - return findFlagBitmapInternal(graphics->flags4[color->getNum()], anim, indexOffset, hero->moveDir, !hero->isStanding); + return findFlagBitmapInternal(graphics->heroFlagAnimations.at(color->getNum()), anim, group, hero->moveDir, !hero->isStanding); } -SDL_Surface * CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int indexOffset, ui8 dir) const +IImage * CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int group, ui8 dir) const { - std::vector Graphics::*flg = nullptr; - switch (boat->subID) + int boatType = boat->subID; + if(boatType < 0 || boatType >= graphics->boatFlagAnimations.size()) { - 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; + logGlobal->errorStream() << "Not supported boat subtype: " << boat->subID; + return nullptr; } - return findFlagBitmapInternal((graphics->*flg)[color->getNum()], anim, indexOffset, dir, false); + + const auto & subtypeFlags = graphics->boatFlagAnimations.at(boatType); + + int colorIndex = color->getNum(); + + if(colorIndex < 0 || colorIndex >= subtypeFlags.size()) + { + logGlobal->errorStream() << "Invalid player color " << colorIndex; + return nullptr; + } + + return findFlagBitmapInternal(subtypeFlags.at(colorIndex), anim, group, dir, false); } -SDL_Surface * CMapHandler::CMapBlitter::findFlagBitmapInternal(const CDefEssential * def, int anim, int indexOffset, ui8 dir, bool moving) const +IImage * CMapHandler::CMapBlitter::findFlagBitmapInternal(std::shared_ptr animation, int anim, int group, 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(iter - def->ourImages.begin()); + if(moving) + return animation->getImage(anim % animation->size(group), group); + else + return animation->getImage((anim / 4) % animation->size(group), group); } CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findObjectBitmap(const CGObjectInstance * obj, int anim) const @@ -1143,14 +1052,11 @@ CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findObjectBitmap(const C return findBoatBitmap(static_cast(obj), anim); // normal object + std::shared_ptr animation = graphics->getAnimation(obj); + IImage * bitmap = animation->getImage((anim + getPhaseShift(obj)) % animation->size()); - const std::vector &ourImages = graphics->getDef(obj)->ourImages; - SDL_Surface *bitmap = ourImages[(anim + getPhaseShift(obj)) % ourImages.size()].bitmap; + bitmap->setFlagColor(obj->tempOwner); - //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); } @@ -1179,7 +1085,7 @@ bool CMapHandler::CMapBlitter::canDrawCurrentTile() const return !neighbors.areAllHidden(); } -ui8 CMapHandler::CMapBlitter::getHeroFrameNum(ui8 dir, bool isMoving) const +ui8 CMapHandler::CMapBlitter::getHeroFrameGroup(ui8 dir, bool isMoving) const { if(isMoving) { @@ -1193,26 +1099,6 @@ ui8 CMapHandler::CMapBlitter::getHeroFrameNum(ui8 dir, bool isMoving) const } } -std::pair CMapHandler::CMapBlitter::getVisBitmap() const -{ - const NeighborTilesInfo neighborInfo(pos, parent->sizes, *info->visibilityMap); - - int retBitmapID = neighborInfo.getBitmapID();// >=0 -> partial hide, <0 - full hide - if (retBitmapID < 0) - { - retBitmapID = - parent->hideBitmap[pos.x][pos.y][pos.z] - 1; //fully hidden - } - - if (retBitmapID >= 0) - { - return std::make_pair(graphics->FoWpartialHide->ourImages[retBitmapID].bitmap, true); - } - else - { - return std::make_pair(graphics->FoWfullHide->ourImages[-retBitmapID - 1].bitmap, false); - } -} - bool CMapHandler::updateObjectsFade() { for (auto iter = fadeAnims.begin(); iter != fadeAnims.end(); ) @@ -1263,13 +1149,14 @@ bool CMapHandler::startObjectFade(TerrainTileObject & obj, bool in, int3 pos) 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); + objData.objBitmap->draw(fadeBitmap,0,0,&objSrcRect); + 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); + objData.flagBitmap->draw(fadeBitmap,0,0, &flagSrcRect); } } auto anim = new CFadeAnimation(); @@ -1287,12 +1174,18 @@ bool CMapHandler::startObjectFade(TerrainTileObject & obj, bool in, int3 pos) bool CMapHandler::printObject(const CGObjectInstance *obj, bool fadein /* = false */) { - if (!graphics->getDef(obj)) - processDef(obj->appearance); + auto animation = graphics->getAnimation(obj); - SDL_Surface *bitmap = graphics->getDef(obj)->ourImages[0].bitmap; - const int tilesW = bitmap->w/32; - const int tilesH = bitmap->h/32; + if(!animation) + return false; + + IImage * bitmap = animation->getImage(0); + + if(!bitmap) + return false; + + const int tilesW = bitmap->width()/32; + const int tilesH = bitmap->height()/32; for(int fx=0; fxx<0) - { - val->w += val->x; - val->x = ext->x; - } - else - { - val->x += ext->x; - } - if(val->y<0) - { - val->h += val->y; - val->y = ext->y; - } - else - { - val->y += ext->y; - } - - if(val->x+val->w > ext->x+ext->w) - { - val->w = ext->x+ext->w-val->x; - } - if(val->y+val->h > ext->y+ext->h) - { - val->h = ext->y+ext->h-val->y; - } - - //for sign problems - if(val->h > 20000 || val->w > 20000) - { - val->h = val->w = 0; - } - } -} - -ui8 CMapHandler::getDir(const int3 &a, const int3 &b) -{ - if(a.z!=b.z) - return -1; //error! - if(a.x==b.x+1 && a.y==b.y+1) //lt - return 0; - - else if(a.x==b.x && a.y==b.y+1) //t - return 1; - - else if(a.x==b.x-1 && a.y==b.y+1) //rt - return 2; - - else if(a.x==b.x-1 && a.y==b.y) //r - return 3; - - else if(a.x==b.x-1 && a.y==b.y-1) //rb - return 4; - - else if(a.x==b.x && a.y==b.y-1) //b - return 5; - - else if(a.x==b.x+1 && a.y==b.y-1) //lb - return 6; - - else if(a.x==b.x+1 && a.y==b.y) //l - return 7; - - 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 -{ - //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); } } CMapHandler::~CMapHandler() { - delete graphics->FoWfullHide; - delete graphics->FoWpartialHide; -// if (fadingOffscreenBitmapSurface) -// delete fadingOffscreenBitmapSurface; - delete normalBlitter; 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() { frameW = frameH = 0; - graphics->FoWfullHide = nullptr; - graphics->FoWpartialHide = nullptr; normalBlitter = new CMapNormalBlitter(this); worldViewBlitter = new CMapWorldViewBlitter(this); puzzleViewBlitter = new CMapPuzzleViewBlitter(this); fadeAnimCounter = 0; + + egdeAnimation = make_unique("EDG"); + egdeAnimation->preload(); } void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terName ) @@ -1596,18 +1397,9 @@ void CMapHandler::discardWorldViewCache() void CMapHandler::CMapCache::discardWorldViewCache() { - for (auto &cacheDataPair : data) - { - for (auto &cacheEntryPair : cacheDataPair.second) - { - if (cacheEntryPair.second) - { - SDL_FreeSurface(cacheEntryPair.second); - } - } - data[cacheDataPair.first].clear(); - } - logGlobal->debugStream() << "Discarded world view cache"; + for(auto & cache : data) + cache.clear(); + logAnim->debug("Discarded world view cache"); } void CMapHandler::CMapCache::updateWorldViewScale(float scale) @@ -1617,56 +1409,25 @@ void CMapHandler::CMapCache::updateWorldViewScale(float scale) worldViewCachedScale = scale; } -void CMapHandler::CMapCache::removeFromWorldViewCache(CMapHandler::EMapCacheType type, intptr_t key) +IImage * CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CMapHandler::EMapCacheType type, const IImage * fullSurface) { - auto iter = data[type].find(key); - if (iter != data[type].end()) + intptr_t key = (intptr_t) fullSurface; + auto & cache = data[(ui8)type]; + + auto iter = cache.find(key); + if(iter == cache.end()) { - SDL_FreeSurface((*iter).second); - data[type].erase(iter); + auto scaled = fullSurface->scaleFast(worldViewCachedScale); + IImage * ret = scaled.get(); + cache[key] = std::move(scaled); + return ret; + } + else + { + return (*iter).second.get(); } } -SDL_Surface * CMapHandler::CMapCache::requestWorldViewCache(CMapHandler::EMapCacheType type, intptr_t key) -{ - auto iter = data[type].find(key); - if (iter == data[type].end()) - return nullptr; - return (*iter).second; -} - -SDL_Surface * CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CMapHandler::EMapCacheType type, intptr_t key, SDL_Surface * fullSurface, float scale) -{ - auto cached = requestWorldViewCache(type, key); - if (cached) - return cached; - - auto scaled = CSDL_Ext::scaleSurfaceFast(fullSurface, fullSurface->w * scale, fullSurface->h * scale); - if (scaled->format && scaled->format->palette) // fix color keying, because SDL loses it at this point - CSDL_Ext::setColorKey(scaled, scaled->format->palette->colors[0]); - return cacheWorldViewEntry(type, key, scaled); -} - -SDL_Surface *CMapHandler::CMapCache::cacheWorldViewEntry(CMapHandler::EMapCacheType type, intptr_t key, SDL_Surface * entry) -{ - if (!entry) - return nullptr; - if (requestWorldViewCache(type, key)) // valid cache already present, no need to do it again - return requestWorldViewCache(type, key); - - data[type][key] = entry; - return entry; -} - -intptr_t CMapHandler::CMapCache::genKey(intptr_t realPtr, ui8 mod) -{ - return (intptr_t)(realPtr ^ (mod << (sizeof(intptr_t) - 2))); // maybe some cleaner method to pack rotation into cache key? -} - -TerrainTile2::TerrainTile2() - :terbitmap(nullptr) -{} - bool CMapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b) { if (!a) diff --git a/client/mapHandler.h b/client/mapHandler.h index bdaaf63ff..5e7e947b2 100644 --- a/client/mapHandler.h +++ b/client/mapHandler.h @@ -20,12 +20,9 @@ class CGObjectInstance; class CGHeroInstance; class CGBoat; class CMap; -class CGDefInfo; -class CDefHandler; struct TerrainTile; struct SDL_Surface; struct SDL_Rect; -class CDefEssential; class CAnimation; class IImage; class CFadeAnimation; @@ -80,10 +77,7 @@ struct TerrainTileObject struct TerrainTile2 { - SDL_Surface * terbitmap; //bitmap of terrain - std::vector objects; //pointers to objects being on this tile with rects to be easier to blit this tile on screen - TerrainTile2(); }; struct MapDrawingInfo @@ -133,16 +127,6 @@ template class PseudoV { public: PseudoV() : offset(0) { } - PseudoV(std::vector &src, int rest, int before, int after, const T& fill) : offset(before) - { - inver.resize(before + rest + after); - for(int i=0; i> data; + std::array< std::map>, (ui8)EMapCacheType::AFTER_LAST> data; float worldViewCachedScale; public: /// destroys all cached data (frees surfaces) void discardWorldViewCache(); /// updates scale and determines if currently cached data is still valid void updateWorldViewScale(float scale); - void removeFromWorldViewCache(EMapCacheType type, intptr_t key); - /// asks for cached data; @returns cached surface or nullptr if data is not in cache - SDL_Surface * requestWorldViewCache(EMapCacheType type, intptr_t key); - /// asks for cached data; @returns cached data if found, new scaled surface otherwise - SDL_Surface * requestWorldViewCacheOrCreate(EMapCacheType type, intptr_t key, SDL_Surface * fullSurface, float scale); - SDL_Surface * cacheWorldViewEntry(EMapCacheType type, intptr_t key, SDL_Surface * entry); - intptr_t genKey(intptr_t realPtr, ui8 mod); + /// asks for cached data; @returns cached data if found, new scaled surface otherwise, may return nullptr in case of scaling error + IImage * requestWorldViewCacheOrCreate(EMapCacheType type, const IImage * fullSurface); }; - /// helper struct to pass around resolved bitmaps of an object; surfaces can be nullptr if object doesn't have bitmap of that type + /// helper struct to pass around resolved bitmaps of an object; images 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) + IImage * objBitmap; // main object bitmap + IImage * 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) + AnimBitmapHolder(IImage * objBitmap_ = nullptr, IImage * flagBitmap_ = nullptr, bool moving = false) : objBitmap(objBitmap_), flagBitmap(flagBitmap_), isMoving(moving) {} }; - class CMapBlitter { protected: @@ -223,8 +201,7 @@ 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; + virtual void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const = 0; // first drawing pass @@ -236,8 +213,8 @@ class CMapHandler 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) virtual void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const; - virtual void drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const; - virtual void drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const; + virtual void drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const; + virtual void drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const; // second drawing pass @@ -262,9 +239,7 @@ class CMapHandler /// calculates clip region for map viewport virtual SDL_Rect clip(SDL_Surface * targetSurf) const = 0; - virtual ui8 getHeroFrameNum(ui8 dir, bool isMoving) const; - ///returns appropriate bitmap and info if alpha blitting is necessary - virtual std::pair getVisBitmap() const; + virtual ui8 getHeroFrameGroup(ui8 dir, bool isMoving) const; virtual ui8 getPhaseShift(const CGObjectInstance *object) const; virtual bool canDrawObject(const CGObjectInstance * obj) const; @@ -273,11 +248,10 @@ class CMapHandler // 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; + IImage * findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const; + IImage * findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const; + IImage * findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int group, ui8 dir) const; + IImage * findFlagBitmapInternal(std::shared_ptr animation, int anim, int group, ui8 dir, bool moving) const; public: CMapBlitter(CMapHandler * p) : parent(p) {} @@ -285,15 +259,12 @@ class CMapHandler 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; - }; 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; @@ -307,22 +278,15 @@ 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, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override; - void drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) 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; void drawFrame(SDL_Surface * targetSurf) const override {} void drawOverlayEx(SDL_Surface * targetSurf) override; void init(const MapDrawingInfo * info) override; SDL_Rect clip(SDL_Surface * targetSurf) const override; - -// ui8 getHeroFrameNum(ui8 dir, bool isMoving) 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, - float scale, SDL_Rect * dstRect, SDL_Rect * srcRect = nullptr) const; void calculateWorldViewCameraPos(); public: CMapWorldViewBlitter(CMapHandler * parent); @@ -353,6 +317,11 @@ class CMapHandler CMapBlitter * resolveBlitter(const MapDrawingInfo * info) const; bool updateObjectsFade(); bool startObjectFade(TerrainTileObject & obj, bool in, int3 pos); + + void initObjectRects(); + void initBorderGraphics(); + void initTerrainGraphics(); + void prepareFOWDefs(); public: PseudoV< PseudoV< PseudoV > > ttiles; //informations about map tiles int3 sizes; //map size (x = width, y = height, z = number of levels) @@ -373,13 +342,30 @@ public: int offsetX; int offsetY; - //std::set usedHeroes; + //terrain graphics - std::vector > terrainGraphics; // [terrain id] [view type] [rotation type] - std::vector roadDefs; - std::vector staticRiverDefs; + typedef std::vector, 4>> TFlippedAnimations; //[type, rotation] + typedef std::vector>> TFlippedCache;//[type, view type, rotation] - std::vector > > hideBitmap; //specifies number of graphic that should be used to fully hide a tile + 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; + std::vector > > hideBitmap; //frame indexes (in FoWfullHide) of graphic that should be used to fully hide a tile + + std::vector FoWpartialHide; + + //edge graphics + std::unique_ptr egdeAnimation; + std::vector egdeImages;//cache of links to egdeAnimation (for faster access) + PseudoV< PseudoV< PseudoV > > edgeFrames; //frame indexes (in egdeImages) of tile outside of map mutable std::map animationPhase; @@ -387,21 +373,12 @@ public: ~CMapHandler(); //d-tor 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 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 removeObject(CGObjectInstance * obj, bool fadeout = false); //removes object from each place in VCMI (I hope) void init(); - void calculateBlockedPos(); - void initObjectRects(); - void borderAndTerrainBitmapInit(); - void roadsRiverTerrainInit(); - void prepareFOWDefs(); EMapAnimRedrawStatus drawTerrainRectNew(SDL_Surface * targetSurface, const MapDrawingInfo * info, bool redrawOnlyAnim = false); void updateWater(); - 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] /// determines if the map is ready to handle new hero movement (not available during fading animations) bool canStartHeroMovement(); diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index f450f688b..8d06cbbd0 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -8,7 +8,6 @@ #include "../CGameInfo.h" #include "../CMusicHandler.h" -#include "../CDefHandler.h" #include "../CPlayerInterface.h" #include "../CPreGame.h" #include "../Graphics.h" diff --git a/client/widgets/TextControls.cpp b/client/widgets/TextControls.cpp index e245735e2..cc3b2175f 100644 --- a/client/widgets/TextControls.cpp +++ b/client/widgets/TextControls.cpp @@ -107,7 +107,7 @@ void CMultiLineLabel::setText(const std::string &Txt) void CTextContainer::blitLine(SDL_Surface *to, Rect destRect, std::string what) { - const IFont * f = graphics->fonts[font]; + const auto f = graphics->fonts[font]; Point where = destRect.topLeft(); // input is rect in which given text should be placed @@ -164,7 +164,7 @@ void CMultiLineLabel::showAll(SDL_Surface * to) { CIntObject::showAll(to); - const IFont * f = graphics->fonts[font]; + const auto f = graphics->fonts[font]; // calculate which lines should be visible int totalLines = lines.size(); @@ -201,7 +201,7 @@ void CMultiLineLabel::splitText(const std::string &Txt) { lines.clear(); - const IFont * f = graphics->fonts[font]; + const auto f = graphics->fonts[font]; int lineHeight = f->getLineHeight(); lines = CMessage::breakText(Txt, pos.w, font); @@ -427,7 +427,7 @@ CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf) void CTextInput::focusGot() { - CSDL_Ext::startTextInput(&pos); + CSDL_Ext::startTextInput(&pos); } void CTextInput::focusLost() @@ -461,7 +461,7 @@ void CTextInput::keyPressed( const SDL_KeyboardEvent & key ) } bool redrawNeeded = false; - + switch(key.keysym.sym) { case SDLK_DELETE: // have index > ' ' so it won't be filtered out by default section @@ -476,7 +476,7 @@ void CTextInput::keyPressed( const SDL_KeyboardEvent & key ) { Unicode::trimRight(text); redrawNeeded = true; - } + } break; default: break; @@ -486,7 +486,7 @@ void CTextInput::keyPressed( const SDL_KeyboardEvent & key ) { redraw(); cb(text); - } + } } void CTextInput::setText( const std::string &nText, bool callCb ) @@ -500,7 +500,7 @@ bool CTextInput::captureThisEvent(const SDL_KeyboardEvent & key) { if(key.keysym.sym == SDLK_RETURN || key.keysym.sym == SDLK_KP_ENTER || key.keysym.sym == SDLK_ESCAPE) return false; - + return true; } @@ -509,15 +509,15 @@ void CTextInput::textInputed(const SDL_TextInputEvent & event) if(!focus) return; std::string oldText = text; - - text += event.text; - + + text += event.text; + filters(text,oldText); if (text != oldText) { redraw(); cb(text); - } + } newText = ""; } @@ -525,10 +525,10 @@ void CTextInput::textEdited(const SDL_TextEditingEvent & event) { if(!focus) return; - + newText = event.text; redraw(); - cb(text+newText); + cb(text+newText); } void CTextInput::filenameFilter(std::string & text, const std::string &) @@ -586,7 +586,7 @@ CFocusable::~CFocusable() { focusLost(); inputWithFocus = nullptr; - } + } focusables -= this; } @@ -602,7 +602,7 @@ void CFocusable::giveFocus() focus = true; inputWithFocus = this; focusGot(); - redraw(); + redraw(); } void CFocusable::moveFocus() diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index d14e3a8c4..b646efce7 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -9,7 +9,6 @@ #include "CTradeWindow.h" #include "../CBitmapHandler.h" -#include "../CDefHandler.h" #include "../CGameInfo.h" #include "../CMessage.h" #include "../CMusicHandler.h" diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index a7876b5f5..0f091b894 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -457,12 +457,6 @@ std::vector < const CGObjectInstance * > CGameInfoCallback::getFlaggableObjects( for(const CGObjectInstance *obj : t->blockingObjects) if(obj->tempOwner != PlayerColor::UNFLAGGABLE) ret.push_back(obj); -// const std::vector < std::pair > & objs = CGI->mh->ttiles[pos.x][pos.y][pos.z].objects; -// for(size_t b=0; btempOwner!=254 && !((objs[b].first->defInfo->blockMap[pos.y - objs[b].first->pos.y + 5] >> (objs[b].first->pos.x - pos.x)) & 1)) -// ret.push_back(CGI->mh->ttiles[pos.x][pos.y][pos.z].objects[b].first); -// } return ret; }