diff --git a/client/CMessage.cpp b/client/CMessage.cpp index ce670af5e..01d42cb97 100644 --- a/client/CMessage.cpp +++ b/client/CMessage.cpp @@ -64,7 +64,7 @@ namespace std::array, PlayerColor::PLAYER_LIMIT_I> dialogBorders; std::array>, PlayerColor::PLAYER_LIMIT_I> piecesOfBox; - SDL_Surface * background = nullptr;//todo: should be CFilledTexture + std::shared_ptr background;//todo: should be CFilledTexture } void CMessage::init() @@ -84,27 +84,27 @@ void CMessage::init() } } - background = BitmapHandler::loadBitmap("DIBOXBCK.BMP"); + background = IImage::createFromFile("DIBOXBCK.BMP"); } void CMessage::dispose() { for(auto & item : dialogBorders) item.reset(); - SDL_FreeSurface(background); } SDL_Surface * CMessage::drawDialogBox(int w, int h, PlayerColor playerColor) { //prepare surface SDL_Surface * ret = CSDL_Ext::newSurface(w,h); - for (int i=0; iw)//background + for (int i=0; iwidth())//background { - for (int j=0; jh) + for (int j=0; jheight()) { - CSDL_Ext::blitSurface(background, ret, Point(i,j)); + background->draw(ret, i, j); } } + drawBorder(playerColor, ret, w, h); return ret; } diff --git a/client/battle/BattleStacksController.cpp b/client/battle/BattleStacksController.cpp index b25861676..369554ed1 100644 --- a/client/battle/BattleStacksController.cpp +++ b/client/battle/BattleStacksController.cpp @@ -89,10 +89,10 @@ BattleStacksController::BattleStacksController(BattleInterface & owner): static const auto shifterNegative = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 1.0f, 0.2f, 0.2f ); static const auto shifterNeutral = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 1.0f, 1.0f, 0.2f ); - amountNormal->adjustPalette(shifterNormal); - amountPositive->adjustPalette(shifterPositive); - amountNegative->adjustPalette(shifterNegative); - amountEffNeutral->adjustPalette(shifterNeutral); + amountNormal->adjustPalette(shifterNormal, 0); + amountPositive->adjustPalette(shifterPositive, 0); + amountNegative->adjustPalette(shifterNegative, 0); + amountEffNeutral->adjustPalette(shifterNeutral, 0); //Restore border color {255, 231, 132, 255} to its original state amountNormal->resetPalette(26); diff --git a/client/battle/CreatureAnimation.cpp b/client/battle/CreatureAnimation.cpp index 0dda6089a..c5d7abbc0 100644 --- a/client/battle/CreatureAnimation.cpp +++ b/client/battle/CreatureAnimation.cpp @@ -345,7 +345,7 @@ void CreatureAnimation::nextFrame(Canvas & canvas, const ColorFilter & shifter, genSpecialPalette(SpecialPalette); image->setSpecialPallete(SpecialPalette); - image->adjustPalette(shifter); + image->adjustPalette(shifter, 8); canvas.draw(image, pos.topLeft(), Rect(0, 0, pos.w, pos.h)); diff --git a/client/gui/CAnimation.cpp b/client/gui/CAnimation.cpp index 9bb926adf..efaea8da1 100644 --- a/client/gui/CAnimation.cpp +++ b/client/gui/CAnimation.cpp @@ -108,7 +108,7 @@ public: void verticalFlip() override; void shiftPalette(int from, int howMany) override; - void adjustPalette(const ColorFilter & shifter) override; + void adjustPalette(const ColorFilter & shifter, size_t colorsToSkip) override; void resetPalette(int colorID) override; void resetPalette() override; @@ -807,15 +807,15 @@ void SDLImage::shiftPalette(int from, int howMany) } } -void SDLImage::adjustPalette(const ColorFilter & shifter) +void SDLImage::adjustPalette(const ColorFilter & shifter, size_t colorsToSkip) { if(originalPalette == nullptr) return; SDL_Palette* palette = surf->format->palette; - // Note: here we skip the first 8 colors in the palette that predefined in H3Palette - for(int i = 8; i < palette->ncolors; i++) + // Note: here we skip first colors in the palette that are predefined in H3 images + for(int i = colorsToSkip; i < palette->ncolors; i++) { palette->colors[i] = shifter.shiftColor(originalPalette->colors[i]); } diff --git a/client/gui/CAnimation.h b/client/gui/CAnimation.h index 58894e80b..e5881c65f 100644 --- a/client/gui/CAnimation.h +++ b/client/gui/CAnimation.h @@ -63,7 +63,7 @@ public: //only indexed bitmaps, 16 colors maximum virtual void shiftPalette(int from, int howMany) = 0; - virtual void adjustPalette(const ColorFilter & shifter) = 0; + virtual void adjustPalette(const ColorFilter & shifter, size_t colorsToSkip) = 0; virtual void resetPalette(int colorID) = 0; virtual void resetPalette() = 0; diff --git a/client/gui/SDL_Extensions.cpp b/client/gui/SDL_Extensions.cpp index f1efad669..abfc10d17 100644 --- a/client/gui/SDL_Extensions.cpp +++ b/client/gui/SDL_Extensions.cpp @@ -880,26 +880,6 @@ void CSDL_Ext::fillRect( SDL_Surface *dst, const Rect & dstrect, const SDL_Color SDL_FillRect(dst, &newRect, sdlColor); } -void CSDL_Ext::fillTexture(SDL_Surface *dst, SDL_Surface * src) -{ - SDL_Rect srcRect; - SDL_Rect dstRect; - - SDL_GetClipRect(src, &srcRect); - SDL_GetClipRect(dst, &dstRect); - - for (int y=dstRect.y; y < dstRect.y + dstRect.h; y+=srcRect.h) - { - for (int x=dstRect.x; x < dstRect.x + dstRect.w; x+=srcRect.w) - { - int xLeft = std::min(srcRect.w, dstRect.x + dstRect.w - x); - int yLeft = std::min(srcRect.h, dstRect.y + dstRect.h - y); - SDL_Rect currentDest{x, y, xLeft, yLeft}; - SDL_BlitSurface(src, &srcRect, dst, ¤tDest); - } - } -} - SDL_Color CSDL_Ext::makeColor(ui8 r, ui8 g, ui8 b, ui8 a) { SDL_Color ret = {r, g, b, a}; diff --git a/client/gui/SDL_Extensions.h b/client/gui/SDL_Extensions.h index 4dbec2382..b63ab8fef 100644 --- a/client/gui/SDL_Extensions.h +++ b/client/gui/SDL_Extensions.h @@ -128,8 +128,6 @@ typedef void (*TColorPutterAlpha)(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, void fillSurface(SDL_Surface *dst, const SDL_Color & color); void fillRect(SDL_Surface *dst, const Rect & dstrect, const SDL_Color & color); - //fill dest image with source texture. - void fillTexture(SDL_Surface *dst, SDL_Surface * sourceTexture); void updateRect(SDL_Surface *surface, const Rect & rect); diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index 2d1a4a6e7..3c0c053f9 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -899,22 +899,22 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn { if(parent->map->getTile(int3(pos.x, pos.y, pos.z)).blocked) //temporary hiding blocked positions { - static SDL_Surface * block = nullptr; + static std::shared_ptr block; if (!block) - block = BitmapHandler::loadBitmap("blocked"); + block = IImage::createFromFile("blocked"); - CSDL_Ext::blitSurface(block, targetSurf, realTileRect.topLeft()); + block->draw(targetSurf, realTileRect.x, realTileRect.y); } } if (settings["session"]["showVisit"].Bool()) { if(parent->map->getTile(int3(pos.x, pos.y, pos.z)).visitable) //temporary hiding visitable positions { - static SDL_Surface * visit = nullptr; + static std::shared_ptr visit; if (!visit) - visit = BitmapHandler::loadBitmap("visitable"); + visit = IImage::createFromFile("visitable"); - CSDL_Ext::blitSurface(visit, targetSurf, realTileRect.topLeft()); + visit->draw(targetSurf, realTileRect.x, realTileRect.y); } } } diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index a9f269ff3..6a6fd19bd 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -23,6 +23,7 @@ #include "../gui/CGuiHandler.h" #include "../gui/SDL_Pixels.h" +#include "../gui/CAnimation.h" #include "../windows/InfoWindows.h" #include "../windows/CAdvmapInterface.h" @@ -1168,9 +1169,9 @@ void CInGameConsole::refreshEnteredText() statusbar->setEnteredText(enteredText); } -CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position) - : CIntObject(), - background(bg) +CAdvMapPanel::CAdvMapPanel(std::shared_ptr bg, Point position) + : CIntObject() + , background(bg) { defActions = 255; recActions = 255; @@ -1178,17 +1179,11 @@ CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position) pos.y += position.y; if (bg) { - pos.w = bg->w; - pos.h = bg->h; + pos.w = bg->width(); + pos.h = bg->height(); } } -CAdvMapPanel::~CAdvMapPanel() -{ - if (background) - SDL_FreeSurface(background); -} - void CAdvMapPanel::addChildColorableButton(std::shared_ptr button) { colorableButtons.push_back(button); @@ -1206,7 +1201,7 @@ void CAdvMapPanel::setPlayerColor(const PlayerColor & clr) void CAdvMapPanel::showAll(SDL_Surface * to) { if(background) - CSDL_Ext::blitAt(background, pos.x, pos.y, to); + background->draw(to, pos.x, pos.y); CIntObject::showAll(to); } @@ -1219,7 +1214,7 @@ void CAdvMapPanel::addChildToPanel(std::shared_ptr obj, ui8 actions) addChild(obj.get(), false); } -CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color) +CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr _icons, std::shared_ptr bg, Point position, int spaceBottom, const PlayerColor &color) : CAdvMapPanel(bg, position), icons(_icons) { OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); diff --git a/client/widgets/AdventureMapClasses.h b/client/widgets/AdventureMapClasses.h index 921f5ca1e..81bc9727f 100644 --- a/client/widgets/AdventureMapClasses.h +++ b/client/widgets/AdventureMapClasses.h @@ -35,6 +35,7 @@ class CComponent; class CHeroTooltip; class CTownTooltip; class CTextBox; +class IImage; /// Base UI Element for hero\town lists class CList : public CIntObject @@ -370,10 +371,9 @@ class CAdvMapPanel : public CIntObject std::vector> colorableButtons; std::vector> otherObjects; /// the surface passed to this obj will be freed in dtor - SDL_Surface * background; + std::shared_ptr background; public: - CAdvMapPanel(SDL_Surface * bg, Point position); - virtual ~CAdvMapPanel(); + CAdvMapPanel(std::shared_ptr bg, Point position); void addChildToPanel(std::shared_ptr obj, ui8 actions = 0); void addChildColorableButton(std::shared_ptr button); @@ -394,7 +394,7 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel std::shared_ptr backgroundFiller; std::shared_ptr icons; public: - CAdvMapWorldViewPanel(std::shared_ptr _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color); + CAdvMapWorldViewPanel(std::shared_ptr _icons, std::shared_ptr bg, Point position, int spaceBottom, const PlayerColor &color); virtual ~CAdvMapWorldViewPanel(); void addChildIcon(std::pair data, int indexOffset); diff --git a/client/widgets/Images.cpp b/client/widgets/Images.cpp index 445069d16..4e2f32652 100644 --- a/client/widgets/Images.cpp +++ b/client/widgets/Images.cpp @@ -113,21 +113,21 @@ void CPicture::colorize(PlayerColor player) CFilledTexture::CFilledTexture(std::string imageName, Rect position): CIntObject(0, position.topLeft()), - texture(BitmapHandler::loadBitmap(imageName)) + texture(IImage::createFromFile(imageName)) { pos.w = position.w; pos.h = position.h; } -CFilledTexture::~CFilledTexture() -{ - SDL_FreeSurface(texture); -} - void CFilledTexture::showAll(SDL_Surface *to) { CSDL_Ext::CClipRectGuard guard(to, pos); - CSDL_Ext::fillTexture(to, texture); + + for (int y=pos.top(); y < pos.bottom(); y+= texture->height()) + { + for (int x=pos.left(); x < pos.right(); x+=texture->width()) + texture->draw(to, x, y); + } } CAnimImage::CAnimImage(const std::string & name, size_t Frame, size_t Group, int x, int y, ui8 Flags): diff --git a/client/widgets/Images.h b/client/widgets/Images.h index 1ac5bbce5..be23dfec9 100644 --- a/client/widgets/Images.h +++ b/client/widgets/Images.h @@ -68,11 +68,11 @@ public: /// area filled with specific texture class CFilledTexture : public CIntObject { - SDL_Surface * texture; + std::shared_ptr texture; public: CFilledTexture(std::string imageName, Rect position); - ~CFilledTexture(); + void showAll(SDL_Surface *to) override; }; diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index ba1085b4d..0b76b654a 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -566,10 +566,10 @@ CAdvMapInt::CAdvMapInt(): pos.h = screen->h; strongInterest = true; // handle all mouse move events to prevent dead mouse move space in fullscreen mode townList.onSelect = std::bind(&CAdvMapInt::selectionChanged,this); - bg = BitmapHandler::loadBitmap(ADVOPT.mainGraphic); + bg = IImage::createFromFile(ADVOPT.mainGraphic); if(!ADVOPT.worldViewGraphic.empty()) { - bgWorldView = BitmapHandler::loadBitmap(ADVOPT.worldViewGraphic); + bgWorldView = IImage::createFromFile(ADVOPT.worldViewGraphic); } else { @@ -579,7 +579,7 @@ CAdvMapInt::CAdvMapInt(): if (!bgWorldView) { logGlobal->warn("bgWorldView not defined in resolution config; fallback to VWorld.bmp"); - bgWorldView = BitmapHandler::loadBitmap("VWorld.bmp"); + bgWorldView = IImage::createFromFile("VWorld.bmp"); } worldViewIcons = std::make_shared("VwSymbol");//todo: customize with ADVOPT @@ -712,11 +712,6 @@ CAdvMapInt::CAdvMapInt(): addUsedEvents(MOVE); } -CAdvMapInt::~CAdvMapInt() -{ - SDL_FreeSurface(bg); -} - void CAdvMapInt::fshowOverview() { GH.pushIntT(); @@ -976,7 +971,7 @@ void CAdvMapInt::deactivate() void CAdvMapInt::showAll(SDL_Surface * to) { - blitAt(bg,0,0,to); + bg->draw(to, 0, 0); if(state != INGAME) return; @@ -1507,7 +1502,7 @@ void CAdvMapInt::startHotSeatWait(PlayerColor Player) void CAdvMapInt::setPlayer(PlayerColor Player) { player = Player; - graphics->blueToPlayersAdv(bg,player); + bg->playerColored(player); panelMain->setPlayerColor(player); panelWorldView->setPlayerColor(player); diff --git a/client/windows/CAdvmapInterface.h b/client/windows/CAdvmapInterface.h index b605137ba..6b1ae0ddc 100644 --- a/client/windows/CAdvmapInterface.h +++ b/client/windows/CAdvmapInterface.h @@ -132,7 +132,6 @@ class CAdvMapInt : public CIntObject public: CAdvMapInt(); - ~CAdvMapInt(); int3 position; //top left corner of visible map part PlayerColor player; @@ -170,8 +169,8 @@ public: WorldViewOptions worldViewOptions; - SDL_Surface * bg; - SDL_Surface * bgWorldView; + std::shared_ptr bg; + std::shared_ptr bgWorldView; std::vector> gems; CMinimap minimap; std::shared_ptr statusbar; diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 19e40fc21..f3d397bcf 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -24,6 +24,8 @@ #include "../CPlayerInterface.h" #include "../Graphics.h" #include "../gui/CGuiHandler.h" +#include "../gui/CAnimation.h" +#include "../gui/ColorFilter.h" #include "../gui/SDL_Extensions.h" #include "../widgets/MiscWidgets.h" #include "../widgets/CComponent.h" @@ -68,24 +70,16 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town } if(!str->borderName.empty()) - border = BitmapHandler::loadBitmap(str->borderName); + border = IImage::createFromFile(str->borderName); else border = nullptr; if(!str->areaName.empty()) - area = BitmapHandler::loadBitmap(str->areaName); + area = IImage::createFromFile(str->areaName); else area = nullptr; } -CBuildingRect::~CBuildingRect() -{ - if(border) - SDL_FreeSurface(border); - if(area) - SDL_FreeSurface(area); -} - const CBuilding * CBuildingRect::getBuilding() { if (!str->building) @@ -127,7 +121,7 @@ void CBuildingRect::clickLeft(tribool down, bool previousState) { if(previousState && getBuilding() && area && !down && (parent->selectedBuilding==this)) { - if(!CSDL_Ext::isTransparent(area, GH.getCursorPosition() - pos.topLeft())) //inside building image + if(!area->isTransparent(GH.getCursorPosition() - pos.topLeft())) //inside building image { auto building = getBuilding(); parent->buildingClicked(building->bid, building->subId, building->upgrade); @@ -139,7 +133,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState) { if((!area) || (!((bool)down)) || (this!=parent->selectedBuilding) || getBuilding() == nullptr) return; - if( !CSDL_Ext::isTransparent(area, GH.getCursorPosition() - pos.topLeft()) ) //inside building image + if( !area->isTransparent(GH.getCursorPosition() - pos.topLeft()) ) //inside building image { BuildingID bid = getBuilding()->bid; const CBuilding *bld = town->town->buildings.at(bid); @@ -186,33 +180,27 @@ void CBuildingRect::show(SDL_Surface * to) if(stateTimeCounter >= BUILD_ANIMATION_FINISHED_TIMEPOINT) { if(parent->selectedBuilding == this) - blitAtLoc(border,0,0,to); + border->draw(to, pos.x, pos.y); return; } - if(border->format->palette != nullptr) - { - // key colors in glowing border - SDL_Color c1 = {200, 200, 200, 255}; // x2 - SDL_Color c2 = {120, 100, 60, 255}; // x0.5 - SDL_Color c3 = {210, 180, 110, 255}; // x1 - ui32 colorID = SDL_MapRGB(border->format, c3.r, c3.g, c3.b); - SDL_Color oldColor = border->format->palette->colors[colorID]; - SDL_Color newColor; + auto darkBorder = ColorFilter::genRangeShifter(0.f, 0.f, 0.f, 0.5f, 0.5f, 0.5f ); + auto lightBorder = ColorFilter::genRangeShifter(0.f, 0.f, 0.f, 2.0f, 2.0f, 2.0f ); + auto baseBorder = ColorFilter::genEmptyShifter(); - if (stateTimeCounter < BUILDING_WHITE_BORDER_TIMEPOINT) - newColor = multiplyColors(c1, c2, static_cast(stateTimeCounter % stageDelay) / stageDelay); - else - if (stateTimeCounter < BUILDING_YELLOW_BORDER_TIMEPOINT) - newColor = multiplyColors(c2, c3, static_cast(stateTimeCounter % stageDelay) / stageDelay); - else - newColor = oldColor; + float progress = float(stateTimeCounter % stageDelay) / stageDelay; - CSDL_Ext::setColors(border, &newColor, colorID, 1); - blitAtLoc(border, 0, 0, to); - CSDL_Ext::setColors(border, &oldColor, colorID, 1); - } + if (stateTimeCounter < BUILDING_WHITE_BORDER_TIMEPOINT) + border->adjustPalette(ColorFilter::genInterpolated(lightBorder, darkBorder, progress), 0); + else + if (stateTimeCounter < BUILDING_YELLOW_BORDER_TIMEPOINT) + border->adjustPalette(ColorFilter::genInterpolated(darkBorder, baseBorder, progress), 0); + else + border->adjustPalette(baseBorder, 0); + + border->draw(to, pos.x, pos.y); } + if(stateTimeCounter < BUILD_ANIMATION_FINISHED_TIMEPOINT) stateTimeCounter += GH.mainFPSmng->getElapsedMilliseconds(); } @@ -224,7 +212,7 @@ void CBuildingRect::showAll(SDL_Surface * to) CShowableAnim::showAll(to); if(!active && parent->selectedBuilding == this && border) - blitAtLoc(border,0,0,to); + border->draw(to, pos.x, pos.y); } std::string CBuildingRect::getSubtitle()//hover text for building @@ -256,7 +244,7 @@ void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent) { if(area && pos.isInside(sEvent.x, sEvent.y)) { - if(CSDL_Ext::isTransparent(area, GH.getCursorPosition() - pos.topLeft())) //hovered pixel is inside this building + if(area->isTransparent(GH.getCursorPosition() - pos.topLeft())) //hovered pixel is inside this building { if(parent->selectedBuilding == this) { diff --git a/client/windows/CCastleInterface.h b/client/windows/CCastleInterface.h index 6b9f7f7e8..5cb817058 100644 --- a/client/windows/CCastleInterface.h +++ b/client/windows/CCastleInterface.h @@ -56,13 +56,12 @@ public: CCastleBuildings * parent; const CGTownInstance * town; const CStructure* str; - SDL_Surface* border; - SDL_Surface* area; + std::shared_ptr border; + std::shared_ptr area; ui32 stateTimeCounter;//For building construction - current stage in animation CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str); - ~CBuildingRect(); bool operator<(const CBuildingRect & p2) const; void hover(bool on) override; void clickLeft(tribool down, bool previousState) override;