From 5c09f751b343fc3d46dd5c3f4f08b0614cf3522f Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Sat, 7 Apr 2018 14:34:11 +0300 Subject: [PATCH] Gui cleanup3 - UI refactoring to use smart pointers (#440) * Changed most gui classes to use shared pointers * Store and use IImage as shared_ptr * CSpellWindow redesign * AdventureMapClasses cleanup * CLabel: store background as smart pointer * Store CObjectList items as smart pointers * Removed destroy function of list item * Store toggle buttons as smart pointers * Use CComponent as smart pointer * Attempt to fix artifact merchant drawing --- AI/VCAI/VCAI.cpp | 2 +- AI/VCAI/VCAI.h | 2 +- client/CMT.cpp | 2 +- client/CMessage.cpp | 38 +- client/CPlayerInterface.cpp | 124 +- client/CPlayerInterface.h | 9 +- client/CreatureCostBox.cpp | 39 +- client/CreatureCostBox.h | 13 +- client/Graphics.cpp | 39 +- client/NetPacksClient.cpp | 7 +- client/battle/CBattleInterface.cpp | 15 +- client/battle/CBattleInterface.h | 4 +- client/battle/CBattleInterfaceClasses.cpp | 333 +++-- client/battle/CBattleInterfaceClasses.h | 49 +- client/battle/CCreatureAnimation.cpp | 2 +- client/gui/CAnimation.cpp | 62 +- client/gui/CAnimation.h | 16 +- client/gui/CGuiHandler.h | 5 +- client/gui/CIntObject.cpp | 43 +- client/gui/CIntObject.h | 2 +- client/lobby/CBonusSelection.cpp | 2 +- client/lobby/CLobbyScreen.cpp | 2 +- client/lobby/CSavingScreen.cpp | 2 +- client/lobby/CSelectionBase.cpp | 2 +- client/lobby/OptionsTab.cpp | 4 +- client/lobby/RandomMapTab.cpp | 7 +- client/mainmenu/CMainMenu.cpp | 24 +- client/mainmenu/CMainMenu.h | 2 +- client/mapHandler.cpp | 43 +- client/mapHandler.h | 42 +- client/widgets/AdventureMapClasses.cpp | 482 +++---- client/widgets/AdventureMapClasses.h | 162 ++- client/widgets/Buttons.cpp | 98 +- client/widgets/Buttons.h | 28 +- client/widgets/CArtifactHolder.cpp | 171 ++- client/widgets/CArtifactHolder.h | 64 +- client/widgets/CComponent.cpp | 64 +- client/widgets/CComponent.h | 22 +- client/widgets/CGarrisonInt.cpp | 161 +-- client/widgets/CGarrisonInt.h | 69 +- client/widgets/Images.cpp | 19 +- client/widgets/Images.h | 1 - client/widgets/MiscWidgets.cpp | 167 +-- client/widgets/MiscWidgets.h | 51 +- client/widgets/ObjectLists.cpp | 97 +- client/widgets/ObjectLists.h | 28 +- client/widgets/TextControls.cpp | 82 +- client/widgets/TextControls.h | 21 +- client/windows/CAdvmapInterface.cpp | 101 +- client/windows/CAdvmapInterface.h | 50 +- client/windows/CCastleInterface.cpp | 1229 ++++++++-------- client/windows/CCastleInterface.h | 194 +-- client/windows/CCreatureWindow.cpp | 1573 +++++++++++---------- client/windows/CCreatureWindow.h | 152 +- client/windows/CHeroWindow.cpp | 265 ++-- client/windows/CHeroWindow.h | 84 +- client/windows/CKingdomInterface.cpp | 446 +++--- client/windows/CKingdomInterface.h | 137 +- client/windows/CQuestLog.cpp | 84 +- client/windows/CQuestLog.h | 29 +- client/windows/CSpellWindow.cpp | 110 +- client/windows/CSpellWindow.h | 30 +- client/windows/CTradeWindow.cpp | 355 +++-- client/windows/CTradeWindow.h | 84 +- client/windows/CWindowObject.cpp | 73 +- client/windows/CWindowObject.h | 12 +- client/windows/CreaturePurchaseCard.cpp | 1 - client/windows/GUIClasses.cpp | 1077 +++++++------- client/windows/GUIClasses.h | 388 +++-- client/windows/InfoWindows.cpp | 101 +- client/windows/InfoWindows.h | 36 +- lib/CGameInterface.h | 1 - lib/IGameEventsReceiver.h | 2 +- 73 files changed, 4793 insertions(+), 4544 deletions(-) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 856553086..45b2f1ae4 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -447,7 +447,7 @@ void VCAI::advmapSpellCast(const CGHeroInstance * caster, int spellID) NET_EVENT_HANDLER; } -void VCAI::showInfoDialog(const std::string &text, const std::vector &components, int soundID) +void VCAI::showInfoDialog(const std::string &text, const std::vector &components, int soundID) { LOG_TRACE_PARAMS(logAi, "soundID '%i'", soundID); NET_EVENT_HANDLER; diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index 1e551a96f..c2ee416c1 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -231,7 +231,7 @@ public: virtual void playerBonusChanged(const Bonus &bonus, bool gain) override; virtual void heroCreated(const CGHeroInstance*) override; virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID) override; - virtual void showInfoDialog(const std::string &text, const std::vector &components, int soundID) override; + virtual void showInfoDialog(const std::string &text, const std::vector &components, int soundID) override; virtual void requestRealized(PackageApplied *pa) override; virtual void receivedResource() override; virtual void objectRemoved(const CGObjectInstance *obj) override; diff --git a/client/CMT.cpp b/client/CMT.cpp index 15f84fca5..f40116494 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -1341,7 +1341,7 @@ void handleQuit(bool ask) if(CSH->client && LOCPLINT && ask) { CCS->curh->changeGraphic(ECursor::ADVENTURE, 0); - LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], quitApplication, 0); + LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], quitApplication, nullptr); } else { diff --git a/client/CMessage.cpp b/client/CMessage.cpp index 6d8b96319..7e6195da8 100644 --- a/client/CMessage.cpp +++ b/client/CMessage.cpp @@ -39,30 +39,30 @@ template std::pair max(const std::pair &x, co class ComponentResolved : public CIntObject { public: - CComponent *comp; + std::shared_ptr comp; //blit component with image centered at this position void showAll(SDL_Surface * to) override; //ComponentResolved(); - ComponentResolved(CComponent *Comp); + ComponentResolved(std::shared_ptr Comp); ~ComponentResolved(); }; // Full set of components for blitting on dialog box struct ComponentsToBlit { - std::vector< std::vector > comps; + std::vector< std::vector>> comps; int w, h; void blitCompsOnSur(bool blitOr, int inter, int &curh, SDL_Surface *ret); - ComponentsToBlit(std::vector & SComps, int maxw, bool blitOr); + ComponentsToBlit(std::vector> & SComps, int maxw, bool blitOr); ~ComponentsToBlit(); }; namespace { std::array, PlayerColor::PLAYER_LIMIT_I> dialogBorders; - std::array, PlayerColor::PLAYER_LIMIT_I> piecesOfBox; + std::array>, PlayerColor::PLAYER_LIMIT_I> piecesOfBox; SDL_Surface * background = nullptr;//todo: should be CFilledTexture } @@ -298,7 +298,7 @@ void CMessage::drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int { if(playerColor.isSpectator()) playerColor = PlayerColor(1); - std::vector &box = piecesOfBox.at(playerColor.getNum()); + auto & box = piecesOfBox.at(playerColor.getNum()); // Note: this code assumes that the corner dimensions are all the same. @@ -358,7 +358,7 @@ void CMessage::drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int box[3]->draw(ret, &dstR, nullptr); } -ComponentResolved::ComponentResolved( CComponent *Comp ): +ComponentResolved::ComponentResolved(std::shared_ptr Comp): comp(Comp) { //Temporary assign ownership on comp @@ -367,10 +367,10 @@ ComponentResolved::ComponentResolved( CComponent *Comp ): if (comp->parent) { comp->parent->addChild(this); - comp->parent->removeChild(comp); + comp->parent->removeChild(comp.get()); } - addChild(comp); + addChild(comp.get()); defActions = 255 - DISPOSE; pos.x = pos.y = 0; @@ -382,8 +382,8 @@ ComponentResolved::~ComponentResolved() { if (parent) { - removeChild(comp); - parent->addChild(comp); + removeChild(comp.get()); + parent->addChild(comp.get()); } } @@ -393,15 +393,9 @@ void ComponentResolved::showAll(SDL_Surface *to) comp->showAll(to); } -ComponentsToBlit::~ComponentsToBlit() -{ - for(auto & elem : comps) - for(size_t j = 0; j < elem.size(); j++) - delete elem[j]; +ComponentsToBlit::~ComponentsToBlit() = default; -} - -ComponentsToBlit::ComponentsToBlit(std::vector & SComps, int maxw, bool blitOr) +ComponentsToBlit::ComponentsToBlit(std::vector> & SComps, int maxw, bool blitOr) { int orWidth = graphics->fonts[FONT_MEDIUM]->getStringWidth(CGI->generaltexth->allTexts[4]); @@ -415,7 +409,7 @@ ComponentsToBlit::ComponentsToBlit(std::vector & SComps, int maxw, for(auto & SComp : SComps) { - auto cur = new ComponentResolved(SComp); + auto cur = std::make_shared(SComp); int toadd = (cur->pos.w + BETWEEN_COMPS + (blitOr ? orWidth : 0)); if (curw + toadd > maxw) @@ -453,7 +447,7 @@ void ComponentsToBlit::blitCompsOnSur( bool blitOr, int inter, int &curh, SDL_Su int totalw=0, maxHeight=0; for(size_t j=0;jpos.w; vstd::amax(maxHeight, cur->pos.h); } @@ -469,7 +463,7 @@ void ComponentsToBlit::blitCompsOnSur( bool blitOr, int inter, int &curh, SDL_Su for(size_t j=0;jmoveTo(Point(curw, curh)); //blit component diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 90a848742..52a827280 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -196,8 +196,8 @@ void CPlayerInterface::yourTurn() makingTurn = true; std::string msg = CGI->generaltexth->allTexts[13]; boost::replace_first(msg, "%s", cb->getStartInfo()->playerInfos.find(playerID)->second.name); - std::vector cmp; - cmp.push_back(new CComponent(CComponent::flag, playerID.getNum(), 0)); + std::vector> cmp; + cmp.push_back(std::make_shared(CComponent::flag, playerID.getNum(), 0)); showInfoDialog(msg, cmp); } else @@ -363,9 +363,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details) GH.mainFPSmng->framerateDelay(); //for animation purposes logGlobal->trace("after [un]locks in %s", __FUNCTION__); } - //CSDL_Ext::update(screen); - } //for (int i=1; i<32; i+=4) + } //main moving done //finishing move @@ -905,8 +904,7 @@ void CPlayerInterface::battleEnd(const BattleResult *br) if (!battleInt) { - SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19); - auto resWindow = new CBattleResultWindow(*br, temp_rect, *this); + auto resWindow = new CBattleResultWindow(*br, *this); GH.pushInt(resWindow); // #1490 - during AI turn when quick combat is on, we need to display the message and wait for user to close it. // Otherwise NewTurn causes freeze. @@ -1100,29 +1098,29 @@ void CPlayerInterface::showComp(const Component &comp, std::string message) adventureInt->infoBar.showComponent(comp, message); } -void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector &components, int soundID) +void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector & components, int soundID) { EVENT_HANDLER_CALLED_BY_CLIENT; if (settings["session"]["autoSkip"].Bool() && !LOCPLINT->shiftPressed()) { return; } - std::vector intComps; + std::vector> intComps; for (auto & component : components) - intComps.push_back(new CComponent(*component)); + intComps.push_back(std::make_shared(component)); showInfoDialog(text,intComps,soundID); } -void CPlayerInterface::showInfoDialog(const std::string &text, CComponent * component) +void CPlayerInterface::showInfoDialog(const std::string & text, std::shared_ptr component) { - std::vector intComps; + std::vector> intComps; intComps.push_back(component); - showInfoDialog(text, intComps, soundBase::sound_todo, true); + showInfoDialog(text, intComps, soundBase::sound_todo); } -void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector & components, int soundID, bool delComps) +void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector> & components, int soundID) { LOG_TRACE_PARAMS(logGlobal, "player=%s, text=%s, is LOCPLINT=%d", playerID % text % (this==LOCPLINT)); waitWhileDialog(); @@ -1131,8 +1129,8 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector { return; } - CInfoWindow *temp = CInfoWindow::create(text, playerID, &components); - temp->setDelComps(delComps); + CInfoWindow *temp = CInfoWindow::create(text, playerID, components); + if (makingTurn && GH.listInt.size() && LOCPLINT == this) { CCS->soundh->playSound(static_cast(soundID)); @@ -1149,46 +1147,37 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector void CPlayerInterface::showInfoDialogAndWait(std::vector & components, const MetaString & text) { EVENT_HANDLER_CALLED_BY_CLIENT; - std::vector comps; - for (auto & elem : components) - { - comps.push_back(&elem); - } + std::string str; text.toString(str); - showInfoDialog(str,comps, 0); + showInfoDialog(str, components, 0); waitWhileDialog(); } -void CPlayerInterface::showYesNoDialog(const std::string &text, CFunctionList onYes, CFunctionList onNo, bool DelComps, const std::vector & components) +void CPlayerInterface::showYesNoDialog(const std::string &text, CFunctionList onYes, CFunctionList onNo, const std::vector> & components) { boost::unique_lock un(*pim); stopMovement(); LOCPLINT->showingDialog->setn(true); - CInfoWindow::showYesNoDialog(text, &components, onYes, onNo, DelComps, playerID); + CInfoWindow::showYesNoDialog(text, components, onYes, onNo, playerID); } void CPlayerInterface::showOkDialog(std::vector & components, const MetaString & text, const std::function & onOk) { boost::unique_lock un(*pim); - std::vector comps; - for (auto & elem : components) - { - comps.push_back(&elem); - } std::string str; text.toString(str); stopMovement(); showingDialog->setn(true); - std::vector intComps; - for (auto & component : comps) - intComps.push_back(new CComponent(*component)); - CInfoWindow::showOkDialog(str, &intComps, onOk, true, playerID); + std::vector> intComps; + for (auto & component : components) + intComps.push_back(std::make_shared(component)); + CInfoWindow::showOkDialog(str, intComps, onOk, playerID); } void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector &components, QueryID askID, const int soundID, bool selection, bool cancel ) @@ -1201,17 +1190,17 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v if (!selection && cancel) //simple yes/no dialog { - std::vector intComps; + std::vector> intComps; for (auto & component : components) - intComps.push_back(new CComponent(component)); //will be deleted by close in window + intComps.push_back(std::make_shared(component)); //will be deleted by close in window - showYesNoDialog(text, [=](){ cb->selectionMade(1, askID); }, [=](){ cb->selectionMade(0, askID); }, true, intComps); + showYesNoDialog(text, [=](){ cb->selectionMade(1, askID); }, [=](){ cb->selectionMade(0, askID); }, intComps); } else if (selection) { - std::vector intComps; + std::vector> intComps; for (auto & component : components) - intComps.push_back(new CSelectableComponent(component)); //will be deleted by CSelWindow::close + intComps.push_back(std::make_shared(component)); //will be deleted by CSelWindow::close std::vector > > pom; pom.push_back(std::pair >("IOKAY.DEF",0)); @@ -1269,8 +1258,8 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component CComponent * localIconC = new CComponent(icon); - CIntObject * localIcon = localIconC->image; - localIconC->removeChild(localIcon, false); + std::shared_ptr localIcon = localIconC->image; + localIconC->removeChild(localIcon.get(), false); delete localIconC; CObjectListWindow * wnd = new CObjectListWindow(tempList, localIcon, localTitle, localDescription, selectCallback); @@ -1302,46 +1291,6 @@ void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero) boost::unique_lock un(*pim); GH.pushInt(new CHeroWindow(hero)); } -/* -void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero) -{ - boost::unique_lock un(*pim); - if (adventureInt->heroWindow->curHero && adventureInt->heroWindow->curHero->id == hero->id) //hero window is opened - { - adventureInt->heroWindow->deactivate(); - adventureInt->heroWindow->setHero(hero); - adventureInt->heroWindow->activate(); - } - else if (CExchangeWindow* cew = dynamic_cast(GH.topInt())) //exchange window is open - { - cew->deactivate(); - for (int g=0; gheroInst); ++g) - { - if (cew->heroInst[g]->id == hero->id) - { - cew->heroInst[g] = hero; - cew->artifs[g]->updateState = true; - cew->artifs[g]->setHero(hero); - cew->artifs[g]->updateState = false; - } - } - cew->prepareBackground(); - cew->activate(); - } - else if (CTradeWindow *caw = dynamic_cast(GH.topInt())) - { - if (caw->arts) - { - caw->deactivate(); - caw->arts->updateState = true; - caw->arts->setHero(hero); - caw->arts->updateState = false; - caw->activate(); - } - } - - updateInfo(hero); -}*/ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town ) { @@ -1504,25 +1453,28 @@ void CPlayerInterface::showArtifactAssemblyDialog (ui32 artifactID, ui32 assembl const CArtifact &artifact = *CGI->arth->artifacts[artifactID]; std::string text = artifact.Description(); text += "\n\n"; - std::vector scs; + std::vector> scs; - if (assemble) { + if(assemble) + { const CArtifact &assembledArtifact = *CGI->arth->artifacts[assembleTo]; // You possess all of the components to... text += boost::str(boost::format(CGI->generaltexth->allTexts[732]) % assembledArtifact.Name()); // Picture of assembled artifact at bottom. - auto sc = new CComponent(CComponent::artifact, assembledArtifact.id, 0); + auto sc = std::make_shared(CComponent::artifact, assembledArtifact.id, 0); //sc->description = assembledArtifact.Description(); //sc->subtitle = assembledArtifact.Name(); scs.push_back(sc); - } else { + } + else + { // Do you wish to disassemble this artifact? text += CGI->generaltexth->allTexts[733]; } - showYesNoDialog(text, onYes, onNo, true, scs); + showYesNoDialog(text, onYes, onNo, scs); } void CPlayerInterface::requestRealized( PackageApplied *pa ) @@ -2230,7 +2182,7 @@ void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResul { std::string str = victoryLossCheckResult.messageToSelf; boost::algorithm::replace_first(str, "%s", CGI->generaltexth->capColors[player.getNum()]); - showInfoDialog(str, std::vector(1, new CComponent(CComponent::flag, player.getNum(), 0))); + showInfoDialog(str, std::vector>(1, std::make_shared(CComponent::flag, player.getNum(), 0))); } } } @@ -2661,7 +2613,7 @@ void CPlayerInterface::waitForAllDialogs(bool unlockPim) void CPlayerInterface::proposeLoadingGame() { - showYesNoDialog(CGI->generaltexth->allTexts[68], [this](){ sendCustomEvent(EUserEvent::RETURN_TO_MENU_LOAD); }, 0, false); + showYesNoDialog(CGI->generaltexth->allTexts[68], [this](){ sendCustomEvent(EUserEvent::RETURN_TO_MENU_LOAD); }, nullptr); } CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting() diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index b0dec6cdc..ff9c10405 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -39,7 +39,6 @@ class CSlider; struct UpgradeInfo; template struct CondSh; class CInGameConsole; -class CGarrisonInt; class CInGameConsole; union SDL_Event; class CInfoWindow; @@ -139,7 +138,7 @@ public: void heroMovePointsChanged(const CGHeroInstance * hero) override; void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override; void receivedResource() override; - void showInfoDialog(const std::string &text, const std::vector &components, int soundID) override; + void showInfoDialog(const std::string & text, const std::vector & components, int soundID) override; void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override; void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard; void showBlockingDialog(const std::string &text, const std::vector &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. @@ -215,11 +214,11 @@ public: void activateForSpectator(); // TODO: spectator probably need own player interface class // show dialogs - void showInfoDialog(const std::string &text, CComponent * component); - void showInfoDialog(const std::string &text, const std::vector & components = std::vector(), int soundID = 0, bool delComps = false); + void showInfoDialog(const std::string &text, std::shared_ptr component); + void showInfoDialog(const std::string &text, const std::vector> & components = std::vector>(), int soundID = 0); void showInfoDialogAndWait(std::vector & components, const MetaString & text); void showOkDialog(std::vector & components, const MetaString & text, const std::function & onOk); - void showYesNoDialog(const std::string &text, CFunctionList onYes, CFunctionList onNo, bool DelComps = false, const std::vector & components = std::vector()); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close + void showYesNoDialog(const std::string &text, CFunctionList onYes, CFunctionList onNo, const std::vector> & components = std::vector>()); void stopMovement(); void moveHero(const CGHeroInstance *h, CGPath path); diff --git a/client/CreatureCostBox.cpp b/client/CreatureCostBox.cpp index 898850c41..5cc61a9c4 100644 --- a/client/CreatureCostBox.cpp +++ b/client/CreatureCostBox.cpp @@ -9,9 +9,19 @@ */ #include "StdInc.h" #include "CreatureCostBox.h" -#include "windows/CAdvmapInterface.h" +#include "widgets/Images.h" +#include "widgets/TextControls.h" #include "gui/CGuiHandler.h" +CreatureCostBox::CreatureCostBox(Rect position, std::string titleText) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + type |= REDRAW_PARENT; + pos = position + pos; + + title = std::make_shared(pos.w/2, 10, FONT_SMALL, CENTER, Colors::WHITE, titleText); +} void CreatureCostBox::set(TResources res) { @@ -19,40 +29,27 @@ void CreatureCostBox::set(TResources res) item.second.first->setText(boost::lexical_cast(res[item.first])); } -CreatureCostBox::CreatureCostBox(Rect position, std::string title) -{ - type |= REDRAW_PARENT; - pos = position + pos; - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CLabel(pos.w/2, 10, FONT_SMALL, CENTER, Colors::WHITE, title); -} - void CreatureCostBox::createItems(TResources res) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - - for(auto & curr : resources) - { - delete curr.second.first; - delete curr.second.second; - } resources.clear(); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + TResources::nziterator iter(res); - while (iter.valid()) + while(iter.valid()) { - CAnimImage * image = new CAnimImage("RESOURCE", iter->resType); - CLabel * text = new CLabel(15, 43, FONT_SMALL, CENTER, Colors::WHITE, "0"); + ImagePtr image = std::make_shared("RESOURCE", iter->resType); + LabelPtr text = std::make_shared(15, 43, FONT_SMALL, CENTER, Colors::WHITE, "0"); resources.insert(std::make_pair(iter->resType, std::make_pair(text, image))); iter++; } - if (!resources.empty()) + if(!resources.empty()) { int curx = pos.w / 2 - (16 * resources.size()) - (8 * (resources.size() - 1)); //reverse to display gold as first resource - for (auto & res : boost::adaptors::reverse(resources)) + for(auto & res : boost::adaptors::reverse(resources)) { res.second.first->moveBy(Point(curx, 22)); res.second.second->moveBy(Point(curx, 22)); diff --git a/client/CreatureCostBox.h b/client/CreatureCostBox.h index 872ac628f..908b74508 100644 --- a/client/CreatureCostBox.h +++ b/client/CreatureCostBox.h @@ -9,15 +9,22 @@ */ #pragma once -#include "widgets/Images.h" #include "../lib/ResourceSet.h" +#include "gui/CIntObject.h" + +class CLabel; +class CAnimImage; class CreatureCostBox : public CIntObject { public: void set(TResources res); - CreatureCostBox(Rect position, std::string title); + CreatureCostBox(Rect position, std::string titleText); void createItems(TResources res); private: - std::map > resources; + using LabelPtr = std::shared_ptr; + using ImagePtr = std::shared_ptr; + + LabelPtr title; + std::map> resources; }; diff --git a/client/Graphics.cpp b/client/Graphics.cpp index 186f63a4b..db17d6a51 100644 --- a/client/Graphics.cpp +++ b/client/Graphics.cpp @@ -264,7 +264,7 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player) { if(sur->format->palette) { - SDL_Color *palette = nullptr; + SDL_Color * palette = nullptr; if(player < PlayerColor::PLAYER_LIMIT) { palette = playerColorPalette + 32*player.getNum(); @@ -278,7 +278,44 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player) logGlobal->error("Wrong player id in blueToPlayersAdv (%s)!", player.getStr()); return; } +//FIXME: not all player colored images have player palette at last 32 indexes +//NOTE: following code is much more correct but still not perfect (bugged with status bar) + SDL_SetColors(sur, palette, 224, 32); + + +#if 0 + + SDL_Color * bluePalette = playerColorPalette + 32; + + SDL_Palette * oldPalette = sur->format->palette; + + SDL_Palette * newPalette = SDL_AllocPalette(256); + + for(size_t destIndex = 0; destIndex < 256; destIndex++) + { + SDL_Color old = oldPalette->colors[destIndex]; + + bool found = false; + + for(size_t srcIndex = 0; srcIndex < 32; srcIndex++) + { + if(old.b == bluePalette[srcIndex].b && old.g == bluePalette[srcIndex].g && old.r == bluePalette[srcIndex].r) + { + found = true; + newPalette->colors[destIndex] = palette[srcIndex]; + break; + } + } + if(!found) + newPalette->colors[destIndex] = old; + } + + SDL_SetSurfacePalette(sur, newPalette); + + SDL_FreePalette(newPalette); + +#endif // 0 } else { diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index b3a8ac3c3..c7168bfbe 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -534,15 +534,10 @@ void GiveHero::applyFirstCl(CClient *cl) void InfoWindow::applyCl(CClient *cl) { - std::vector comps; - for(auto & elem : components) - { - comps.push_back(&elem); - } std::string str; text.toString(str); - if(!callInterfaceIfPresent(cl, player, &CGameInterface::showInfoDialog, str,comps,(soundBase::soundID)soundID)) + if(!callInterfaceIfPresent(cl, player, &CGameInterface::showInfoDialog, str,components,(soundBase::soundID)soundID)) logNetwork->warn("We received InfoWindow for not our player..."); } diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index 578137b29..85081b830 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -803,7 +803,7 @@ void CBattleInterface::bSurrenderf() enemyHeroName = "#ENEMY#"; //TODO: should surrendering without enemy hero be enabled? std::string surrenderMessage = boost::str(boost::format(CGI->generaltexth->allTexts[32]) % enemyHeroName % cost); //%s states: "I will accept your surrender and grant you and your troops safe passage for the price of %d gold." - curInt->showYesNoDialog(surrenderMessage, [this](){ reallySurrender(); }, 0, false); + curInt->showYesNoDialog(surrenderMessage, [this](){ reallySurrender(); }, nullptr); } } @@ -815,11 +815,11 @@ void CBattleInterface::bFleef() if ( curInt->cb->battleCanFlee() ) { CFunctionList ony = std::bind(&CBattleInterface::reallyFlee,this); - curInt->showYesNoDialog(CGI->generaltexth->allTexts[28], ony, 0, false); //Are you sure you want to retreat? + curInt->showYesNoDialog(CGI->generaltexth->allTexts[28], ony, nullptr); //Are you sure you want to retreat? } else { - std::vector comps; + std::vector> comps; std::string heroName; //calculating fleeing hero's name if (attackingHeroInstance) @@ -1280,8 +1280,7 @@ void CBattleInterface::displayBattleFinished() return; } - SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19); - resWindow = new CBattleResultWindow(*bresult, temp_rect, *this->curInt); + resWindow = new CBattleResultWindow(*bresult, *this->curInt); GH.pushInt(resWindow); curInt->waitWhileDialog(); // Avoid freeze when AI end turn after battle. Check bug #1897 } @@ -3637,7 +3636,7 @@ void CBattleInterface::updateBattleAnimations() } } -IImage * CBattleInterface::getObstacleImage(const CObstacleInstance & oi) +std::shared_ptr CBattleInterface::getObstacleImage(const CObstacleInstance & oi) { int frameIndex = (animCount+1) *25 / getAnimSpeed(); std::shared_ptr animation; @@ -3650,7 +3649,7 @@ IImage * CBattleInterface::getObstacleImage(const CObstacleInstance & oi) { const SpellCreatedObstacle * spellObstacle = dynamic_cast(&oi); if(!spellObstacle) - return nullptr; + return std::shared_ptr(); std::string animationName = spellObstacle->animation; @@ -3679,7 +3678,7 @@ IImage * CBattleInterface::getObstacleImage(const CObstacleInstance & oi) return nullptr; } -Point CBattleInterface::getObstaclePosition(IImage * image, const CObstacleInstance & obstacle) +Point CBattleInterface::getObstaclePosition(std::shared_ptr image, const CObstacleInstance & obstacle) { int offset = obstacle.getAnimationYOffset(image->height()); diff --git a/client/battle/CBattleInterface.h b/client/battle/CBattleInterface.h index 41dd4724a..947a2f98c 100644 --- a/client/battle/CBattleInterface.h +++ b/client/battle/CBattleInterface.h @@ -254,9 +254,9 @@ private: BattleObjectsByHex sortObjectsByHex(); void updateBattleAnimations(); - IImage * getObstacleImage(const CObstacleInstance & oi); + std::shared_ptr getObstacleImage(const CObstacleInstance & oi); - Point getObstaclePosition(IImage * image, const CObstacleInstance & obstacle); + Point getObstaclePosition(std::shared_ptr image, const CObstacleInstance & obstacle); void redrawBackgroundWithHexes(const CStack *activeStack); /** End of battle screen blitting methods */ diff --git a/client/battle/CBattleInterfaceClasses.cpp b/client/battle/CBattleInterfaceClasses.cpp index 33ae32f3e..21b64ae32 100644 --- a/client/battle/CBattleInterfaceClasses.cpp +++ b/client/battle/CBattleInterfaceClasses.cpp @@ -277,55 +277,111 @@ CBattleHero::CBattleHero(const std::string & animationPath, bool flipG, PlayerCo CBattleHero::~CBattleHero() = default; +CHeroInfoWindow::CHeroInfoWindow(const InfoAboutHero & hero, Point * position) + : CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP") +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + if (position != nullptr) + moveTo(*position); + background->colorize(hero.owner); //maybe add this functionality to base class? + + auto attack = hero.details->primskills[0]; + auto defense = hero.details->primskills[1]; + auto power = hero.details->primskills[2]; + auto knowledge = hero.details->primskills[3]; + auto morale = hero.details->morale; + auto luck = hero.details->luck; + auto currentSpellPoints = hero.details->mana; + auto maxSpellPoints = hero.details->manaLimit; + + icons.push_back(std::make_shared("PortraitsLarge", hero.portrait, 0, 10, 6)); + + //primary stats + labels.push_back(std::make_shared(9, 75, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[380] + ":")); + labels.push_back(std::make_shared(9, 87, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[381] + ":")); + labels.push_back(std::make_shared(9, 99, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[382] + ":")); + labels.push_back(std::make_shared(9, 111, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[383] + ":")); + + labels.push_back(std::make_shared(69, 87, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(attack))); + labels.push_back(std::make_shared(69, 99, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(defense))); + labels.push_back(std::make_shared(69, 111, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(power))); + labels.push_back(std::make_shared(69, 123, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(knowledge))); + + //morale+luck + labels.push_back(std::make_shared(9, 131, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[384] + ":")); + labels.push_back(std::make_shared(9, 143, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[385] + ":")); + + icons.push_back(std::make_shared("IMRL22", morale + 3, 0, 47, 131)); + icons.push_back(std::make_shared("ILCK22", luck + 3, 0, 47, 143)); + + //spell points + labels.push_back(std::make_shared(39, 174, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, CGI->generaltexth->allTexts[387])); + labels.push_back(std::make_shared(39, 186, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints))); +} + CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); pos = position; - background = new CPicture("comopbck.bmp"); + + background = std::make_shared("comopbck.bmp"); background->colorize(owner->getCurrentPlayerInterface()->playerID); - viewGrid = new CToggleButton(Point(25, 56), "sysopchk.def", CGI->generaltexth->zelp[427], [=](bool on){owner->setPrintCellBorders(on);} ); + auto viewGrid = std::make_shared(Point(25, 56), "sysopchk.def", CGI->generaltexth->zelp[427], [=](bool on){owner->setPrintCellBorders(on);} ); viewGrid->setSelected(settings["battle"]["cellBorders"].Bool()); - movementShadow = new CToggleButton(Point(25, 89), "sysopchk.def", CGI->generaltexth->zelp[428], [=](bool on){owner->setPrintStackRange(on);}); - movementShadow->setSelected(settings["battle"]["stackRange"].Bool()); - mouseShadow = new CToggleButton(Point(25, 122), "sysopchk.def", CGI->generaltexth->zelp[429], [=](bool on){owner->setPrintMouseShadow(on);}); - mouseShadow->setSelected(settings["battle"]["mouseShadow"].Bool()); + toggles.push_back(viewGrid); + + auto movementShadow = std::make_shared(Point(25, 89), "sysopchk.def", CGI->generaltexth->zelp[428], [=](bool on){owner->setPrintStackRange(on);}); + movementShadow->setSelected(settings["battle"]["stackRange"].Bool()); + toggles.push_back(movementShadow); + + auto mouseShadow = std::make_shared(Point(25, 122), "sysopchk.def", CGI->generaltexth->zelp[429], [=](bool on){owner->setPrintMouseShadow(on);}); + mouseShadow->setSelected(settings["battle"]["mouseShadow"].Bool()); + toggles.push_back(mouseShadow); + + animSpeeds = std::make_shared([=](int value){ owner->setAnimSpeed(value);}); + + std::shared_ptr toggle; + toggle = std::make_shared(Point( 28, 225), "sysopb9.def", CGI->generaltexth->zelp[422]); + animSpeeds->addToggle(40, toggle); + + toggle = std::make_shared(Point( 92, 225), "sysob10.def", CGI->generaltexth->zelp[423]); + animSpeeds->addToggle(63, toggle); + + toggle = std::make_shared(Point(156, 225), "sysob11.def", CGI->generaltexth->zelp[424]); + animSpeeds->addToggle(100, toggle); - animSpeeds = new CToggleGroup([=](int value){ owner->setAnimSpeed(value);}); - animSpeeds->addToggle(40, new CToggleButton(Point( 28, 225), "sysopb9.def", CGI->generaltexth->zelp[422])); - animSpeeds->addToggle(63, new CToggleButton(Point( 92, 225), "sysob10.def", CGI->generaltexth->zelp[423])); - animSpeeds->addToggle(100, new CToggleButton(Point(156, 225), "sysob11.def", CGI->generaltexth->zelp[424])); animSpeeds->setSelected(owner->getAnimSpeed()); - setToDefault = new CButton (Point(246, 359), "codefaul.def", CGI->generaltexth->zelp[393], [&](){ bDefaultf(); }); + setToDefault = std::make_shared(Point(246, 359), "codefaul.def", CGI->generaltexth->zelp[393], [&](){ bDefaultf(); }); setToDefault->setImageOrder(1, 0, 2, 3); - exit = new CButton (Point(357, 359), "soretrn.def", CGI->generaltexth->zelp[392], [&](){ bExitf();}, SDLK_RETURN); + exit = std::make_shared(Point(357, 359), "soretrn.def", CGI->generaltexth->zelp[392], [&](){ bExitf();}, SDLK_RETURN); exit->setImageOrder(1, 0, 2, 3); //creating labels - labels.push_back(new CLabel(242, 32, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[392]));//window title - labels.push_back(new CLabel(122, 214, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[393]));//animation speed - labels.push_back(new CLabel(122, 293, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[394]));//music volume - labels.push_back(new CLabel(122, 359, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[395]));//effects' volume - labels.push_back(new CLabel(353, 66, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[396]));//auto - combat options - labels.push_back(new CLabel(353, 265, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[397]));//creature info + labels.push_back(std::make_shared(242, 32, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[392]));//window title + labels.push_back(std::make_shared(122, 214, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[393]));//animation speed + labels.push_back(std::make_shared(122, 293, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[394]));//music volume + labels.push_back(std::make_shared(122, 359, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[395]));//effects' volume + labels.push_back(std::make_shared(353, 66, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[396]));//auto - combat options + labels.push_back(std::make_shared(353, 265, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[397]));//creature info //auto - combat options - labels.push_back(new CLabel(283, 86, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[398]));//creatures - labels.push_back(new CLabel(283, 116, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[399]));//spells - labels.push_back(new CLabel(283, 146, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[400]));//catapult - labels.push_back(new CLabel(283, 176, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[151]));//ballista - labels.push_back(new CLabel(283, 206, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[401]));//first aid tent + labels.push_back(std::make_shared(283, 86, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[398]));//creatures + labels.push_back(std::make_shared(283, 116, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[399]));//spells + labels.push_back(std::make_shared(283, 146, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[400]));//catapult + labels.push_back(std::make_shared(283, 176, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[151]));//ballista + labels.push_back(std::make_shared(283, 206, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[401]));//first aid tent //creature info - labels.push_back(new CLabel(283, 285, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[402]));//all stats - labels.push_back(new CLabel(283, 315, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[403]));//spells only + labels.push_back(std::make_shared(283, 285, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[402]));//all stats + labels.push_back(std::make_shared(283, 315, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[403]));//spells only //general options - labels.push_back(new CLabel(61, 57, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[404])); - labels.push_back(new CLabel(61, 90, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[405])); - labels.push_back(new CLabel(61, 123, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[406])); - labels.push_back(new CLabel(61, 156, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[407])); + labels.push_back(std::make_shared(61, 57, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[404])); + labels.push_back(std::make_shared(61, 90, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[405])); + labels.push_back(std::make_shared(61, 123, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[406])); + labels.push_back(std::make_shared(61, 156, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[407])); } void CBattleOptionsWindow::bDefaultf() @@ -338,31 +394,32 @@ void CBattleOptionsWindow::bExitf() GH.popIntTotally(this); } -CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect & pos, CPlayerInterface &_owner) -: owner(_owner) +CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterface & _owner) + : owner(_owner) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - this->pos = pos; - CPicture * bg = new CPicture("CPRESULT"); - bg->colorize(owner.playerID); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - exit = new CButton (Point(384, 505), "iok6432.def", std::make_pair("", ""), [&](){ bExitf();}, SDLK_RETURN); + pos = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19); + background = std::make_shared("CPRESULT"); + background->colorize(owner.playerID); + + exit = std::make_shared(Point(384, 505), "iok6432.def", std::make_pair("", ""), [&](){ bExitf();}, SDLK_RETURN); exit->setBorderColor(Colors::METALLIC_GOLD); if(br.winner==0) //attacker won { - new CLabel( 59, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[410]); - new CLabel(408, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[411]); + labels.push_back(std::make_shared(59, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[410])); + labels.push_back(std::make_shared(408, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[411])); } else //if(br.winner==1) { - new CLabel( 59, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[411]); - new CLabel(412, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[410]); + labels.push_back(std::make_shared(59, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[411])); + labels.push_back(std::make_shared(412, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[410])); } - new CLabel(232, 302, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[407]); - new CLabel(232, 332, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[408]); - new CLabel(232, 428, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[409]); + labels.push_back(std::make_shared(232, 302, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[407])); + labels.push_back(std::make_shared(232, 332, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[408])); + labels.push_back(std::make_shared(232, 428, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[409])); std::string sideNames[2] = {"N/A", "N/A"}; @@ -373,45 +430,51 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect if(heroInfo.portrait >= 0) //attacking hero { - new CAnimImage("PortraitsLarge", heroInfo.portrait, 0, xs[i], 38); + icons.push_back(std::make_shared("PortraitsLarge", heroInfo.portrait, 0, xs[i], 38)); sideNames[i] = heroInfo.name; } else { auto stacks = owner.cb->battleGetAllStacks(); - vstd::erase_if(stacks, [i](const CStack *stack) //erase stack of other side and not coming from garrison - { return stack->side != i || !stack->base; }); + vstd::erase_if(stacks, [i](const CStack * stack) //erase stack of other side and not coming from garrison + { + return stack->side != i || !stack->base; + }); + + auto best = vstd::maxElementByFun(stacks, [](const CStack * stack) + { + return stack->type->AIValue; + }); - auto best = vstd::maxElementByFun(stacks, [](const CStack *stack){ return stack->type->AIValue; }); if(best != stacks.end()) //should be always but to be safe... { - new CAnimImage("TWCRPORT", (*best)->type->idNumber+2, 0, xs[i], 38); + icons.push_back(std::make_shared("TWCRPORT", (*best)->type->idNumber+2, 0, xs[i], 38)); sideNames[i] = CGI->creh->creatures[(*best)->type->idNumber]->namePl; } } } //printing attacker and defender's names - new CLabel( 89, 37, FONT_SMALL, TOPLEFT, Colors::WHITE, sideNames[0]); - new CLabel( 381, 53, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, sideNames[1]); + labels.push_back(std::make_shared(89, 37, FONT_SMALL, TOPLEFT, Colors::WHITE, sideNames[0])); + labels.push_back(std::make_shared(381, 53, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, sideNames[1])); //printing casualties for(int step = 0; step < 2; ++step) { if(br.casualties[step].size()==0) { - new CLabel( 235, 360 + 97*step, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[523]); + labels.push_back(std::make_shared(235, 360 + 97 * step, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[523])); } else { int xPos = 235 - (br.casualties[step].size()*32 + (br.casualties[step].size() - 1)*10)/2; //increment by 42 with each picture - int yPos = 344 + step*97; + int yPos = 344 + step * 97; for(auto & elem : br.casualties[step]) { - new CAnimImage("CPRSMALL", CGI->creh->creatures[elem.first]->iconIndex, 0, xPos, yPos); + icons.push_back(std::make_shared("CPRSMALL", CGI->creh->creatures[elem.first]->iconIndex, 0, xPos, yPos)); std::ostringstream amount; amount<(xPos + 16, yPos + 42, FONT_SMALL, CENTER, Colors::WHITE, amount.str())); xPos += 42; } } @@ -420,12 +483,20 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect bool weAreAttacker = !(owner.cb->battleGetMySide()); if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won { - int text=-1; + int text = 304; switch(br.result) { - case BattleResult::NORMAL: text = 304; break; - case BattleResult::ESCAPE: text = 303; break; - case BattleResult::SURRENDER: text = 302; break; + case BattleResult::NORMAL: + break; + case BattleResult::ESCAPE: + text = 303; + break; + case BattleResult::SURRENDER: + text = 302; + break; + default: + logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast(br.result)); + break; } CCS->musich->playMusic("Music/Win Battle", false); @@ -436,44 +507,43 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect if (ourHero) { str += CGI->generaltexth->allTexts[305]; - boost::algorithm::replace_first(str,"%s",ourHero->name); - boost::algorithm::replace_first(str,"%d",boost::lexical_cast(br.exp[weAreAttacker?0:1])); + boost::algorithm::replace_first(str, "%s", ourHero->name); + boost::algorithm::replace_first(str, "%d", boost::lexical_cast(br.exp[weAreAttacker ? 0 : 1])); } - new CTextBox(str, Rect(69, 203, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE); + description = std::make_shared(str, Rect(69, 203, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE); } else // we lose { + int text = 311; + std::string musicName = "Music/LoseCombat"; + std::string videoName = "LBSTART.BIK"; switch(br.result) { case BattleResult::NORMAL: - { - CCS->musich->playMusic("Music/LoseCombat", false); - CCS->videoh->open("LBSTART.BIK"); - new CLabel(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[311]); - break; - } - case BattleResult::ESCAPE: //flee - { - CCS->musich->playMusic("Music/Retreat Battle", false); - CCS->videoh->open("RTSTART.BIK"); - new CLabel(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[310]); - break; - } + break; + case BattleResult::ESCAPE: + musicName = "Music/Retreat Battle"; + videoName = "RTSTART.BIK"; + text = 310; + break; case BattleResult::SURRENDER: - { - CCS->musich->playMusic("Music/Surrender Battle", false); - CCS->videoh->open("SURRENDER.BIK"); - new CLabel(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[309]); - break; - } + musicName = "Music/Surrender Battle"; + videoName = "SURRENDER.BIK"; + text = 309; + break; + default: + logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast(br.result)); + break; } + CCS->musich->playMusic(musicName, false); + CCS->videoh->open(videoName); + + labels.push_back(std::make_shared(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[text])); } } -CBattleResultWindow::~CBattleResultWindow() -{ -} +CBattleResultWindow::~CBattleResultWindow() = default; void CBattleResultWindow::activate() { @@ -628,52 +698,11 @@ void CClickableHex::clickRight(tribool down, bool previousState) } } -CHeroInfoWindow::CHeroInfoWindow(const InfoAboutHero &hero, Point *position) : CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP") -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - if (position != nullptr) - moveTo(*position); - background->colorize(hero.owner); //maybe add this functionality to base class? - - int attack = hero.details->primskills[0]; - int defense = hero.details->primskills[1]; - int power = hero.details->primskills[2]; - int knowledge = hero.details->primskills[3]; - int morale = hero.details->morale; - int luck = hero.details->luck; - int currentSpellPoints = hero.details->mana; - int maxSpellPoints = hero.details->manaLimit; - - new CAnimImage("PortraitsLarge", hero.portrait, 0, 10, 6); - - //primary stats - new CLabel(9, 75, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[380] + ":"); - new CLabel(9, 87, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[381] + ":"); - new CLabel(9, 99, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[382] + ":"); - new CLabel(9, 111, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[383] + ":"); - - new CLabel(69, 87, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(attack)); - new CLabel(69, 99, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(defense)); - new CLabel(69, 111, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(power)); - new CLabel(69, 123, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(knowledge)); - - //morale+luck - new CLabel(9, 131, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[384] + ":"); - new CLabel(9, 143, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[385] + ":"); - - new CAnimImage("IMRL22", morale + 3, 0, 47, 131); - new CAnimImage("ILCK22", luck + 3, 0, 47, 143); - - //spell points - new CLabel(39, 174, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, CGI->generaltexth->allTexts[387]); - new CLabel(39, 186, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints)); -} - CStackQueue::CStackQueue(bool Embedded, CBattleInterface * _owner) : embedded(Embedded), owner(_owner) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); if(embedded) { pos.w = QUEUE_SIZE * 37; @@ -689,7 +718,7 @@ CStackQueue::CStackQueue(bool Embedded, CBattleInterface * _owner) pos.w = 800; pos.h = 85; - new CFilledTexture("DIBOXBCK", Rect(0,0, pos.w, pos.h)); + background = std::make_shared("DIBOXBCK", Rect(0, 0, pos.w, pos.h)); icons = std::make_shared("TWCRPORT"); stateIcons = std::make_shared("VCMI/BATTLEQUEUE/STATESSMALL"); @@ -701,14 +730,12 @@ CStackQueue::CStackQueue(bool Embedded, CBattleInterface * _owner) stackBoxes.resize(QUEUE_SIZE); for (int i = 0; i < stackBoxes.size(); i++) { - stackBoxes[i] = new StackBox(this); - stackBoxes[i]->moveBy(Point(1 + (embedded ? 36 : 80)*i, 0)); + stackBoxes[i] = std::make_shared(this); + stackBoxes[i]->moveBy(Point(1 + (embedded ? 36 : 80) * i, 0)); } } -CStackQueue::~CStackQueue() -{ -} +CStackQueue::~CStackQueue() = default; void CStackQueue::update() { @@ -721,60 +748,56 @@ void CStackQueue::update() for(size_t turn = 0; turn < queueData.size() && boxIndex < stackBoxes.size(); turn++) { for(size_t unitIndex = 0; unitIndex < queueData[turn].size() && boxIndex < stackBoxes.size(); boxIndex++, unitIndex++) - stackBoxes[boxIndex]->setStack(queueData[turn][unitIndex], turn); + stackBoxes[boxIndex]->setUnit(queueData[turn][unitIndex], turn); } for(; boxIndex < stackBoxes.size(); boxIndex++) - stackBoxes[boxIndex]->setStack(nullptr); + stackBoxes[boxIndex]->setUnit(nullptr); } CStackQueue::StackBox::StackBox(CStackQueue * owner) - : bg(nullptr), - icon(nullptr), - amount(nullptr), - stateIcon(nullptr) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - bg = new CPicture(owner->embedded ? "StackQueueSmall" : "StackQueueLarge" ); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background = std::make_shared(owner->embedded ? "StackQueueSmall" : "StackQueueLarge"); - pos.w = bg->pos.w; - pos.h = bg->pos.h; + pos.w = background->pos.w; + pos.h = background->pos.h; if(owner->embedded) { - icon = new CAnimImage(owner->icons, 0, 0, 5, 2); - amount = new CLabel(pos.w/2, pos.h - 7, FONT_SMALL, CENTER, Colors::WHITE); + icon = std::make_shared(owner->icons, 0, 0, 5, 2); + amount = std::make_shared(pos.w/2, pos.h - 7, FONT_SMALL, CENTER, Colors::WHITE); } else { - icon = new CAnimImage(owner->icons, 0, 0, 9, 1); - amount = new CLabel(pos.w/2, pos.h - 8, FONT_MEDIUM, CENTER, Colors::WHITE); + icon = std::make_shared(owner->icons, 0, 0, 9, 1); + amount = std::make_shared(pos.w/2, pos.h - 8, FONT_MEDIUM, CENTER, Colors::WHITE); int icon_x = pos.w - 17; int icon_y = pos.h - 18; - stateIcon = new CAnimImage(owner->stateIcons, 0, 0, icon_x, icon_y); + stateIcon = std::make_shared(owner->stateIcons, 0, 0, icon_x, icon_y); stateIcon->visible = false; } } -void CStackQueue::StackBox::setStack(const battle::Unit * nStack, size_t turn) +void CStackQueue::StackBox::setUnit(const battle::Unit * unit, size_t turn) { - if(nStack) + if(unit) { - bg->colorize(nStack->unitOwner()); + background->colorize(unit->unitOwner()); icon->visible = true; - icon->setFrame(nStack->creatureIconIndex()); - amount->setText(makeNumberShort(nStack->getCount())); + icon->setFrame(unit->creatureIconIndex()); + amount->setText(makeNumberShort(unit->getCount())); if(stateIcon) { - if(nStack->defended(turn) || (turn > 0 && nStack->defended(turn - 1))) + if(unit->defended(turn) || (turn > 0 && unit->defended(turn - 1))) { stateIcon->setFrame(0, 0); stateIcon->visible = true; } - else if(nStack->waited(turn)) + else if(unit->waited(turn)) { stateIcon->setFrame(1, 0); stateIcon->visible = true; @@ -787,7 +810,7 @@ void CStackQueue::StackBox::setStack(const battle::Unit * nStack, size_t turn) } else { - bg->colorize(PlayerColor::NEUTRAL); + background->colorize(PlayerColor::NEUTRAL); icon->visible = false; icon->setFrame(0); amount->setText(""); diff --git a/client/battle/CBattleInterfaceClasses.h b/client/battle/CBattleInterfaceClasses.h index 85f1a0ceb..cdb496502 100644 --- a/client/battle/CBattleInterfaceClasses.h +++ b/client/battle/CBattleInterfaceClasses.h @@ -17,10 +17,12 @@ struct SDL_Surface; class CGHeroInstance; class CBattleInterface; class CPicture; +class CFilledTexture; class CButton; class CToggleButton; class CToggleGroup; class CLabel; +class CTextBox; struct BattleResult; class CStack; namespace battle @@ -79,22 +81,25 @@ public: class CHeroInfoWindow : public CWindowObject { +private: + std::vector> labels; + std::vector> icons; public: - CHeroInfoWindow(const InfoAboutHero &hero, Point *position); + CHeroInfoWindow(const InfoAboutHero & hero, Point * position); }; /// Class which manages the battle options window class CBattleOptionsWindow : public CIntObject { private: - CPicture * background; - CButton * setToDefault, * exit; - CToggleButton * viewGrid, * movementShadow, * mouseShadow; - CToggleGroup * animSpeeds; - - std::vector labels; + std::shared_ptr background; + std::shared_ptr setToDefault; + std::shared_ptr exit; + std::shared_ptr animSpeeds; + std::vector> labels; + std::vector> toggles; public: - CBattleOptionsWindow(const SDL_Rect &position, CBattleInterface *owner); + CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface * owner); void bDefaultf(); //default button callback void bExitf(); //exit button callback @@ -104,10 +109,14 @@ public: class CBattleResultWindow : public CIntObject { private: - CButton *exit; - CPlayerInterface &owner; + std::shared_ptr background; + std::vector> labels; + std::shared_ptr exit; + std::vector> icons; + std::shared_ptr description; + CPlayerInterface & owner; public: - CBattleResultWindow(const BattleResult & br, const SDL_Rect & pos, CPlayerInterface &_owner); + CBattleResultWindow(const BattleResult & br, CPlayerInterface & _owner); ~CBattleResultWindow(); void bExitf(); //exit button callback @@ -143,24 +152,26 @@ class CStackQueue : public CIntObject class StackBox : public CIntObject { public: - CPicture * bg; - CAnimImage * icon; - CLabel * amount; - CAnimImage * stateIcon; + std::shared_ptr background; + std::shared_ptr icon; + std::shared_ptr amount; + std::shared_ptr stateIcon; - void setStack(const battle::Unit * nStack, size_t turn = 0); + void setUnit(const battle::Unit * unit, size_t turn = 0); StackBox(CStackQueue * owner); }; -public: static const int QUEUE_SIZE = 10; - const bool embedded; - std::vector stackBoxes; + std::shared_ptr background; + std::vector> stackBoxes; CBattleInterface * owner; std::shared_ptr icons; std::shared_ptr stateIcons; +public: + const bool embedded; + CStackQueue(bool Embedded, CBattleInterface * _owner); ~CStackQueue(); void update(); diff --git a/client/battle/CCreatureAnimation.cpp b/client/battle/CCreatureAnimation.cpp index ff181356b..9700a90ba 100644 --- a/client/battle/CCreatureAnimation.cpp +++ b/client/battle/CCreatureAnimation.cpp @@ -286,7 +286,7 @@ void CCreatureAnimation::nextFrame(SDL_Surface * dest, bool attacker) { size_t frame = floor(currentFrame); - IImage * image = nullptr; + std::shared_ptr image; if(attacker) image = forward->getImage(frame, type); diff --git a/client/gui/CAnimation.cpp b/client/gui/CAnimation.cpp index 4759f27d0..316a5ef56 100644 --- a/client/gui/CAnimation.cpp +++ b/client/gui/CAnimation.cpp @@ -90,7 +90,7 @@ public: 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; + std::shared_ptr scaleFast(float scale) const override; void exportBitmap(const boost::filesystem::path & path) const override; void playerColored(PlayerColor player) override; void setFlagColor(PlayerColor player) override; @@ -148,7 +148,7 @@ public: 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; + std::shared_ptr scaleFast(float scale) const override; void exportBitmap(const boost::filesystem::path & path) const override; @@ -801,22 +801,9 @@ CompImageLoader::~CompImageLoader() * Classes for images, support loading from file and drawing on surface * *************************************************************************/ -IImage::IImage(): - refCount(1) -{ +IImage::IImage() = default; +IImage::~IImage() = default; -} - -bool IImage::decreaseRef() -{ - refCount--; - return refCount <= 0; -} - -void IImage::increaseRef() -{ - refCount++; -} SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group, bool compressed) : surf(nullptr), @@ -957,7 +944,7 @@ void SDLImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alpha } } -std::unique_ptr SDLImage::scaleFast(float scale) const +std::shared_ptr SDLImage::scaleFast(float scale) const { auto scaled = CSDL_Ext::scaleSurfaceFast(surf, surf->w * scale, surf->h * scale); @@ -976,7 +963,7 @@ std::unique_ptr SDLImage::scaleFast(float scale) const ret->margins.x = (int) round((float)margins.x * scale); ret->margins.y = (int) round((float)margins.y * scale); - return std::unique_ptr(ret); + return std::shared_ptr(ret); } void SDLImage::exportBitmap(const boost::filesystem::path& path) const @@ -1156,7 +1143,7 @@ void CompImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alph } -std::unique_ptr CompImage::scaleFast(float scale) const +std::shared_ptr CompImage::scaleFast(float scale) const { //todo: CompImage::scaleFast @@ -1331,7 +1318,7 @@ void CompImage::exportBitmap(const boost::filesystem::path & path) const * CAnimation for animations handling, can load part of file if needed * *************************************************************************/ -IImage * CAnimation::getFromExtraDef(std::string filename) +std::shared_ptr CAnimation::getFromExtraDef(std::string filename) { size_t pos = filename.find(':'); if (pos == -1) @@ -1364,7 +1351,6 @@ bool CAnimation::loadFrame(size_t frame, size_t group) auto image = getImage(frame, group, false); if(image) { - image->increaseRef(); return true; } @@ -1378,22 +1364,22 @@ bool CAnimation::loadFrame(size_t frame, size_t group) if(vstd::contains(frameList, group) && frameList.at(group) > frame) // frame is present { if(compressed) - images[group][frame] = new CompImage(defFile, frame, group); + images[group][frame] = std::make_shared(defFile, frame, group); else - images[group][frame] = new SDLImage(defFile, frame, group); + images[group][frame] = std::make_shared(defFile, frame, group); return true; } } // still here? image is missing printError(frame, group, "LoadFrame"); - images[group][frame] = new SDLImage("DEFAULT", compressed); + images[group][frame] = std::make_shared("DEFAULT", compressed); } else //load from separate file { auto img = getFromExtraDef(source[group][frame]["file"].String()); if(!img) - img = new SDLImage(source[group][frame]); + img = std::make_shared(source[group][frame]); images[group][frame] = img; return true; @@ -1404,15 +1390,11 @@ bool CAnimation::loadFrame(size_t frame, size_t group) bool CAnimation::unloadFrame(size_t frame, size_t group) { auto image = getImage(frame, group, false); - if (image) + if(image) { - //decrease ref count for image and delete if needed - if (image->decreaseRef()) - { - delete image; - images[group].erase(frame); - } - if (images[group].empty()) + images[group].erase(frame); + + if(images[group].empty()) images.erase(group); return true; } @@ -1558,16 +1540,6 @@ CAnimation::CAnimation(): CAnimation::~CAnimation() { - if(preloaded) - unload(); - - if(!images.empty()) - { - logGlobal->warn("Warning: not all frames were unloaded from %s", name); - for (auto & elem : images) - for (auto & _image : elem.second) - delete _image.second; - } if(defFile) delete defFile; } @@ -1599,7 +1571,7 @@ void CAnimation::setCustom(std::string filename, size_t frame, size_t group) //FIXME: update image if already loaded } -IImage * CAnimation::getImage(size_t frame, size_t group, bool verbose) const +std::shared_ptr CAnimation::getImage(size_t frame, size_t group, bool verbose) const { auto groupIter = images.find(group); if (groupIter != images.end()) diff --git a/client/gui/CAnimation.h b/client/gui/CAnimation.h index 1b4e3ab0d..d988dca8e 100644 --- a/client/gui/CAnimation.h +++ b/client/gui/CAnimation.h @@ -22,7 +22,6 @@ class CDefFile; */ class IImage { - int refCount; public: using BorderPallete = std::array; @@ -30,14 +29,10 @@ public: 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; + virtual std::shared_ptr scaleFast(float scale) const = 0; virtual void exportBitmap(const boost::filesystem::path & path) const = 0; - //decrease ref count, returns true if image can be deleted (refCount <= 0) - bool decreaseRef(); - void increaseRef(); - //Change palette to specific player virtual void playerColored(PlayerColor player)=0; @@ -57,7 +52,7 @@ public: virtual void verticalFlip() = 0; IImage(); - virtual ~IImage() {}; + virtual ~IImage(); }; /// Class for handling animation @@ -68,7 +63,7 @@ private: std::map > source; //bitmap[group][position], store objects with loaded bitmaps - std::map > images; + std::map > > images; //animation file name std::string name; @@ -95,7 +90,7 @@ private: //not a very nice method to get image from another def file //TODO: remove after implementing resource manager - IImage * getFromExtraDef(std::string filename); + std::shared_ptr getFromExtraDef(std::string filename); public: CAnimation(std::string Name, bool Compressed = false); @@ -109,8 +104,7 @@ public: //add custom surface to the selected position. void setCustom(std::string filename, size_t frame, size_t group=0); - //get pointer to image from specific group, nullptr if not found - IImage * getImage(size_t frame, size_t group=0, bool verbose=true) const; + std::shared_ptr getImage(size_t frame, size_t group=0, bool verbose=true) const; void exportBitmaps(const boost::filesystem::path & path) const; diff --git a/client/gui/CGuiHandler.h b/client/gui/CGuiHandler.h index efe5d73c0..c786cb0f8 100644 --- a/client/gui/CGuiHandler.h +++ b/client/gui/CGuiHandler.h @@ -150,7 +150,6 @@ struct SSetCaptureState #define OBJ_CONSTRUCTION SObjectConstruction obj__i(this) #define OBJECT_CONSTRUCTION_CAPTURING(actions) defActions = actions; SSetCaptureState obj__i1(true, actions); SObjectConstruction obj__i(this) -#define OBJ_CONSTRUCTION_CAPTURING_ALL defActions = 255; SSetCaptureState obj__i1(true, 255); SObjectConstruction obj__i(this) +#define OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(actions) SSetCaptureState obj__i1(true, actions); SObjectConstruction obj__i(this) + #define OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE defActions = 255 - DISPOSE; SSetCaptureState obj__i1(true, 255 - DISPOSE); SObjectConstruction obj__i(this) -#define BLOCK_CAPTURING SSetCaptureState obj__i(false, 0) -#define BLOCK_CAPTURING_DONT_TOUCH_REC_ACTIONS SSetCaptureState obj__i(false, GH.defActionsDef) diff --git a/client/gui/CIntObject.cpp b/client/gui/CIntObject.cpp index dd2bfe6b0..e3a707dd5 100644 --- a/client/gui/CIntObject.cpp +++ b/client/gui/CIntObject.cpp @@ -40,6 +40,23 @@ CIntObject::CIntObject(int used_, Point pos_): GH.createdObj.front()->addChild(this, true); } +CIntObject::~CIntObject() +{ + if(active_m) + deactivate(); + + while(!children.empty()) + { + if((defActions & DISPOSE) && (children.front()->recActions & DISPOSE)) + delete children.front(); + else + removeChild(children.front()); + } + + if(parent_m) + parent_m->removeChild(this); +} + void CIntObject::setTimer(int msToTrigger) { if (!(active & TIME)) @@ -125,24 +142,6 @@ void CIntObject::deactivate(ui16 what) GH.handleElementDeActivate(this, what); } -CIntObject::~CIntObject() -{ - if (active_m) - deactivate(); - - if(defActions & DISPOSE) - { - while (!children.empty()) - if(children.front()->recActions & DISPOSE) - delete children.front(); - else - removeChild(children.front()); - } - - if(parent_m) - parent_m->removeChild(this); -} - void CIntObject::click(EIntObjMouseBtnType btn, tribool down, bool previousState) { switch(btn) @@ -291,8 +290,12 @@ void CIntObject::removeChild(CIntObject * child, bool adjustPosition) if (!child) return; - assert(vstd::contains(children, child)); - assert(child->parent_m == this); + if(!vstd::contains(children, child)) + throw std::runtime_error("Wrong child object"); + + if(child->parent_m != this) + throw std::runtime_error("Wrong child object"); + children -= child; child->parent_m = nullptr; if(adjustPosition) diff --git a/client/gui/CIntObject.h b/client/gui/CIntObject.h index b2f04df75..30a14d36c 100644 --- a/client/gui/CIntObject.h +++ b/client/gui/CIntObject.h @@ -66,7 +66,6 @@ enum class EIntObjMouseBtnType { LEFT, MIDDLE, RIGHT }; // Base UI element class CIntObject : public IShowActivatable //interface object { - ui16 used;//change via addUsed() or delUsed //time handling @@ -80,6 +79,7 @@ class CIntObject : public IShowActivatable //interface object //non-const versions of fields to allow changing them in CIntObject CIntObject *parent_m; //parent object ui16 active_m; + protected: //activate or deactivate specific action (LCLICK, RCLICK...) void activate(ui16 what); diff --git a/client/lobby/CBonusSelection.cpp b/client/lobby/CBonusSelection.cpp index 101d22e10..59c47d039 100644 --- a/client/lobby/CBonusSelection.cpp +++ b/client/lobby/CBonusSelection.cpp @@ -323,7 +323,7 @@ void CBonusSelection::createBonusesIcons() break; } - CToggleButton * bonusButton = new CToggleButton(Point(475 + i * 68, 455), "", CButton::tooltip(desc, desc)); + std::shared_ptr bonusButton = std::make_shared(Point(475 + i * 68, 455), "", CButton::tooltip(desc, desc)); if(picNumber != -1) picName += ":" + boost::lexical_cast(picNumber); diff --git a/client/lobby/CLobbyScreen.cpp b/client/lobby/CLobbyScreen.cpp index cbd1040cb..469177c9d 100644 --- a/client/lobby/CLobbyScreen.cpp +++ b/client/lobby/CLobbyScreen.cpp @@ -134,7 +134,7 @@ void CLobbyScreen::startScenario(bool allowOnlyAI) catch(ExceptionNoHuman & e) { // You must position yourself prior to starting the game. - CInfoWindow::showYesNoDialog(std::ref(CGI->generaltexth->allTexts[530]), nullptr, 0, std::bind(&CLobbyScreen::startScenario, this, true), false, PlayerColor(1)); + CInfoWindow::showYesNoDialog(std::ref(CGI->generaltexth->allTexts[530]), CInfoWindow::TCompsInfo(), 0, std::bind(&CLobbyScreen::startScenario, this, true), PlayerColor(1)); } catch(ExceptionNoTemplate & e) { diff --git a/client/lobby/CSavingScreen.cpp b/client/lobby/CSavingScreen.cpp index c6324ff3e..3a97943b4 100644 --- a/client/lobby/CSavingScreen.cpp +++ b/client/lobby/CSavingScreen.cpp @@ -88,7 +88,7 @@ void CSavingScreen::saveGame() { std::string hlp = CGI->generaltexth->allTexts[493]; //%s exists. Overwrite? boost::algorithm::replace_first(hlp, "%s", tabSel->inputName->text); - LOCPLINT->showYesNoDialog(hlp, overWrite, 0, false); + LOCPLINT->showYesNoDialog(hlp, overWrite, nullptr); } else { diff --git a/client/lobby/CSelectionBase.cpp b/client/lobby/CSelectionBase.cpp index 6ea17a392..9cb06eab0 100644 --- a/client/lobby/CSelectionBase.cpp +++ b/client/lobby/CSelectionBase.cpp @@ -148,7 +148,7 @@ InfoCard::InfoCard() for(int i = 0; i < 5; i++) { - auto button = new CToggleButton(Point(110 + i * 32, 450), difButns[i], CGI->generaltexth->zelp[24 + i]); + auto button = std::make_shared(Point(110 + i * 32, 450), difButns[i], CGI->generaltexth->zelp[24 + i]); iconDifficulty->addToggle(i, button); if(SEL->screenType != ESelectionScreen::newGame) diff --git a/client/lobby/OptionsTab.cpp b/client/lobby/OptionsTab.cpp index 7ff0aeefd..9562bf62b 100644 --- a/client/lobby/OptionsTab.cpp +++ b/client/lobby/OptionsTab.cpp @@ -367,12 +367,12 @@ void OptionsTab::CPlayerOptionTooltipBox::genTownWindow() genHeader(); labelAssociatedCreatures = std::make_shared(pos.w / 2 + 8, 122, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[79]); - std::vector components; + std::vector> components; const CTown * town = CGI->townh->factions[settings.castle]->town; for(auto & elem : town->creatures) { if(!elem.empty()) - components.push_back(new CComponent(CComponent::creature, elem.front(), 0, CComponent::tiny)); + components.push_back(std::make_shared(CComponent::creature, elem.front(), 0, CComponent::tiny)); } boxAssociatedCreatures = std::make_shared(components, Rect(10, 140, pos.w - 20, 140)); } diff --git a/client/lobby/RandomMapTab.cpp b/client/lobby/RandomMapTab.cpp index 8879ddc25..cd87598b2 100644 --- a/client/lobby/RandomMapTab.cpp +++ b/client/lobby/RandomMapTab.cpp @@ -219,7 +219,7 @@ void RandomMapTab::addButtonsWithRandToGroup(CToggleGroup * group, const std::ve // Buttons are relative to button group, TODO better solution? SObjectConstruction obj__i(group); const std::string RANDOM_DEF = "RANRAND"; - group->addToggle(CMapGenOptions::RANDOM_SIZE, new CToggleButton(Point(256, 0), RANDOM_DEF, CGI->generaltexth->zelp[helpRandIndex])); + group->addToggle(CMapGenOptions::RANDOM_SIZE, std::make_shared(Point(256, 0), RANDOM_DEF, CGI->generaltexth->zelp[helpRandIndex])); group->setSelected(CMapGenOptions::RANDOM_SIZE); } @@ -230,10 +230,9 @@ void RandomMapTab::addButtonsToGroup(CToggleGroup * group, const std::vectorgeneraltexth->zelp[helpStartIndex + i]); + auto button = std::make_shared(Point(i * btnWidth, 0), defs[i + nStart], CGI->generaltexth->zelp[helpStartIndex + i]); // For blocked state we should use pressed image actually button->setImageOrder(0, 1, 1, 3); - group->addToggle(i + nStart, button); } } @@ -243,7 +242,7 @@ void RandomMapTab::deactivateButtonsFrom(CToggleGroup * group, int startId) logGlobal->debug("Blocking buttons from %d", startId); for(auto toggle : group->buttons) { - if(auto button = dynamic_cast(toggle.second)) + if(auto button = std::dynamic_pointer_cast(toggle.second)) { if(startId == CMapGenOptions::RANDOM_SIZE || toggle.first < startId) { diff --git a/client/mainmenu/CMainMenu.cpp b/client/mainmenu/CMainMenu.cpp index 53ef11bc5..ee121bdd4 100644 --- a/client/mainmenu/CMainMenu.cpp +++ b/client/mainmenu/CMainMenu.cpp @@ -94,16 +94,16 @@ CMenuScreen::CMenuScreen(const JsonNode & configNode) //Hardcoded entry menuNameToEntry.push_back("credits"); - tabs = std::make_shared(std::bind(&CMenuScreen::createTab, this, _1), CTabbedInt::DestroyFunc()); + tabs = std::make_shared(std::bind(&CMenuScreen::createTab, this, _1)); tabs->type |= REDRAW_PARENT; } -CIntObject * CMenuScreen::createTab(size_t index) +std::shared_ptr CMenuScreen::createTab(size_t index) { if(config["items"].Vector().size() == index) - return new CreditsScreen(); - - return new CMenuEntry(this, config["items"].Vector()[index]); + return std::make_shared(); + else + return std::make_shared(this, config["items"].Vector()[index]); } void CMenuScreen::show(SDL_Surface * to) @@ -175,7 +175,7 @@ static std::function genCommand(CMenuScreen * menu, std::vector *)nullptr, false, PlayerColor(1)); + return std::bind(CInfoWindow::showInfoDialog, "Sorry, tutorial is not implemented yet\n", std::vector>(), PlayerColor(1)); } break; } @@ -190,18 +190,18 @@ static std::function genCommand(CMenuScreen * menu, std::vector *)nullptr, false, PlayerColor(1)); + return std::bind(CInfoWindow::showInfoDialog, "Sorry, tutorial is not implemented yet\n", std::vector>(), PlayerColor(1)); } } break; case 4: //exit { - return std::bind(CInfoWindow::showYesNoDialog, std::ref(CGI->generaltexth->allTexts[69]), (const std::vector *)nullptr, do_quit, 0, false, PlayerColor(1)); + return std::bind(CInfoWindow::showYesNoDialog, std::ref(CGI->generaltexth->allTexts[69]), std::vector>(), do_quit, 0, PlayerColor(1)); } break; case 5: //highscores { - return std::bind(CInfoWindow::showInfoDialog, "Sorry, high scores menu is not implemented yet\n", (const std::vector *)nullptr, false, PlayerColor(1)); + return std::bind(CInfoWindow::showInfoDialog, "Sorry, high scores menu is not implemented yet\n", std::vector>(), PlayerColor(1)); } } } @@ -383,7 +383,7 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType) blitAt(CPicture("MUMAP.bmp"), 16, 77, *background); pos = background->center(); //center, window has size of bg graphic - statusBar = std::make_shared(new CPicture(Rect(7, 465, 440, 18), 0)); //226, 472 + statusBar = std::make_shared(std::make_shared(Rect(7, 465, 440, 18), 0)); //226, 472 playerName = std::make_shared(Rect(19, 436, 334, 16), *background); playerName->setText(settings["general"]["playerName"].String()); playerName->cb += std::bind(&CMultiMode::onNameChange, this, _1); @@ -431,7 +431,7 @@ CMultiPlayers::CMultiPlayers(const std::string & firstPlayer, ESelectionScreen S buttonOk = std::make_shared(Point(95, 338), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CMultiPlayers::enterSelectionScreen, this), SDLK_RETURN); buttonCancel = std::make_shared(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CGuiHandler::popIntTotally, std::ref(GH), this), SDLK_ESCAPE); - statusBar = std::make_shared(new CPicture(Rect(7, 381, 348, 18), 0)); //226, 472 + statusBar = std::make_shared(std::make_shared(Rect(7, 381, 348, 18), 0)); //226, 472 inputNames[0]->setText(firstPlayer, true); inputNames[0]->giveFocus(); @@ -489,7 +489,7 @@ CSimpleJoinScreen::CSimpleJoinScreen(bool host) inputPort->setText(CServerHandler::getDefaultPortStr(), true); buttonCancel = std::make_shared(Point(142, 142), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CSimpleJoinScreen::leaveScreen, this), SDLK_ESCAPE); - statusBar = std::make_shared(new CPicture(Rect(7, 186, 218, 18), 0)); + statusBar = std::make_shared(std::make_shared(Rect(7, 186, 218, 18), 0)); } void CSimpleJoinScreen::connectToServer() diff --git a/client/mainmenu/CMainMenu.h b/client/mainmenu/CMainMenu.h index 22e75e4ff..f171cb427 100644 --- a/client/mainmenu/CMainMenu.h +++ b/client/mainmenu/CMainMenu.h @@ -42,7 +42,7 @@ class CMenuScreen : public CWindowObject std::shared_ptr background; std::vector> images; - CIntObject * createTab(size_t index); + std::shared_ptr createTab(size_t index); public: std::vector menuNameToEntry; diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index 7121504f7..693e6e8fd 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -398,7 +398,7 @@ CMapHandler::CMapBlitter *CMapHandler::resolveBlitter(const MapDrawingInfo * inf return normalBlitter; } -void CMapHandler::CMapNormalBlitter::drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const +void CMapHandler::CMapNormalBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const { source->draw(targetSurf, destRect, sourceRect); } @@ -470,7 +470,7 @@ CMapHandler::CMapNormalBlitter::CMapNormalBlitter(CMapHandler * parent) defaultTileRect = Rect(0, 0, tileSize, tileSize); } -IImage * CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const +std::shared_ptr CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const { int ownerIndex = 0; if(owner < PlayerColor::PLAYER_LIMIT) @@ -501,7 +501,7 @@ IImage * CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, Pla case Obj::RESOURCE: return info->icons->getImage((int)EWorldViewIcon::RES_WOOD + subId + ownerIndex); } - return nullptr; + return std::shared_ptr(); } void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos() @@ -536,7 +536,7 @@ void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos() topTile.y = parent->sizes.y - tileCount.y; } -void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const +void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const { auto scaled = parent->cache.requestWorldViewCacheOrCreate(cacheType, source); @@ -604,7 +604,7 @@ void CMapHandler::CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf) } } -void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const +void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const { if (moving) return; @@ -612,7 +612,7 @@ void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, c CMapBlitter::drawHeroFlag(targetSurf, source, sourceRect, destRect, false); } -void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const +void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr source, SDL_Rect * sourceRect, bool moving) const { if (moving) return; @@ -729,12 +729,12 @@ void CMapHandler::CMapBlitter::drawOverlayEx(SDL_Surface * targetSurf) //nothing to do here } -void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const +void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const { drawElement(EMapCacheType::HERO_FLAGS, source, sourceRect, targetSurf, destRect); } -void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const +void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr source, SDL_Rect * sourceRect, bool moving) const { Rect dstRect(realTileRect); drawElement(EMapCacheType::OBJECTS, source, sourceRect, targetSurf, &dstRect); @@ -830,7 +830,7 @@ void CMapHandler::CMapBlitter::drawFow(SDL_Surface * targetSurf) const if (retBitmapID < 0) retBitmapID = - parent->hideBitmap[pos.x][pos.y][pos.z] - 1; //fully hidden - const IImage * image = nullptr; + std::shared_ptr image; if (retBitmapID >= 0) image = parent->FoWpartialHide.at(retBitmapID); @@ -1006,22 +1006,22 @@ CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findBoatBitmap(const CGB return CMapHandler::AnimBitmapHolder(); } -IImage * CMapHandler::CMapBlitter::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const +std::shared_ptr CMapHandler::CMapBlitter::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const { - if (!hero) - return nullptr; + if(!hero) + return std::shared_ptr(); - if (hero->boat) + if(hero->boat) return findBoatFlagBitmap(hero->boat, anim, color, group, hero->moveDir); return findHeroFlagBitmap(hero, anim, color, group); } -IImage * CMapHandler::CMapBlitter::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const +std::shared_ptr CMapHandler::CMapBlitter::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const { return findFlagBitmapInternal(graphics->heroFlagAnimations.at(color->getNum()), anim, group, hero->moveDir, !hero->isStanding); } -IImage * CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int group, ui8 dir) const +std::shared_ptr CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int group, ui8 dir) const { int boatType = boat->subID; if(boatType < 0 || boatType >= graphics->boatFlagAnimations.size()) @@ -1043,7 +1043,7 @@ IImage * CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int a return findFlagBitmapInternal(subtypeFlags.at(colorIndex), anim, group, dir, false); } -IImage * CMapHandler::CMapBlitter::findFlagBitmapInternal(std::shared_ptr animation, int anim, int group, ui8 dir, bool moving) const +std::shared_ptr CMapHandler::CMapBlitter::findFlagBitmapInternal(std::shared_ptr animation, int anim, int group, ui8 dir, bool moving) const { size_t groupSize = animation->size(group); if(groupSize == 0) @@ -1438,22 +1438,21 @@ void CMapHandler::CMapCache::updateWorldViewScale(float scale) worldViewCachedScale = scale; } -IImage * CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CMapHandler::EMapCacheType type, const IImage * fullSurface) +std::shared_ptr CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CMapHandler::EMapCacheType type, std::shared_ptr fullSurface) { - intptr_t key = (intptr_t) fullSurface; + intptr_t key = (intptr_t) (fullSurface.get()); auto & cache = data[(ui8)type]; auto iter = cache.find(key); if(iter == cache.end()) { auto scaled = fullSurface->scaleFast(worldViewCachedScale); - IImage * ret = scaled.get(); - cache[key] = std::move(scaled); - return ret; + cache[key] = scaled; + return scaled; } else { - return (*iter).second.get(); + return (*iter).second; } } diff --git a/client/mapHandler.h b/client/mapHandler.h index 261414efd..6d460e32e 100644 --- a/client/mapHandler.h +++ b/client/mapHandler.h @@ -159,7 +159,7 @@ class CMapHandler /// temporarily caches rescaled frames for map world view redrawing class CMapCache { - std::array< std::map>, (ui8)EMapCacheType::AFTER_LAST> data; + std::array< std::map>, (ui8)EMapCacheType::AFTER_LAST> data; float worldViewCachedScale; public: CMapCache(); @@ -168,17 +168,17 @@ class CMapHandler /// updates scale and determines if currently cached data is still valid void updateWorldViewScale(float scale); /// 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); + std::shared_ptr requestWorldViewCacheOrCreate(EMapCacheType type, std::shared_ptr fullSurface); }; /// 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 { - IImage * objBitmap; // main object bitmap - IImage * flagBitmap; // flag bitmap for the object (probably only for heroes and boats with heroes) + std::shared_ptr objBitmap; // main object bitmap + std::shared_ptr 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(IImage * objBitmap_ = nullptr, IImage * flagBitmap_ = nullptr, bool moving = false) + AnimBitmapHolder(std::shared_ptr objBitmap_ = nullptr, std::shared_ptr flagBitmap_ = nullptr, bool moving = false) : objBitmap(objBitmap_), flagBitmap(flagBitmap_), isMoving(moving) @@ -202,7 +202,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, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const = 0; + virtual void drawElement(EMapCacheType cacheType, std::shared_ptr source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const = 0; // first drawing pass @@ -214,8 +214,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, 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; + virtual void drawObject(SDL_Surface * targetSurf, std::shared_ptr source, SDL_Rect * sourceRect, bool moving) const; + virtual void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const; // second drawing pass @@ -249,10 +249,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; - 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; + std::shared_ptr findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const; + std::shared_ptr findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const; + std::shared_ptr findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int group, ui8 dir) const; + std::shared_ptr findFlagBitmapInternal(std::shared_ptr animation, int anim, int group, ui8 dir, bool moving) const; public: CMapBlitter(CMapHandler * p); @@ -265,7 +265,7 @@ class CMapHandler class CMapNormalBlitter : public CMapBlitter { protected: - void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override; + void drawElement(EMapCacheType cacheType, std::shared_ptr 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; @@ -277,12 +277,12 @@ class CMapHandler class CMapWorldViewBlitter : public CMapBlitter { private: - IImage * objectToIcon(Obj id, si32 subId, PlayerColor owner) const; + std::shared_ptr objectToIcon(Obj id, si32 subId, PlayerColor owner) const; protected: - void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override; + void drawElement(EMapCacheType cacheType, std::shared_ptr source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override; void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override; - void drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override; - void drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const override; + void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override; + void drawObject(SDL_Surface * targetSurf, std::shared_ptr 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; @@ -347,7 +347,7 @@ public: //FIXME: unique_ptr should be enough, but fails to compile in MSVS 2013 typedef std::vector, 4>> TFlippedAnimations; //[type, rotation] - typedef std::vector>> TFlippedCache;//[type, view type, rotation] + typedef std::vector, 4>>> TFlippedCache;//[type, view type, rotation] TFlippedAnimations terrainAnimations;//[terrain type, rotation] TFlippedCache terrainImages;//[terrain type, view type, rotation] @@ -359,14 +359,14 @@ public: TFlippedCache riverImages;//[river type, view type, rotation] //Fog of War cache (not owned) - std::vector FoWfullHide; + std::vector> FoWfullHide; std::vector > > hideBitmap; //frame indexes (in FoWfullHide) of graphic that should be used to fully hide a tile - std::vector FoWpartialHide; + std::vector> FoWpartialHide; //edge graphics std::unique_ptr egdeAnimation; - std::vector egdeImages;//cache of links to egdeAnimation (for faster access) + 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; diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index cc35567cc..f774baf5f 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -48,18 +48,16 @@ #include "../../lib/NetPacksBase.h" #include "../../lib/StringConstants.h" -CList::CListItem::CListItem(CList * Parent): - CIntObject(LCLICK | RCLICK | HOVER), +CList::CListItem::CListItem(CList * Parent) + : CIntObject(LCLICK | RCLICK | HOVER), parent(Parent), - selection(nullptr) + selection() { + defActions = 255-DISPOSE; } CList::CListItem::~CListItem() { - // select() method in this was already destroyed so we can't safely call method in parent - if (parent->selected == this) - parent->selected = nullptr; } void CList::CListItem::clickRight(tribool down, bool previousState) @@ -70,15 +68,17 @@ void CList::CListItem::clickRight(tribool down, bool previousState) void CList::CListItem::clickLeft(tribool down, bool previousState) { - if (down == true) + if(down == true) { //second click on already selected item - if (parent->selected == this) + if(parent->selected == this->shared_from_this()) + { open(); + } else { //first click - switch selection - parent->select(this); + parent->select(this->shared_from_this()); } } } @@ -93,53 +93,54 @@ void CList::CListItem::hover(bool on) void CList::CListItem::onSelect(bool on) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - vstd::clear_pointer(selection); - if (on) + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + selection.reset(); + if(on) selection = genSelection(); select(on); GH.totalRedraw(); } -CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, - int helpUp, int helpDown, CListBox::CreateFunc create, CListBox::DestroyFunc destroy): - CIntObject(0, position), +CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create) + : CIntObject(0, position), size(Size), selected(nullptr) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - scrollUp = new CButton(Point(0, 0), btnUp, CGI->generaltexth->zelp[helpUp]); - list = new CListBox(create, destroy, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + scrollUp = std::make_shared(Point(0, 0), btnUp, CGI->generaltexth->zelp[helpUp]); + scrollDown = std::make_shared(Point(0, scrollUp->pos.h + 32*size), btnDown, CGI->generaltexth->zelp[helpDown]); + + listBox = std::make_shared(create, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount); //assign callback only after list was created - scrollUp->addCallback(std::bind(&CListBox::moveToPrev, list)); - scrollDown = new CButton(Point(0, scrollUp->pos.h + 32*size), btnDown, CGI->generaltexth->zelp[helpDown], std::bind(&CListBox::moveToNext, list)); + scrollUp->addCallback(std::bind(&CListBox::moveToPrev, listBox)); + scrollDown->addCallback(std::bind(&CListBox::moveToNext, listBox)); - scrollDown->addCallback(std::bind(&CList::update, this)); scrollUp->addCallback(std::bind(&CList::update, this)); + scrollDown->addCallback(std::bind(&CList::update, this)); update(); } void CList::update() { - bool onTop = list->getPos() == 0; - bool onBottom = list->getPos() + size >= list->size(); + bool onTop = listBox->getPos() == 0; + bool onBottom = listBox->getPos() + size >= listBox->size(); scrollUp->block(onTop); scrollDown->block(onBottom); } -void CList::select(CListItem *which) +void CList::select(std::shared_ptr which) { - if (selected == which) + if(selected == which) return; - if (selected) + if(selected) selected->onSelect(false); selected = which; - if (which) + if(which) { which->onSelect(true); onSelect(); @@ -148,28 +149,28 @@ void CList::select(CListItem *which) int CList::getSelectedIndex() { - return list->getIndexOf(selected); + return listBox->getIndexOf(selected); } void CList::selectIndex(int which) { - if (which < 0) + if(which < 0) { - if (selected) + if(selected) select(nullptr); } else { - list->scrollTo(which); + listBox->scrollTo(which); update(); - select(dynamic_cast(list->getItem(which))); + select(std::dynamic_pointer_cast(listBox->getItem(which))); } } void CList::selectNext() { int index = getSelectedIndex() + 1; - if (index >= list->size()) + if(index >= listBox->size()) index = 0; selectIndex(index); } @@ -177,7 +178,7 @@ void CList::selectNext() void CList::selectPrev() { int index = getSelectedIndex(); - if (index <= 0) + if(index <= 0) selectIndex(0); else selectIndex(index-1); @@ -185,23 +186,23 @@ void CList::selectPrev() CHeroList::CEmptyHeroItem::CEmptyHeroItem() { - OBJ_CONSTRUCTION_CAPTURING_ALL; - auto move = new CAnimImage("IMOBIL", 0, 0, 0, 1); - auto img = new CPicture("HPSXXX", move->pos.w + 1); - auto mana = new CAnimImage("IMANA", 0, 0, move->pos.w + img->pos.w + 2, 1 ); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + movement = std::make_shared("IMOBIL", 0, 0, 0, 1); + portrait = std::make_shared("HPSXXX", movement->pos.w + 1); + mana = std::make_shared("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 ); pos.w = mana->pos.w + mana->pos.x - pos.x; - pos.h = std::max(std::max(move->pos.h + 1, mana->pos.h + 1), img->pos.h); + pos.h = std::max(std::max(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h); } -CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero): - CListItem(parent), +CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero) + : CListItem(parent), hero(Hero) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - movement = new CAnimImage("IMOBIL", 0, 0, 0, 1); - portrait = new CAnimImage("PortraitsSmall", hero->portrait, 0, movement->pos.w + 1); - mana = new CAnimImage("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 ); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + movement = std::make_shared("IMOBIL", 0, 0, 0, 1); + portrait = std::make_shared("PortraitsSmall", hero->portrait, 0, movement->pos.w + 1); + mana = std::make_shared("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1); pos.w = mana->pos.w + mana->pos.x - pos.x; pos.h = std::max(std::max(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h); @@ -216,15 +217,15 @@ void CHeroList::CHeroItem::update() redraw(); } -CIntObject * CHeroList::CHeroItem::genSelection() +std::shared_ptr CHeroList::CHeroItem::genSelection() { - return new CPicture("HPSYYY", movement->pos.w + 1); + return std::make_shared("HPSYYY", movement->pos.w + 1); } void CHeroList::CHeroItem::select(bool on) { - if (on && adventureInt->selection != hero) - adventureInt->select(hero); + if(on && adventureInt->selection != hero) + adventureInt->select(hero); } void CHeroList::CHeroItem::open() @@ -242,11 +243,11 @@ std::string CHeroList::CHeroItem::getHoverText() return boost::str(boost::format(CGI->generaltexth->allTexts[15]) % hero->name % hero->type->heroClass->name); } -CIntObject * CHeroList::createHeroItem(size_t index) +std::shared_ptr CHeroList::createHeroItem(size_t index) { if (LOCPLINT->wanderingHeroes.size() > index) - return new CHeroItem(this, LOCPLINT->wanderingHeroes[index]); - return new CEmptyHeroItem(); + return std::make_shared(this, LOCPLINT->wanderingHeroes[index]); + return std::make_shared(); } CHeroList::CHeroList(int size, Point position, std::string btnUp, std::string btnDown): @@ -262,10 +263,10 @@ void CHeroList::select(const CGHeroInstance * hero) void CHeroList::update(const CGHeroInstance * hero) { //this hero is already present, update its status - for (auto & elem : list->getItems()) + for(auto & elem : listBox->getItems()) { - auto item = dynamic_cast(elem); - if (item && item->hero == hero && vstd::contains(LOCPLINT->wanderingHeroes, hero)) + auto item = std::dynamic_pointer_cast(elem); + if(item && item->hero == hero && vstd::contains(LOCPLINT->wanderingHeroes, hero)) { item->update(); return; @@ -273,7 +274,7 @@ void CHeroList::update(const CGHeroInstance * hero) } //simplest solution for now: reset list and restore selection - list->resize(LOCPLINT->wanderingHeroes.size()); + listBox->resize(LOCPLINT->wanderingHeroes.size()); if (adventureInt->selection) { auto hero = dynamic_cast(adventureInt->selection); @@ -283,26 +284,26 @@ void CHeroList::update(const CGHeroInstance * hero) CList::update(); } -CIntObject * CTownList::createTownItem(size_t index) +std::shared_ptr CTownList::createTownItem(size_t index) { if (LOCPLINT->towns.size() > index) - return new CTownItem(this, LOCPLINT->towns[index]); - return new CAnimImage("ITPA", 0); + return std::make_shared(this, LOCPLINT->towns[index]); + return std::make_shared("ITPA", 0); } CTownList::CTownItem::CTownItem(CTownList *parent, const CGTownInstance *Town): CListItem(parent), town(Town) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - picture = new CAnimImage("ITPA", 0); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + picture = std::make_shared("ITPA", 0); pos = picture->pos; update(); } -CIntObject * CTownList::CTownItem::genSelection() +std::shared_ptr CTownList::CTownItem::genSelection() { - return new CAnimImage("ITPA", 1); + return std::make_shared("ITPA", 1); } void CTownList::CTownItem::update() @@ -348,7 +349,7 @@ void CTownList::update(const CGTownInstance *) { //simplest solution for now: reset list and restore selection - list->resize(LOCPLINT->towns.size()); + listBox->resize(LOCPLINT->towns.size()); if (adventureInt->selection) { auto town = dynamic_cast(adventureInt->selection); @@ -475,7 +476,7 @@ CMinimapInstance::~CMinimapInstance() SDL_FreeSurface(minimap); } -void CMinimapInstance::showAll(SDL_Surface *to) +void CMinimapInstance::showAll(SDL_Surface * to) { blitAtLoc(minimap, 0, 0, to); @@ -484,7 +485,7 @@ void CMinimapInstance::showAll(SDL_Surface *to) for(auto & hero : heroes) { int3 position = hero->getPosition(false); - if (position.z == level) + if(position.z == level) { const SDL_Color & color = graphics->playerColors[hero->getOwner().getNum()]; blitTileWithColor(color, position, to, pos.x, pos.y); @@ -531,15 +532,17 @@ std::map > CMinimap::loadColors(std::string return ret; } -CMinimap::CMinimap(const Rect &position): - CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()), - aiShield(nullptr), - minimap(nullptr), +CMinimap::CMinimap(const Rect & position) + : CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()), level(0), colors(loadColors("config/terrains.json")) { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); pos.w = position.w; pos.h = position.h; + + aiShield = std::make_shared("AIShield"); + aiShield->disable(); } int3 CMinimap::translateMousePosition() @@ -567,7 +570,7 @@ void CMinimap::moveAdvMapSelection() void CMinimap::clickLeft(tribool down, bool previousState) { - if (down) + if(down) moveAdvMapSelection(); } @@ -578,7 +581,7 @@ void CMinimap::clickRight(tribool down, bool previousState) void CMinimap::hover(bool on) { - if (on) + if(on) GH.statusbar->setText(CGI->generaltexth->zelp[291].first); else GH.statusbar->clear(); @@ -593,7 +596,7 @@ void CMinimap::mouseMoved(const SDL_MouseMotionEvent & sEvent) void CMinimap::showAll(SDL_Surface * to) { CIntObject::showAll(to); - if (minimap) + if(minimap) { int3 mapSizes = LOCPLINT->cb->getMapSize(); int3 tileCountOnScreen = adventureInt->terrain.tileCountOnScreen(); @@ -608,13 +611,13 @@ void CMinimap::showAll(SDL_Surface * to) ui16(tileCountOnScreen.y * pos.h / mapSizes.y) }; - if (adventureInt->mode == EAdvMapMode::WORLD_VIEW) + if(adventureInt->mode == EAdvMapMode::WORLD_VIEW) { // adjusts radar so that it doesn't go out of map in world view mode (since there's no frame) radar.x = std::min(std::max(pos.x, radar.x), pos.x + pos.w - radar.w); radar.y = std::min(std::max(pos.y, radar.y), pos.y + pos.h - radar.h); - if (radar.x < pos.x && radar.y < pos.y) + if(radar.x < pos.x && radar.y < pos.y) return; // whole map is visible at once, no point in redrawing border } @@ -627,12 +630,11 @@ void CMinimap::showAll(SDL_Surface * to) void CMinimap::update() { - if (aiShield) //AI turn is going on. There is no need to update minimap + if(aiShield->recActions & UPDATE) //AI turn is going on. There is no need to update minimap return; - OBJ_CONSTRUCTION_CAPTURING_ALL; - vstd::clear_pointer(minimap); - minimap = new CMinimapInstance(this, level); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + minimap = std::make_shared(this, level); redraw(); } @@ -644,16 +646,14 @@ void CMinimap::setLevel(int newLevel) void CMinimap::setAIRadar(bool on) { - if (on) + if(on) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - vstd::clear_pointer(minimap); - if (!aiShield) - aiShield = new CPicture("AIShield"); + aiShield->enable(); + minimap.reset(); } else { - vstd::clear_pointer(aiShield); + aiShield->disable(); update(); } // this my happen during AI turn when this interface is inactive @@ -663,123 +663,98 @@ void CMinimap::setAIRadar(bool on) void CMinimap::hideTile(const int3 &pos) { - if (minimap) + if(minimap) minimap->refreshTile(pos); } void CMinimap::showTile(const int3 &pos) { - if (minimap) + if(minimap) minimap->refreshTile(pos); } -CInfoBar::CVisibleInfo::CVisibleInfo(Point position): - CIntObject(0, position), - aiProgress(nullptr) +CInfoBar::CVisibleInfo::CVisibleInfo() + : CIntObject(0, Point(8, 12)) { - } -void CInfoBar::CVisibleInfo::show(SDL_Surface *to) +void CInfoBar::CVisibleInfo::show(SDL_Surface * to) { CIntObject::show(to); for(auto object : forceRefresh) object->showAll(to); } -void CInfoBar::CVisibleInfo::loadHero(const CGHeroInstance * hero) +CInfoBar::EmptyVisibleInfo::EmptyVisibleInfo() { - assert(children.empty()); // visible info should be re-created to change type - - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CPicture("ADSTATHR"); - new CHeroTooltip(Point(0,0), hero); } -void CInfoBar::CVisibleInfo::loadTown(const CGTownInstance *town) +CInfoBar::VisibleHeroInfo::VisibleHeroInfo(const CGHeroInstance * hero) { - assert(children.empty()); // visible info should be re-created to change type - - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CPicture("ADSTATCS"); - new CTownTooltip(Point(0,0), town); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background = std::make_shared("ADSTATHR"); + heroTooltip = std::make_shared(Point(0,0), hero); } -void CInfoBar::CVisibleInfo::playNewDaySound() +CInfoBar::VisibleTownInfo::VisibleTownInfo(const CGTownInstance * town) { - if (LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) != 1) // not first day of the week - CCS->soundh->playSound(soundBase::newDay); - else - if (LOCPLINT->cb->getDate(Date::WEEK) != 1) // not first week in month - CCS->soundh->playSound(soundBase::newWeek); - else - if (LOCPLINT->cb->getDate(Date::MONTH) != 1) // not first month - CCS->soundh->playSound(soundBase::newMonth); - else - CCS->soundh->playSound(soundBase::newDay); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background = std::make_shared("ADSTATCS"); + townTooltip = std::make_shared(Point(0,0), town); } -std::string CInfoBar::CVisibleInfo::getNewDayName() +CInfoBar::VisibleDateInfo::VisibleDateInfo() { - if (LOCPLINT->cb->getDate(Date::DAY) == 1) - return "NEWDAY"; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - if (LOCPLINT->cb->getDate(Date::DAY) != 1) - return "NEWDAY"; - - switch(LOCPLINT->cb->getDate(Date::WEEK)) - { - case 1: return "NEWWEEK1"; - case 2: return "NEWWEEK2"; - case 3: return "NEWWEEK3"; - case 4: return "NEWWEEK4"; - default: assert(0); return ""; - } -} - -void CInfoBar::CVisibleInfo::loadDay() -{ - assert(children.empty()); // visible info should be re-created first to change type - - playNewDaySound(); - - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CShowableAnim(1, 0, getNewDayName(), CShowableAnim::PLAY_ONCE); + animation = std::make_shared(1, 0, getNewDayName(), CShowableAnim::PLAY_ONCE); std::string labelText; - if (LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) == 1 && LOCPLINT->cb->getDate(Date::DAY) != 1) // monday of any week but first - show new week info + if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) == 1 && LOCPLINT->cb->getDate(Date::DAY) != 1) // monday of any week but first - show new week info labelText = CGI->generaltexth->allTexts[63] + " " + boost::lexical_cast(LOCPLINT->cb->getDate(Date::WEEK)); else labelText = CGI->generaltexth->allTexts[64] + " " + boost::lexical_cast(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK)); - forceRefresh.push_back(new CLabel(95, 31, FONT_MEDIUM, CENTER, Colors::WHITE, labelText)); + label = std::make_shared(95, 31, FONT_MEDIUM, CENTER, Colors::WHITE, labelText); + + forceRefresh.push_back(label); } -void CInfoBar::CVisibleInfo::loadEnemyTurn(PlayerColor player) +std::string CInfoBar::VisibleDateInfo::getNewDayName() { - assert(children.empty()); // visible info should be re-created to change type + if(LOCPLINT->cb->getDate(Date::DAY) == 1) + return "NEWDAY"; - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CPicture("ADSTATNX"); - new CAnimImage("CREST58", player.getNum(), 0, 20, 51); - new CShowableAnim(99, 51, "HOURSAND"); + if(LOCPLINT->cb->getDate(Date::DAY) != 1) + return "NEWDAY"; - // FIXME: currently there is no way to get progress from VCAI - // if this will change at some point switch this ifdef to enable correct code -#if 0 - //prepare hourglass for updating AI turn - aiProgress = new CAnimImage("HOURGLAS", 0, 0, 99, 51); - forceRefresh.push_back(aiProgress); -#else - //create hourglass that will be always animated ignoring AI status - new CShowableAnim(99, 51, "HOURGLAS", CShowableAnim::PLAY_ONCE, 40); -#endif + switch(LOCPLINT->cb->getDate(Date::WEEK)) + { + case 1: + return "NEWWEEK1"; + case 2: + return "NEWWEEK2"; + case 3: + return "NEWWEEK3"; + case 4: + return "NEWWEEK4"; + default: + return ""; + } } -void CInfoBar::CVisibleInfo::loadGameStatus() +CInfoBar::VisibleEnemyTurnInfo::VisibleEnemyTurnInfo(PlayerColor player) { - assert(children.empty()); // visible info should be re-created to change type + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background = std::make_shared("ADSTATNX"); + banner = std::make_shared("CREST58", player.getNum(), 0, 20, 51); + sand = std::make_shared(99, 51, "HOURSAND"); + glass = std::make_shared(99, 51, "HOURGLAS", CShowableAnim::PLAY_ONCE, 40); +} +CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo() +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); //get amount of halls of each level std::vector halls(4, 0); for(auto town : LOCPLINT->towns) @@ -797,83 +772,84 @@ void CInfoBar::CVisibleInfo::loadGameStatus() { if(LOCPLINT->cb->getPlayerStatus(PlayerColor(i), false) == EPlayerStatus::INGAME) { - if (LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, PlayerColor(i)) != PlayerRelations::ENEMIES) + if(LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, PlayerColor(i)) != PlayerRelations::ENEMIES) allies.push_back(PlayerColor(i)); else enemies.push_back(PlayerColor(i)); } } - //generate component - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CPicture("ADSTATIN"); - auto allyLabel = new CLabel(10, 106, FONT_SMALL, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[390] + ":"); - auto enemyLabel = new CLabel(10, 136, FONT_SMALL, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[391] + ":"); + //generate widgets + background = std::make_shared("ADSTATIN"); + allyLabel = std::make_shared(10, 106, FONT_SMALL, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[390] + ":"); + enemyLabel = std::make_shared(10, 136, FONT_SMALL, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[391] + ":"); int posx = allyLabel->pos.w + allyLabel->pos.x - pos.x + 4; for(PlayerColor & player : allies) { - auto image = new CAnimImage("ITGFLAGS", player.getNum(), 0, posx, 102); + auto image = std::make_shared("ITGFLAGS", player.getNum(), 0, posx, 102); posx += image->pos.w; + flags.push_back(image); } posx = enemyLabel->pos.w + enemyLabel->pos.x - pos.x + 4; for(PlayerColor & player : enemies) { - auto image = new CAnimImage("ITGFLAGS", player.getNum(), 0, posx, 132); + auto image = std::make_shared("ITGFLAGS", player.getNum(), 0, posx, 132); posx += image->pos.w; + flags.push_back(image); } - for (size_t i=0; i(halls[i])); + hallIcons.push_back(std::make_shared("itmtl", i, 0, 6 + 42 * i , 11)); + if(halls[i]) + hallLabels.push_back(std::make_shared( 26 + 42 * i, 64, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast(halls[i]))); } } -void CInfoBar::CVisibleInfo::loadComponent(const Component & compToDisplay, std::string message) +CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const Component & compToDisplay, std::string message) { - assert(children.empty()); // visible info should be re-created to change type + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - OBJ_CONSTRUCTION_CAPTURING_ALL; + background = std::make_shared("ADSTATOT", 1); - new CPicture("ADSTATOT", 1); - - auto comp = new CComponent(compToDisplay); + comp = std::make_shared(compToDisplay); comp->moveTo(Point(pos.x+47, pos.y+50)); - new CTextBox(message, Rect(10, 4, 160, 50), 0, FONT_SMALL, CENTER, Colors::WHITE); + text = std::make_shared(message, Rect(10, 4, 160, 50), 0, FONT_SMALL, CENTER, Colors::WHITE); } -void CInfoBar::CVisibleInfo::updateEnemyTurn(double progress) +void CInfoBar::playNewDaySound() { - if (aiProgress) - aiProgress->setFrame((aiProgress->size() - 1) * progress); + if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) != 1) // not first day of the week + CCS->soundh->playSound(soundBase::newDay); + else if(LOCPLINT->cb->getDate(Date::WEEK) != 1) // not first week in month + CCS->soundh->playSound(soundBase::newWeek); + else if(LOCPLINT->cb->getDate(Date::MONTH) != 1) // not first month + CCS->soundh->playSound(soundBase::newMonth); + else + CCS->soundh->playSound(soundBase::newDay); } -void CInfoBar::reset(EState newState = EMPTY) +void CInfoBar::reset() { - OBJ_CONSTRUCTION_CAPTURING_ALL; - - vstd::clear_pointer(visibleInfo); - currentObject = nullptr; - state = newState; - visibleInfo = new CVisibleInfo(Point(8, 12)); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + state = EMPTY; + visibleInfo = std::make_shared(); } void CInfoBar::showSelection() { - if (adventureInt->selection) + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + if(adventureInt->selection) { - auto hero = dynamic_cast(adventureInt->selection); - if (hero) + if(auto hero = dynamic_cast(adventureInt->selection)) { showHeroSelection(hero); return; } - auto town = dynamic_cast(adventureInt->selection); - if (town) + else if(auto town = dynamic_cast(adventureInt->selection)) { showTownSelection(town); return; @@ -891,11 +867,11 @@ void CInfoBar::tick() void CInfoBar::clickLeft(tribool down, bool previousState) { - if (down) + if(down) { - if (state == HERO || state == TOWN) + if(state == HERO || state == TOWN) showGameStatus(); - else if (state == GAME) + else if(state == GAME) showDate(); else showSelection(); @@ -909,83 +885,96 @@ void CInfoBar::clickRight(tribool down, bool previousState) void CInfoBar::hover(bool on) { - if (on) + if(on) GH.statusbar->setText(CGI->generaltexth->zelp[292].first); else GH.statusbar->clear(); } -CInfoBar::CInfoBar(const Rect &position): - CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()), - visibleInfo(nullptr), - state(EMPTY), - currentObject(nullptr) +CInfoBar::CInfoBar(const Rect & position) + : CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()), + state(EMPTY) { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); pos.w = position.w; pos.h = position.h; - //FIXME: enable some mode? Should be done by advMap::select() when game starts but just in case? + reset(); } void CInfoBar::showDate() { - reset(DATE); - visibleInfo->loadDay(); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + playNewDaySound(); + state = DATE; + visibleInfo = std::make_shared(); setTimer(3000); redraw(); } void CInfoBar::showComponent(const Component & comp, std::string message) { - reset(COMPONENT); - visibleInfo->loadComponent(comp, message); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + state = COMPONENT; + visibleInfo = std::make_shared(comp, message); setTimer(3000); redraw(); } void CInfoBar::startEnemyTurn(PlayerColor color) { - reset(AITURN); - visibleInfo->loadEnemyTurn(color); - redraw(); -} - -void CInfoBar::updateEnemyTurn(double progress) -{ - assert(state == AITURN); - visibleInfo->updateEnemyTurn(progress); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + state = AITURN; + visibleInfo = std::make_shared(color); redraw(); } void CInfoBar::showHeroSelection(const CGHeroInstance * hero) { - if (!hero) - return; - - reset(HERO); - currentObject = hero; - visibleInfo->loadHero(hero); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + if(!hero) + { + reset(); + } + else + { + state = HERO; + visibleInfo = std::make_shared(hero); + } redraw(); } void CInfoBar::showTownSelection(const CGTownInstance * town) { - if (!town) - return; - - reset(TOWN); - currentObject = town; - visibleInfo->loadTown(town); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + if(!town) + { + reset(); + } + else + { + state = TOWN; + visibleInfo = std::make_shared(town); + } redraw(); } void CInfoBar::showGameStatus() { - reset(GAME); - visibleInfo->loadGameStatus(); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + state = GAME; + visibleInfo = std::make_shared(); setTimer(3000); redraw(); } +CInGameConsole::CInGameConsole() + : CIntObject(KEYBOARD | TEXTINPUT), + prevEntDisp(-1), + defaultTimeout(10000), + maxDisplayedTexts(10) +{ +} + void CInGameConsole::show(SDL_Surface * to) { int number = 0; @@ -1207,11 +1196,6 @@ void CInGameConsole::refreshEnteredText() } } -CInGameConsole::CInGameConsole() : prevEntDisp(-1), defaultTimeout(10000), maxDisplayedTexts(10) -{ - addUsedEvents(KEYBOARD | TEXTINPUT); -} - CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position) : CIntObject(), background(bg) @@ -1233,32 +1217,34 @@ CAdvMapPanel::~CAdvMapPanel() SDL_FreeSurface(background); } -void CAdvMapPanel::addChildColorableButton(CButton * btn) +void CAdvMapPanel::addChildColorableButton(std::shared_ptr button) { - buttons.push_back(btn); - addChildToPanel(btn, ACTIVATE | DEACTIVATE); + colorableButtons.push_back(button); + addChildToPanel(button, ACTIVATE | DEACTIVATE); } void CAdvMapPanel::setPlayerColor(const PlayerColor & clr) { - for (auto &btn : buttons) + for(auto & button : colorableButtons) { - btn->setPlayerColor(clr); + button->setPlayerColor(clr); } } void CAdvMapPanel::showAll(SDL_Surface * to) { - if (background) + if(background) blitAt(background, pos.x, pos.y, to); CIntObject::showAll(to); } -void CAdvMapPanel::addChildToPanel(CIntObject * obj, ui8 actions) +void CAdvMapPanel::addChildToPanel(std::shared_ptr obj, ui8 actions) { + otherObjects.push_back(obj); obj->recActions |= actions | SHOWALL; - addChild(obj, false); + obj->recActions &= ~DISPOSE; + addChild(obj.get(), false); } CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color) @@ -1280,7 +1266,7 @@ CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel() SDL_FreeSurface(tmpBackgroundFiller); } -void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, int indexOffset) +void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOffset) { assert(iconsData.size() == currentIcons.size()); @@ -1290,9 +1276,9 @@ void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, int indexOffs currentIcons[idx]->setFrame(data.first + indexOffset); } - if (fillerHeight > 0) + if(fillerHeight > 0) { - if (tmpBackgroundFiller) + if(tmpBackgroundFiller) SDL_FreeSurface(tmpBackgroundFiller); tmpBackgroundFiller = CMessage::drawDialogBox(pos.w, fillerHeight, color); } @@ -1300,9 +1286,9 @@ void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, int indexOffs void CAdvMapWorldViewPanel::addChildIcon(std::pair data, int indexOffset) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); iconsData.push_back(data); - currentIcons.push_back(new CAnimImage(icons, data.first + indexOffset, 0, data.second.x, data.second.y)); + currentIcons.push_back(std::make_shared(icons, data.first + indexOffset, 0, data.second.x, data.second.y)); } void CAdvMapWorldViewPanel::showAll(SDL_Surface * to) diff --git a/client/widgets/AdventureMapClasses.h b/client/widgets/AdventureMapClasses.h index 8daf2faa8..3cacc3995 100644 --- a/client/widgets/AdventureMapClasses.h +++ b/client/widgets/AdventureMapClasses.h @@ -22,18 +22,22 @@ class CGHeroInstance; class CGTownInstance; class CButton; struct Component; +class CComponent; struct InfoAboutArmy; struct InfoAboutHero; struct InfoAboutTown; +class CHeroTooltip; +class CTownTooltip; +class CTextBox; /// Base UI Element for hero\town lists class CList : public CIntObject { protected: - class CListItem : public CIntObject + class CListItem : public CIntObject, public std::enable_shared_from_this { CList * parent; - CIntObject * selection; + std::shared_ptr selection; public: CListItem(CList * parent); ~CListItem(); @@ -44,7 +48,7 @@ protected: void onSelect(bool on); /// create object with selection rectangle - virtual CIntObject * genSelection()=0; + virtual std::shared_ptr genSelection()=0; /// reaction on item selection (e.g. enable selection border) /// NOTE: item may be deleted in selected state virtual void select(bool on)=0; @@ -56,7 +60,7 @@ protected: virtual std::string getHoverText()=0; }; - CListBox * list; + std::shared_ptr listBox; const size_t size; /** @@ -71,22 +75,20 @@ protected: * @param create - function for creating items in listbox * @param destroy - function for deleting items in listbox */ - CList(int size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, - CListBox::CreateFunc create, CListBox::DestroyFunc destroy = CListBox::DestroyFunc()); + CList(int size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create); //for selection\deselection - CListItem *selected; - void select(CListItem * which); + std::shared_ptr selected; + void select(std::shared_ptr which); friend class CListItem; + std::shared_ptr scrollUp; + std::shared_ptr scrollDown; + /// should be called when list is invalidated void update(); public: - - CButton * scrollUp; - CButton * scrollDown; - /// functions that will be called when selection changes CFunctionList onSelect; @@ -105,21 +107,24 @@ class CHeroList : public CList /// Empty hero item used as placeholder for unused entries in list class CEmptyHeroItem : public CIntObject { + std::shared_ptr movement; + std::shared_ptr mana; + std::shared_ptr portrait; public: CEmptyHeroItem(); }; class CHeroItem : public CListItem { - CAnimImage * movement; - CAnimImage * mana; - CAnimImage * portrait; + std::shared_ptr movement; + std::shared_ptr mana; + std::shared_ptr portrait; public: const CGHeroInstance * const hero; - CHeroItem(CHeroList *parent, const CGHeroInstance * hero); + CHeroItem(CHeroList * parent, const CGHeroInstance * hero); - CIntObject * genSelection() override; + std::shared_ptr genSelection() override; void update(); void select(bool on) override; void open() override; @@ -127,7 +132,7 @@ class CHeroList : public CList std::string getHoverText() override; }; - CIntObject * createHeroItem(size_t index); + std::shared_ptr createHeroItem(size_t index); public: /** * @brief CHeroList @@ -147,13 +152,13 @@ class CTownList : public CList { class CTownItem : public CListItem { - CAnimImage * picture; + std::shared_ptr picture; public: const CGTownInstance * const town; CTownItem(CTownList *parent, const CGTownInstance * town); - CIntObject * genSelection() override; + std::shared_ptr genSelection() override; void update(); void select(bool on) override; void open() override; @@ -161,7 +166,7 @@ class CTownList : public CList std::string getHoverText() override; }; - CIntObject * createTownItem(size_t index); + std::shared_ptr createTownItem(size_t index); public: /** * @brief CTownList @@ -180,14 +185,14 @@ class CMinimap; class CMinimapInstance : public CIntObject { - CMinimap *parent; + CMinimap * parent; SDL_Surface * minimap; int level; //get color of selected tile on minimap const SDL_Color & getTileColor(const int3 & pos); - void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface *to, int x, int y); + void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface * to, int x, int y); //draw minimap already scaled. //result is not antialiased. Will result in "missing" pixels on huge maps (>144) @@ -196,19 +201,17 @@ public: CMinimapInstance(CMinimap * parent, int level); ~CMinimapInstance(); - void showAll(SDL_Surface *to) override; - void tileToPixels (const int3 &tile, int &x, int &y,int toX = 0, int toY = 0); - - void refreshTile(const int3 &pos); + void showAll(SDL_Surface * to) override; + void tileToPixels (const int3 & tile, int & x, int & y, int toX = 0, int toY = 0); + void refreshTile(const int3 & pos); }; /// Minimap which is displayed at the right upper corner of adventure map class CMinimap : public CIntObject { protected: - - CPicture *aiShield; //the graphic displayed during AI turn - CMinimapInstance * minimap; + std::shared_ptr aiShield; //the graphic displayed during AI turn + std::shared_ptr minimap; int level; //to initialize colors @@ -245,30 +248,73 @@ class CInfoBar : public CIntObject //all visible information located in one object - for ease of replacing class CVisibleInfo : public CIntObject { - //list of objects that must be redrawed on each frame on a top of animation - std::list forceRefresh; + public: + void show(SDL_Surface * to) override; - //the only part of gui we need to know about for updating - AI progress - CAnimImage *aiProgress; + protected: + std::shared_ptr background; + std::list> forceRefresh; + + CVisibleInfo(); + }; + + class EmptyVisibleInfo : public CVisibleInfo + { + public: + EmptyVisibleInfo(); + }; + + class VisibleHeroInfo : public CVisibleInfo + { + std::shared_ptr heroTooltip; + public: + VisibleHeroInfo(const CGHeroInstance * hero); + }; + + class VisibleTownInfo : public CVisibleInfo + { + std::shared_ptr townTooltip; + public: + VisibleTownInfo(const CGTownInstance * town); + }; + + class VisibleDateInfo : public CVisibleInfo + { + std::shared_ptr animation; + std::shared_ptr label; std::string getNewDayName(); - void playNewDaySound(); - public: - CVisibleInfo(Point position); + VisibleDateInfo(); + }; - void show(SDL_Surface *to) override; + class VisibleEnemyTurnInfo : public CVisibleInfo + { + std::shared_ptr banner; + std::shared_ptr glass; + std::shared_ptr sand; + public: + VisibleEnemyTurnInfo(PlayerColor player); + }; - //functions that must be called only once - void loadHero(const CGHeroInstance * hero); - void loadTown(const CGTownInstance * town); - void loadDay(); - void loadEnemyTurn(PlayerColor player); - void loadGameStatus(); - void loadComponent(const Component &comp, std::string message); + class VisibleGameStatusInfo : public CVisibleInfo + { + std::shared_ptr allyLabel; + std::shared_ptr enemyLabel; - //can be called multiple times - void updateEnemyTurn(double progress); + std::vector> flags; + std::vector> hallIcons; + std::vector> hallLabels; + public: + VisibleGameStatusInfo(); + }; + + class VisibleComponentInfo : public CVisibleInfo + { + std::shared_ptr comp; + std::shared_ptr text; + public: + VisibleComponentInfo(const Component & compToDisplay, std::string message); }; enum EState @@ -276,13 +322,11 @@ class CInfoBar : public CIntObject EMPTY, HERO, TOWN, DATE, GAME, AITURN, COMPONENT }; - CVisibleInfo * visibleInfo; + std::shared_ptr visibleInfo; EState state; - //currently displayed object. May be null if state is not hero or town - const CGObjectInstance * currentObject; //removes all information about current state, deactivates timer (if any) - void reset(EState newState); + void reset(); void tick() override; @@ -290,6 +334,7 @@ class CInfoBar : public CIntObject void clickRight(tribool down, bool previousState) override; void hover(bool on) override; + void playNewDaySound(); public: CInfoBar(const Rect & pos); @@ -301,9 +346,6 @@ public: /// print enemy turn progress void startEnemyTurn(PlayerColor color); - /// updates enemy turn. - /// NOTE: currently DISABLED. Check comments in CInfoBar::CVisibleInfo::loadEnemyTurn() - void updateEnemyTurn(double progress); /// reset to default view - selected object void showSelection(); @@ -319,16 +361,16 @@ public: /// simple panel that contains other displayable elements; used to separate groups of controls class CAdvMapPanel : public CIntObject { - /// ptrs to child-buttons that can be recolored with setPlayerColor() - std::vector buttons; + std::vector> colorableButtons; + std::vector> otherObjects; /// the surface passed to this obj will be freed in dtor SDL_Surface * background; public: CAdvMapPanel(SDL_Surface * bg, Point position); virtual ~CAdvMapPanel(); - void addChildToPanel(CIntObject * obj, ui8 actions = 0); - void addChildColorableButton(CButton * btn); + void addChildToPanel(std::shared_ptr obj, ui8 actions = 0); + void addChildColorableButton(std::shared_ptr button); /// recolors all buttons to given player color void setPlayerColor(const PlayerColor & clr); @@ -341,7 +383,7 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel /// data that allows reconstruction of panel info icons std::vector> iconsData; /// ptrs to child-pictures constructed from iconsData - std::vector currentIcons; + std::vector> currentIcons; /// temporary surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod) SDL_Surface * tmpBackgroundFiller; int fillerHeight; @@ -352,7 +394,7 @@ public: void addChildIcon(std::pair data, int indexOffset); /// recreates all pictures from given def to recolor them according to current player color - void recolorIcons(const PlayerColor &color, int indexOffset); + void recolorIcons(const PlayerColor & color, int indexOffset); void showAll(SDL_Surface * to) override; }; diff --git a/client/widgets/Buttons.cpp b/client/widgets/Buttons.cpp index 1c32f2761..f605866fd 100644 --- a/client/widgets/Buttons.cpp +++ b/client/widgets/Buttons.cpp @@ -74,18 +74,17 @@ void CButton::addCallback(std::function callback) this->callback += callback; } -void CButton::addTextOverlay( const std::string &Text, EFonts font, SDL_Color color) +void CButton::addTextOverlay(const std::string & Text, EFonts font, SDL_Color color) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - addOverlay(new CLabel(pos.w/2, pos.h/2, font, CENTER, color, Text)); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + addOverlay(std::make_shared(pos.w/2, pos.h/2, font, CENTER, color, Text)); update(); } -void CButton::addOverlay(CIntObject *newOverlay) +void CButton::addOverlay(std::shared_ptr newOverlay) { - delete overlay; overlay = newOverlay; - addChild(newOverlay); + addChild(newOverlay.get()); overlay->moveTo(overlay->pos.centerIn(pos).topLeft()); update(); } @@ -235,6 +234,7 @@ CButton::CButton(Point position, const std::string &defName, const std::pair anim, bool playerColoredButton, int animFlags) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); - image = new CAnimImage(anim, getState(), 0, 0, 0, animFlags); + image = std::make_shared(anim, getState(), 0, 0, 0, animFlags); if (playerColoredButton) image->playerColored(LOCPLINT->playerID); pos = image->pos; @@ -317,9 +315,7 @@ CToggleBase::CToggleBase(CFunctionList callback): { } -CToggleBase::~CToggleBase() -{ -} +CToggleBase::~CToggleBase() = default; void CToggleBase::doSelect(bool on) { @@ -399,25 +395,30 @@ void CToggleGroup::addCallback(std::function callback) onChange += callback; } -void CToggleGroup::addToggle(int identifier, CToggleBase* bt) +void CToggleGroup::resetCallback() { - if (auto intObj = dynamic_cast(bt)) // hack-ish workagound to avoid diamond problem with inheritance + onChange.clear(); +} + +void CToggleGroup::addToggle(int identifier, std::shared_ptr button) +{ + if(auto intObj = std::dynamic_pointer_cast(button)) // hack-ish workagound to avoid diamond problem with inheritance { - if (intObj->parent) - intObj->parent->removeChild(intObj); - addChild(intObj); + addChild(intObj.get()); } - bt->addCallback([=] (bool on) { if (on) selectionChanged(identifier);}); - bt->allowDeselection = false; + button->addCallback([=] (bool on) { if (on) selectionChanged(identifier);}); + button->allowDeselection = false; - assert(buttons[identifier] == nullptr); - buttons[identifier] = bt; + if(buttons.count(identifier)>0) + logAnim->error("Duplicated toggle button id %d", identifier); + buttons[identifier] = button; } CToggleGroup::CToggleGroup(const CFunctionList &OnChange) -: onChange(OnChange), selectedID(-2) -{} + : onChange(OnChange), selectedID(-2) +{ +} void CToggleGroup::setSelected(int id) { @@ -443,15 +444,13 @@ void CToggleGroup::selectionChanged(int to) parent->redraw(); } -CVolumeSlider::CVolumeSlider(const Point &position, const std::string &defName, const int value, - const std::pair * const help) : +CVolumeSlider::CVolumeSlider(const Point & position, const std::string & defName, const int value, const std::pair * const help) + : CIntObject(LCLICK | RCLICK | WHEEL), value(value), helpHandlers(help) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - animImage = new CAnimImage(std::make_shared(defName), 0, 0, position.x, position.y), - assert(!defName.empty()); - addUsedEvents(LCLICK | RCLICK | WHEEL); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + animImage = std::make_shared(std::make_shared(defName), 0, 0, position.x, position.y), pos.x += position.x; pos.y += position.y; pos.w = (animImage->pos.w + 1) * animImage->size(); @@ -658,25 +657,20 @@ void CSlider::clickLeft(tribool down, bool previousState) removeUsedEvents(MOVE); } -CSlider::~CSlider() +CSlider::CSlider(Point position, int totalw, std::function Moved, int Capacity, int Amount, int Value, bool Horizontal, CSlider::EStyle style) + : CIntObject(LCLICK | RCLICK | WHEEL), + capacity(Capacity), + horizontal(Horizontal), + amount(Amount), + value(Value), + scrollStep(1), + moved(Moved) { - -} - -CSlider::CSlider(Point position, int totalw, std::function Moved, int Capacity, int Amount, int Value, bool Horizontal, CSlider::EStyle style): - capacity(Capacity), - horizontal(Horizontal), - amount(Amount), - value(Value), - scrollStep(1), - moved(Moved) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); setAmount(amount); vstd::amax(value, 0); vstd::amin(value, positions); - addUsedEvents(LCLICK | KEYBOARD | WHEEL); strongInterest = true; pos.x += position.x; @@ -684,12 +678,12 @@ CSlider::CSlider(Point position, int totalw, std::function Moved, int if(style == BROWN) { - std::string name = horizontal?"IGPCRDIV.DEF":"OVBUTN2.DEF"; + std::string name = horizontal ? "IGPCRDIV.DEF" : "OVBUTN2.DEF"; //NOTE: this images do not have "blocked" frames. They should be implemented somehow (e.g. palette transform or something...) - left = new CButton(Point(), name, CButton::tooltip()); - right = new CButton(Point(), name, CButton::tooltip()); - slider = new CButton(Point(), name, CButton::tooltip()); + left = std::make_shared(Point(), name, CButton::tooltip()); + right = std::make_shared(Point(), name, CButton::tooltip()); + slider = std::make_shared(Point(), name, CButton::tooltip()); left->setImageOrder(0, 1, 1, 1); right->setImageOrder(2, 3, 3, 3); @@ -697,9 +691,9 @@ CSlider::CSlider(Point position, int totalw, std::function Moved, int } else { - left = new CButton(Point(), horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF", CButton::tooltip()); - right = new CButton(Point(), horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF", CButton::tooltip()); - slider = new CButton(Point(), "SCNRBSL.DEF", CButton::tooltip()); + left = std::make_shared(Point(), horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF", CButton::tooltip()); + right = std::make_shared(Point(), horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF", CButton::tooltip()); + slider = std::make_shared(Point(), "SCNRBSL.DEF", CButton::tooltip()); } slider->actOnDown = true; slider->soundDisabled = true; @@ -729,6 +723,8 @@ CSlider::CSlider(Point position, int totalw, std::function Moved, int updateSliderPos(); } +CSlider::~CSlider() = default; + void CSlider::block( bool on ) { left->block(on); diff --git a/client/widgets/Buttons.h b/client/widgets/Buttons.h index e390fdb00..fe875c8e9 100644 --- a/client/widgets/Buttons.h +++ b/client/widgets/Buttons.h @@ -50,8 +50,8 @@ private: std::array, 4> stateToBorderColor; // mapping of button state to border color std::string helpBox; //for right-click help - CAnimImage * image; //image for this button - CIntObject * overlay;//object-overlay, can be null + std::shared_ptr image; //image for this button + std::shared_ptr overlay;//object-overlay, can be null bool animateLonelyFrame = false; protected: void onButtonClicked(); // calls callback @@ -80,8 +80,8 @@ public: void addCallback(std::function callback); /// adds overlay on top of button image. Only one overlay can be active at once - void addOverlay(CIntObject * newOverlay); - void addTextOverlay(const std::string &Text, EFonts font, SDL_Color color = Colors::WHITE); + void addOverlay(std::shared_ptr newOverlay); + void addTextOverlay(const std::string & Text, EFonts font, SDL_Color color = Colors::WHITE); void addImage(std::string filename); void addHoverText(ButtonState state, std::string text); @@ -95,7 +95,7 @@ public: bool isHighlighted(); /// Constructor - CButton(Point position, const std::string &defName, const std::pair &help, + CButton(Point position, const std::string & defName, const std::pair & help, CFunctionList Callback = 0, int key=0, bool playerColoredButton = false ); /// Appearance modifiers @@ -162,14 +162,15 @@ class CToggleGroup : public CIntObject int selectedID; void selectionChanged(int to); public: - std::map buttons; + std::map> buttons; CToggleGroup(const CFunctionList & OnChange); void addCallback(std::function callback); + void resetCallback(); /// add one toggle/button into group - void addToggle(int index, CToggleBase * button); + void addToggle(int index, std::shared_ptr button); /// Changes selection to specific value. Will select toggle with this ID, if present void setSelected(int id); }; @@ -179,7 +180,7 @@ class CVolumeSlider : public CIntObject { int value; CFunctionList onChange; - CAnimImage * animImage; + std::shared_ptr animImage; const std::pair * const helpHandlers; void setVolume(const int v); public: @@ -188,7 +189,7 @@ public: /// @param defName name of def animation for slider /// @param value initial value for volume /// @param help pointer to first helptext of slider - CVolumeSlider(const Point &position, const std::string &defName, const int value, + CVolumeSlider(const Point & position, const std::string & defName, const int value, const std::pair * const help); void moveTo(int id); @@ -203,7 +204,11 @@ public: /// A typical slider which can be orientated horizontally/vertically. class CSlider : public CIntObject { - CButton *left, *right, *slider; //if vertical then left=up + //if vertical then left=up + std::shared_ptr left; + std::shared_ptr right; + std::shared_ptr slider; + int capacity;//how many elements can be active at same time (e.g. hero list = 5) int positions; //number of highest position (0 if there is only one) bool horizontal; @@ -216,7 +221,8 @@ class CSlider : public CIntObject void sliderClicked(); public: - enum EStyle { + enum EStyle + { BROWN, BLUE }; diff --git a/client/widgets/CArtifactHolder.cpp b/client/widgets/CArtifactHolder.cpp index 5c551b56c..65b882f38 100644 --- a/client/widgets/CArtifactHolder.cpp +++ b/client/widgets/CArtifactHolder.cpp @@ -30,27 +30,31 @@ #include "../../lib/mapObjects/CGHeroInstance.h" -CHeroArtPlace::CHeroArtPlace(Point position, const CArtifactInstance * Art): CArtPlace(position, Art), - locked(false), picked(false), marked(false), ourOwner(nullptr) +CHeroArtPlace::CHeroArtPlace(Point position, const CArtifactInstance * Art) + : CArtPlace(position, Art), + locked(false), + picked(false), + marked(false), + ourOwner(nullptr) { createImage(); } void CHeroArtPlace::createImage() { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - int imageIndex = 0; - if (ourArt) + si32 imageIndex = 0; + if(ourArt) imageIndex = ourArt->artType->iconIndex; - if (locked) + if(locked) imageIndex = ArtifactID::ART_LOCK; - image = new CAnimImage("artifact", imageIndex); - if (!ourArt) + image = std::make_shared("artifact", imageIndex); + if(!ourArt) image->disable(); - selection = new CAnimImage("artifact", ArtifactID::ART_SELECTION); + selection = std::make_shared("artifact", ArtifactID::ART_SELECTION); selection->disable(); } @@ -137,7 +141,7 @@ void CHeroArtPlace::clickLeft(tribool down, bool previousState) { if(ourArt->artType->id == ArtifactID::CATAPULT) //catapult cannot be highlighted { - std::vector catapult(1, new CComponent(CComponent::artifact, 3, 0)); + std::vector> catapult(1, std::make_shared(CComponent::artifact, 3, 0)); LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[312], catapult); //The Catapult must be equipped. return; } @@ -284,8 +288,8 @@ void CHeroArtPlace::select () { for(int i = 0; i < GameConstants::BACKPACK_START; i++) { - CHeroArtPlace * ap = ourOwner->getArtPlace(i); - if(nullptr != ap)//getArtPlace may return null + auto ap = ourOwner->getArtPlace(i); + if(ap)//getArtPlace may return null ap->pickSlot(ourArt->isPart(ap->ourArt)); } } @@ -492,7 +496,7 @@ void CArtifactsOfHero::scrollBackpack(int dir) { if(elem->marked) { - highlightModeCallback(elem); + highlightModeCallback(elem.get()); break; } } @@ -504,7 +508,6 @@ void CArtifactsOfHero::scrollBackpack(int dir) rightArtRoll->block(!scrollingPossible); safeRedraw(); - } /** @@ -538,9 +541,10 @@ void CArtifactsOfHero::unmarkSlots(bool withRedraw) void CArtifactsOfHero::unmarkLocalSlots(bool withRedraw) { - for(auto p : artWorn) + for(auto & p : artWorn) p.second->selectSlot(false); - for(CHeroArtPlace *place : backpack) + + for(auto & place : backpack) place->selectSlot(false); if(withRedraw) @@ -550,7 +554,7 @@ void CArtifactsOfHero::unmarkLocalSlots(bool withRedraw) /** * Assigns an artifacts to an artifact place depending on it's new slot ID. */ -void CArtifactsOfHero::setSlotData(CHeroArtPlace* artPlace, ArtifactPosition slotID) +void CArtifactsOfHero::setSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID) { if(!artPlace && slotID >= GameConstants::BACKPACK_START) //spurious call from artifactMoved in attempt to update hidden backpack slot { @@ -572,21 +576,25 @@ void CArtifactsOfHero::setSlotData(CHeroArtPlace* artPlace, ArtifactPosition slo /** * Makes given artifact slot appear as empty with a certain slot ID. */ -void CArtifactsOfHero::eraseSlotData (CHeroArtPlace* artPlace, ArtifactPosition slotID) +void CArtifactsOfHero::eraseSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID) { artPlace->pickSlot(false); artPlace->slotID = slotID; artPlace->setArtifact(nullptr); } -CArtifactsOfHero::CArtifactsOfHero(std::map ArtWorn, std::vector Backpack, - CButton *leftScroll, CButton *rightScroll, bool createCommonPart): - - curHero(nullptr), - artWorn(ArtWorn), backpack(Backpack), - backpackPos(0), commonInfo(nullptr), updateState(false), - leftArtRoll(leftScroll), rightArtRoll(rightScroll), - allowedAssembling(true), highlightModeCallback(nullptr) +CArtifactsOfHero::CArtifactsOfHero(ArtPlaceMap ArtWorn, std::vector Backpack, + std::shared_ptr leftScroll, std::shared_ptr rightScroll, bool createCommonPart) + : curHero(nullptr), + artWorn(ArtWorn), + backpack(Backpack), + backpackPos(0), + commonInfo(nullptr), + updateState(false), + leftArtRoll(leftScroll), + rightArtRoll(rightScroll), + allowedAssembling(true), + highlightModeCallback(nullptr) { if(createCommonPart) { @@ -595,7 +603,7 @@ CArtifactsOfHero::CArtifactsOfHero(std::map A } // Init slots for worn artifacts. - for (auto p : artWorn) + for(auto p : artWorn) { p.second->ourOwner = this; eraseSlotData(p.second, p.first); @@ -608,12 +616,17 @@ CArtifactsOfHero::CArtifactsOfHero(std::map A eraseSlotData(backpack[s], ArtifactPosition(GameConstants::BACKPACK_START + s)); } - leftArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack,this,-1)); - rightArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack,this,+1)); + leftArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack, this,-1)); + rightArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack, this,+1)); } -CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart) - : curHero(nullptr), backpackPos(0), commonInfo(nullptr), updateState(false), allowedAssembling(true), highlightModeCallback(nullptr) +CArtifactsOfHero::CArtifactsOfHero(const Point & position, bool createCommonPart) + : curHero(nullptr), + backpackPos(0), + commonInfo(nullptr), + updateState(false), + allowedAssembling(true), + highlightModeCallback(nullptr) { if(createCommonPart) { @@ -621,7 +634,7 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart) commonInfo->participants.insert(this); } - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); pos += position; std::vector slotPos = @@ -636,9 +649,9 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart) }; // Create slots for worn artifacts. - for (size_t g = 0; g < GameConstants::BACKPACK_START ; g++) + for(size_t g = 0; g < GameConstants::BACKPACK_START; g++) { - artWorn[ArtifactPosition(g)] = new CHeroArtPlace(slotPos[g]); + artWorn[ArtifactPosition(g)] = std::make_shared(slotPos[g]); artWorn[ArtifactPosition(g)]->ourOwner = this; eraseSlotData(artWorn[ArtifactPosition(g)], ArtifactPosition(g)); } @@ -646,7 +659,7 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart) // Create slots for the backpack. for(size_t s=0; s<5; ++s) { - auto add = new CHeroArtPlace(Point(403 + 46 * s, 365)); + auto add = std::make_shared(Point(403 + 46 * s, 365)); add->ourOwner = this; eraseSlotData(add, ArtifactPosition(GameConstants::BACKPACK_START + s)); @@ -654,8 +667,8 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart) backpack.push_back(add); } - leftArtRoll = new CButton(Point(379, 364), "hsbtns3.def", CButton::tooltip(), [&](){ scrollBackpack(-1);}, SDLK_LEFT); - rightArtRoll = new CButton(Point(632, 364), "hsbtns5.def", CButton::tooltip(), [&](){ scrollBackpack(+1);}, SDLK_RIGHT); + leftArtRoll = std::make_shared(Point(379, 364), "hsbtns3.def", CButton::tooltip(), [&](){ scrollBackpack(-1);}, SDLK_LEFT); + rightArtRoll = std::make_shared(Point(632, 364), "hsbtns5.def", CButton::tooltip(), [&](){ scrollBackpack(+1);}, SDLK_RIGHT); } CArtifactsOfHero::~CArtifactsOfHero() @@ -674,7 +687,6 @@ void CArtifactsOfHero::updateParentWindow() } else if(CExchangeWindow* cew = dynamic_cast(GH.topInt())) { - //use our copy of hero to draw window if(cew->heroInst[0]->id == curHero->id) cew->heroInst[0] = curHero; @@ -684,16 +696,7 @@ void CArtifactsOfHero::updateParentWindow() if(!updateState) { cew->deactivate(); -// for(int g=0; gheroInst); ++g) -// { -// if(cew->heroInst[g] == curHero) -// { -// cew->artifs[g]->setHero(curHero); -// } -// } - - - cew->prepareBackground(); + cew->updateWidgets(); cew->redraw(); cew->activate(); } @@ -746,7 +749,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact assert(dst.slot >= GameConstants::BACKPACK_START); commonInfo->reset(); - CHeroArtPlace *ap = nullptr; + CArtifactsOfHero::ArtPlacePtr ap; for(CArtifactsOfHero *aoh : commonInfo->participants) { if(dst.isHolder(aoh->curHero)) @@ -811,7 +814,7 @@ void CArtifactsOfHero::artifactRemoved(const ArtifactLocation &al) } } -CHeroArtPlace * CArtifactsOfHero::getArtPlace(int slot) +CArtifactsOfHero::ArtPlacePtr CArtifactsOfHero::getArtPlace(int slot) { if(slot < GameConstants::BACKPACK_START) { @@ -825,7 +828,7 @@ CHeroArtPlace * CArtifactsOfHero::getArtPlace(int slot) } else { - for(CHeroArtPlace *ap : backpack) + for(ArtPlacePtr ap : backpack) if(ap->slotID == slot) return ap; return nullptr; @@ -867,21 +870,47 @@ CArtifactHolder::CArtifactHolder() { } +void CWindowWithArtifacts::addSet(std::shared_ptr artSet) +{ + artSets.emplace_back(artSet); +} + +std::shared_ptr CWindowWithArtifacts::getCommonPart() +{ + for(auto artSetWeak : artSets) + { + std::shared_ptr realPtr = artSetWeak.lock(); + if(realPtr) + return realPtr->commonInfo; + } + + return std::shared_ptr(); +} + void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation &artLoc) { - for(CArtifactsOfHero *aoh : artSets) - aoh->artifactRemoved(artLoc); + for(auto artSetWeak : artSets) + { + std::shared_ptr realPtr = artSetWeak.lock(); + if(realPtr) + realPtr->artifactRemoved(artLoc); + } } void CWindowWithArtifacts::artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) { - CArtifactsOfHero *destaoh = nullptr; - for(CArtifactsOfHero *aoh : artSets) + CArtifactsOfHero * destaoh = nullptr; + + for(auto artSetWeak : artSets) { - aoh->artifactMoved(artLoc, destLoc); - aoh->redraw(); - if(destLoc.isHolder(aoh->getHero())) - destaoh = aoh; + std::shared_ptr realPtr = artSetWeak.lock(); + if(realPtr) + { + realPtr->artifactMoved(artLoc, destLoc); + realPtr->redraw(); + if(destLoc.isHolder(realPtr->getHero())) + destaoh = realPtr.get(); + } } //Make sure the status bar is updated so it does not display old text @@ -893,14 +922,22 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation &artLoc, const A void CWindowWithArtifacts::artifactDisassembled(const ArtifactLocation &artLoc) { - for(CArtifactsOfHero *aoh : artSets) - aoh->artifactDisassembled(artLoc); + for(auto artSetWeak : artSets) + { + std::shared_ptr realPtr = artSetWeak.lock(); + if(realPtr) + realPtr->artifactDisassembled(artLoc); + } } void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation &artLoc) { - for(CArtifactsOfHero *aoh : artSets) - aoh->artifactAssembled(artLoc); + for(auto artSetWeak : artSets) + { + std::shared_ptr realPtr = artSetWeak.lock(); + if(realPtr) + realPtr->artifactAssembled(artLoc); + } } void CArtifactsOfHero::SCommonPart::Artpos::clear() @@ -979,14 +1016,14 @@ void CCommanderArtPlace::clickRight(tribool down, bool previousState) void CCommanderArtPlace::createImage() { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); int imageIndex = 0; - if (ourArt) + if(ourArt) imageIndex = ourArt->artType->iconIndex; - image = new CAnimImage("artifact", imageIndex); - if (!ourArt) + image = std::make_shared("artifact", imageIndex); + if(!ourArt) image->disable(); } diff --git a/client/widgets/CArtifactHolder.h b/client/widgets/CArtifactHolder.h index 4ecea572f..cdf92e69e 100644 --- a/client/widgets/CArtifactHolder.h +++ b/client/widgets/CArtifactHolder.h @@ -9,7 +9,6 @@ */ #pragma once -//#include "CComponent.h" #include "MiscWidgets.h" class CArtifactsOfHero; @@ -29,21 +28,10 @@ public: virtual void artifactAssembled(const ArtifactLocation &artLoc)=0; }; -class CWindowWithArtifacts : public CArtifactHolder -{ -public: - std::vector artSets; - - void artifactRemoved(const ArtifactLocation &artLoc) override; - void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) override; - void artifactDisassembled(const ArtifactLocation &artLoc) override; - void artifactAssembled(const ArtifactLocation &artLoc) override; -}; - class CArtPlace : public LRClickableAreaWTextComp { protected: - CAnimImage *image; + std::shared_ptr image; virtual void createImage()=0; public: const CArtifactInstance * ourArt; // should be changed only with setArtifact() @@ -75,7 +63,7 @@ public: /// Artifacts can be placed there. Gets shown at the hero window class CHeroArtPlace: public CArtPlace { - CAnimImage *selection; + std::shared_ptr selection; void createImage() override; @@ -111,14 +99,10 @@ public: /// Contains artifacts of hero. Distincts which artifacts are worn or backpacked class CArtifactsOfHero : public CIntObject { - const CGHeroInstance * curHero; - - std::map artWorn; - - std::vector backpack; //hero's visible backpack (only 5 elements!) - int backpackPos; //number of first art visible in backpack (in hero's vector) - public: + using ArtPlacePtr = std::shared_ptr; + using ArtPlaceMap = std::map; + struct SCommonPart { struct Artpos @@ -142,8 +126,10 @@ public: bool updateState; // Whether the commonInfo should be updated on setHero or not. - CButton * leftArtRoll, * rightArtRoll; + std::shared_ptr leftArtRoll; + std::shared_ptr rightArtRoll; bool allowedAssembling; + std::multiset artifactsOnAltar; //artifacts id that are technically present in backpack but in GUI are moved to the altar - they'll be omitted in backpack slots std::function highlightModeCallback; //if set, clicking on art place doesn't pick artifact but highlights the slot and calls this function @@ -152,7 +138,7 @@ public: void artifactRemoved(const ArtifactLocation &al); void artifactAssembled(const ArtifactLocation &al); void artifactDisassembled(const ArtifactLocation &al); - CHeroArtPlace *getArtPlace(int slot);//may return null + ArtPlacePtr getArtPlace(int slot);//may return null void setHero(const CGHeroInstance * hero); const CGHeroInstance *getHero() const; @@ -163,17 +149,41 @@ public: void markPossibleSlots(const CArtifactInstance* art); void unmarkSlots(bool withRedraw = true); //unmarks slots in all visible AOHs void unmarkLocalSlots(bool withRedraw = true); //unmarks slots in that particular AOH - void setSlotData (CHeroArtPlace* artPlace, ArtifactPosition slotID); void updateWornSlots (bool redrawParent = true); void updateSlot(ArtifactPosition i); - void eraseSlotData (CHeroArtPlace* artPlace, ArtifactPosition slotID); CArtifactsOfHero(const Point& position, bool createCommonPart = false); //Alternative constructor, used if custom artifacts positioning required (Kingdom interface) - CArtifactsOfHero(std::map ArtWorn, std::vector Backpack, - CButton *leftScroll, CButton *rightScroll, bool createCommonPart = false); + CArtifactsOfHero(ArtPlaceMap ArtWorn, std::vector Backpack, + std::shared_ptr leftScroll, std::shared_ptr rightScroll, bool createCommonPart = false); ~CArtifactsOfHero(); void updateParentWindow(); friend class CHeroArtPlace; + +private: + + const CGHeroInstance * curHero; + + ArtPlaceMap artWorn; + + std::vector backpack; //hero's visible backpack (only 5 elements!) + int backpackPos; //number of first art visible in backpack (in hero's vector) + + void eraseSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID); + void setSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID); +}; + +class CWindowWithArtifacts : public CArtifactHolder +{ + std::vector> artSets; +public: + void addSet(std::shared_ptr artSet); + + std::shared_ptr getCommonPart(); + + void artifactRemoved(const ArtifactLocation &artLoc) override; + void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) override; + void artifactDisassembled(const ArtifactLocation &artLoc) override; + void artifactAssembled(const ArtifactLocation &artLoc) override; }; diff --git a/client/widgets/CComponent.cpp b/client/widgets/CComponent.cpp index 9e0d04ad0..6620fe4ed 100644 --- a/client/widgets/CComponent.cpp +++ b/client/widgets/CComponent.cpp @@ -27,29 +27,26 @@ #include "../../lib/CGeneralTextHandler.h" #include "../../lib/NetPacksBase.h" -CComponent::CComponent(Etype Type, int Subtype, int Val, ESize imageSize): - image(nullptr), - perDay(false) +CComponent::CComponent(Etype Type, int Subtype, int Val, ESize imageSize) + : perDay(false) { - addUsedEvents(RCLICK); init(Type, Subtype, Val, imageSize); } -CComponent::CComponent(const Component &c, ESize imageSize): - image(nullptr), - perDay(false) +CComponent::CComponent(const Component & c, ESize imageSize) + : perDay(false) { - addUsedEvents(RCLICK); - if(c.id == Component::RESOURCE && c.when==-1) perDay = true; - init((Etype)c.id,c.subtype,c.val, imageSize); + init((Etype)c.id, c.subtype, c.val, imageSize); } void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + addUsedEvents(RCLICK); compType = Type; subtype = Subtype; @@ -74,14 +71,15 @@ void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize) for(auto & line : textLines) { int height = graphics->fonts[font]->getLineHeight(); - auto label = new CLabel(pos.w/2, pos.h + height/2, font, CENTER, Colors::WHITE, line); + auto label = std::make_shared(pos.w/2, pos.h + height/2, font, CENTER, Colors::WHITE, line); pos.h += height; - if (label->pos.w > pos.w) + if(label->pos.w > pos.w) { pos.x -= (label->pos.w - pos.w)/2; pos.w = label->pos.w; } + lines.push_back(label); } } @@ -232,9 +230,8 @@ std::string CComponent::getSubtitleInternal() void CComponent::setSurface(std::string defName, int imgPos) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - vstd::clear_pointer(image); - image = new CAnimImage(defName, imgPos); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + image = std::make_shared(defName, imgPos); } void CComponent::clickRight(tribool down, bool previousState) @@ -291,7 +288,7 @@ void CSelectableComponent::showAll(SDL_Surface * to) } } -void CComponentBox::selectionChanged(CSelectableComponent * newSelection) +void CComponentBox::selectionChanged(std::shared_ptr newSelection) { if (newSelection == selected) return; @@ -339,14 +336,14 @@ void CComponentBox::placeComponents(bool selectable) { static const int betweenRows = 22; - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); if (components.empty()) return; //prepare components for(auto & comp : components) { - addChild(comp); + addChild(comp.get()); comp->moveTo(Point(pos.x, pos.y)); } @@ -362,14 +359,14 @@ void CComponentBox::placeComponents(bool selectable) rows.push_back (RowData (0,0,0)); //split components in rows - CComponent * prevComp = nullptr; + std::shared_ptr prevComp; - for(CComponent * comp : components) + for(std::shared_ptr comp : components) { //make sure that components are smaller than our width //assert(pos.w == 0 || pos.w < comp->pos.w); - const int distance = prevComp ? getDistance(prevComp, comp) : 0; + const int distance = prevComp ? getDistance(prevComp.get(), comp.get()) : 0; //start next row if ((pos.w != 0 && rows.back().width + comp->pos.w + distance > pos.w) // row is full @@ -421,11 +418,11 @@ void CComponentBox::placeComponents(bool selectable) { if (selectable) { - Point orPos = Point(currentX - freeSpace, currentY) + getOrTextPos(prevComp, *iter); + Point orPos = Point(currentX - freeSpace, currentY) + getOrTextPos(prevComp.get(), iter->get()); - new CLabel(orPos.x, orPos.y, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[4]); + orLabels.push_back(std::make_shared(orPos.x, orPos.y, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[4])); } - currentX += getDistance(prevComp, *iter); + currentX += getDistance(prevComp.get(), iter->get()); } (*iter)->moveBy(Point(currentX, currentY)); @@ -438,27 +435,16 @@ void CComponentBox::placeComponents(bool selectable) } } -CComponentBox::CComponentBox(CComponent * _components, Rect position): - components(1, _components), - selected(nullptr) +CComponentBox::CComponentBox(std::vector> _components, Rect position): + components(_components) { type |= REDRAW_PARENT; pos = position + pos; placeComponents(false); } -CComponentBox::CComponentBox(std::vector _components, Rect position): - components(_components), - selected(nullptr) -{ - type |= REDRAW_PARENT; - pos = position + pos; - placeComponents(false); -} - -CComponentBox::CComponentBox(std::vector _components, Rect position, std::function _onSelect): +CComponentBox::CComponentBox(std::vector> _components, Rect position, std::function _onSelect): components(_components.begin(), _components.end()), - selected(nullptr), onSelect(_onSelect) { type |= REDRAW_PARENT; diff --git a/client/widgets/CComponent.h b/client/widgets/CComponent.h index 1b7968855..f46428b25 100644 --- a/client/widgets/CComponent.h +++ b/client/widgets/CComponent.h @@ -13,6 +13,7 @@ struct Component; class CAnimImage; +class CLabel; /// common popup window component class CComponent : public virtual CIntObject @@ -34,6 +35,8 @@ public: }; private: + std::vector> lines; + size_t getIndex(); const std::vector getFileName(); void setSurface(std::string defName, int imgPos); @@ -42,7 +45,7 @@ private: void init(Etype Type, int Subtype, int Val, ESize imageSize); public: - CAnimImage *image; //our image + std::shared_ptr image; Etype compType; //component type ESize size; //component size. @@ -72,19 +75,21 @@ public: void clickLeft(tribool down, bool previousState) override; //call-in CSelectableComponent(Etype Type, int Sub, int Val, ESize imageSize=large, std::function OnSelect = nullptr); - CSelectableComponent(const Component &c, std::function OnSelect = nullptr); + CSelectableComponent(const Component & c, std::function OnSelect = nullptr); }; /// box with multiple components (up to 8?) /// will take ownership on components and delete them afterwards class CComponentBox : public CIntObject { - std::vector components; + std::vector> components; - CSelectableComponent * selected; + std::vector> orLabels; + + std::shared_ptr selected; std::function onSelect; - void selectionChanged(CSelectableComponent * newSelection); + void selectionChanged(std::shared_ptr newSelection); //get position of "or" text between these comps //it will place "or" equidistant to both images @@ -98,14 +103,11 @@ public: /// return index of selected item int selectedIndex(); - /// constructor for quite common 1-components popups - /// if position width or height are 0 then it will be determined automatically - CComponentBox(CComponent * components, Rect position); /// constructor for non-selectable components - CComponentBox(std::vector components, Rect position); + CComponentBox(std::vector> components, Rect position); /// constructor for selectable components /// will also create "or" labels between components /// onSelect - optional function that will be called every time on selection change - CComponentBox(std::vector components, Rect position, std::function onSelect = nullptr); + CComponentBox(std::vector> components, Rect position, std::function onSelect = nullptr); }; diff --git a/client/widgets/CGarrisonInt.cpp b/client/widgets/CGarrisonInt.cpp index 5061bd675..abd286d3d 100644 --- a/client/widgets/CGarrisonInt.cpp +++ b/client/widgets/CGarrisonInt.cpp @@ -172,8 +172,12 @@ bool CGarrisonSlot::highlightOrDropArtifact() bool artSelected = false; if (CWindowWithArtifacts* chw = dynamic_cast(GH.topInt())) //dirty solution { - const std::shared_ptr commonInfo = chw->artSets.front()->commonInfo; - if (const CArtifactInstance *art = commonInfo->src.art) + const std::shared_ptr commonInfo = chw->getCommonPart(); + const CArtifactInstance * art = nullptr; + if(commonInfo) + art = commonInfo->src.art; + + if(art) { const CGHeroInstance *srcHero = commonInfo->src.AOH->getHero(); artSelected = true; @@ -335,7 +339,7 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) void CGarrisonSlot::update() { - if (getObj() != nullptr) + if(getObj() != nullptr) { addUsedEvents(LCLICK | RCLICK | HOVER); myStack = getObj()->getStackPtr(ID); @@ -348,7 +352,7 @@ void CGarrisonSlot::update() creature = nullptr; } - if (creature) + if(creature) { creatureImage->enable(); creatureImage->setFrame(creature->iconIndex); @@ -363,26 +367,24 @@ void CGarrisonSlot::update() } } -CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, CGarrisonSlot::EGarrisonType Upg, const CStackInstance * Creature): - ID(IID), - owner(Owner), - myStack(Creature), - creature(Creature ? Creature->type : nullptr), - upg(Upg) +CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGarrisonSlot::EGarrisonType Upg, const CStackInstance * Creature) + : ID(IID), + owner(Owner), + myStack(Creature), + creature(nullptr), + upg(Upg) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - if (getObj()) - addUsedEvents(LCLICK | RCLICK | HOVER); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + pos.x += x; pos.y += y; std::string imgName = owner->smallIcons ? "cprsmall" : "TWCRPORT"; - creatureImage = new CAnimImage(imgName, creature ? creature->iconIndex : 0); - if (!creature) - creatureImage->disable(); + creatureImage = std::make_shared(imgName, 0); + creatureImage->disable(); - selectionImage = new CAnimImage(imgName, 1); + selectionImage = std::make_shared(imgName, 1); selectionImage->disable(); if(Owner->smallIcons) @@ -396,11 +398,9 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, CGar pos.h = 64; } - stackCount = new CLabel(pos.w, pos.h, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE); - if (!creature) - stackCount->disable(); - else - stackCount->setText(boost::lexical_cast(myStack->count)); + stackCount = std::make_shared(pos.w, pos.h, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE); + + update(); } void CGarrisonSlot::splitIntoParts(CGarrisonSlot::EGarrisonType type, int amount, int maxOfSplittedSlots) @@ -419,8 +419,9 @@ void CGarrisonSlot::splitIntoParts(CGarrisonSlot::EGarrisonType type, int amount void CGarrisonSlot::handleSplittingShortcuts() { const Uint8 * state = SDL_GetKeyboardState(NULL); - if(owner->getSelection() && owner->getEmptySlots(owner->getSelection()->upg).size() && owner->getSelection()->myStack->count > 1){ - if (state[SDL_SCANCODE_LCTRL] && state[SDL_SCANCODE_LSHIFT]) + if(owner->getSelection() && owner->getEmptySlots(owner->getSelection()->upg).size() && owner->getSelection()->myStack->count > 1) + { + if(state[SDL_SCANCODE_LCTRL] && state[SDL_SCANCODE_LSHIFT]) splitIntoParts(owner->getSelection()->upg, 1, 7); else if(state[SDL_SCANCODE_LCTRL]) splitIntoParts(owner->getSelection()->upg, 1, 1); @@ -432,39 +433,38 @@ void CGarrisonSlot::handleSplittingShortcuts() } } -void CGarrisonInt::addSplitBtn(CButton * button) +void CGarrisonInt::addSplitBtn(std::shared_ptr button) { - addChild(button); - button->recActions = defActions; + addChild(button.get()); + button->recActions &= ~DISPOSE; splitButtons.push_back(button); button->block(getSelection() == nullptr); } void CGarrisonInt::createSlots() { - OBJ_CONSTRUCTION_CAPTURING_ALL; - int distance = interx + (smallIcons? 32 : 58); + int distance = interx + (smallIcons ? 32 : 58); for(int i=0; i<2; i++) { - std::vector garrisonSlots; + std::vector> garrisonSlots; garrisonSlots.resize(7); - if (armedObjs[i]) + if(armedObjs[i]) { for(auto & elem : armedObjs[i]->Slots()) { - garrisonSlots[elem.first.getNum()] = new CGarrisonSlot(this, i*garOffset.x + (elem.first.getNum()*distance), i*garOffset.y, elem.first, static_cast(i), elem.second); + garrisonSlots[elem.first.getNum()] = std::make_shared(this, i*garOffset.x + (elem.first.getNum()*distance), i*garOffset.y, elem.first, static_cast(i), elem.second); } } for(int j=0; j<7; j++) { if(!garrisonSlots[j]) - garrisonSlots[j] = new CGarrisonSlot(this, i*garOffset.x + (j*distance), i*garOffset.y, SlotID(j), static_cast(i), nullptr); - if (twoRows && j>=4) + garrisonSlots[j] = std::make_shared(this, i*garOffset.x + (j*distance), i*garOffset.y, SlotID(j), static_cast(i), nullptr); + if(twoRows && j>=4) { garrisonSlots[j]->moveBy(Point(-126, 37)); } } - std::copy(garrisonSlots.begin(), garrisonSlots.end(), std::back_inserter(availableSlots)); + vstd::concatenate(availableSlots, garrisonSlots); } } @@ -476,10 +476,8 @@ void CGarrisonInt::recreateSlots() for(auto & elem : splitButtons) elem->block(true); - - for(CGarrisonSlot * slot : availableSlots) + for(auto slot : availableSlots) slot->update(); - } void CGarrisonInt::splitClick() @@ -494,19 +492,20 @@ void CGarrisonInt::splitStacks(int, int amountRight) LOCPLINT->cb->splitStack(armedObjs[getSelection()->upg], armedObjs[pb], getSelection()->ID, p2, amountRight); } -CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point &garsOffset, - SDL_Surface *pomsur, const Point& SurOffset, - const CArmedInstance *s1, const CArmedInstance *s2, - bool _removableUnits, bool smallImgs, bool _twoRows ) : - highlighted(nullptr), - inSplittingMode(false), - interx(inx), - garOffset(garsOffset), - pb(false), - smallIcons(smallImgs), - removableUnits(_removableUnits), - twoRows(_twoRows) +CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point & garsOffset, + const CArmedInstance * s1, const CArmedInstance * s2, + bool _removableUnits, bool smallImgs, bool _twoRows) + : highlighted(nullptr), + inSplittingMode(false), + interx(inx), + garOffset(garsOffset), + pb(false), + smallIcons(smallImgs), + removableUnits(_removableUnits), + twoRows(_twoRows) { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + setArmy(s1, false); setArmy(s2, true); pos.x += x; @@ -521,16 +520,16 @@ const CGarrisonSlot * CGarrisonInt::getSelection() void CGarrisonInt::selectSlot(CGarrisonSlot *slot) { - if (slot != highlighted) + if(slot != highlighted) { - if (highlighted) + if(highlighted) highlighted->setHighlight(false); highlighted = slot; - for (auto button : splitButtons) + for(auto button : splitButtons) button->block(highlighted == nullptr || !slot->our()); - if (highlighted) + if(highlighted) highlighted->setHighlight(true); } } @@ -539,11 +538,11 @@ void CGarrisonInt::setSplittingMode(bool on) { assert(on == false || highlighted != nullptr); //can't be in splitting mode without selection - if (inSplittingMode || on) + if(inSplittingMode || on) { - for(CGarrisonSlot * slot : availableSlots) + for(auto slot : availableSlots) { - if(slot!=getSelection()) + if(slot.get() != getSelection()) slot->setHighlight( ( on && (slot->our() || slot->ally()) && (slot->creature == nullptr || slot->creature == getSelection()->creature))); } inSplittingMode = on; @@ -558,58 +557,16 @@ bool CGarrisonInt::getSplittingMode() std::vector CGarrisonInt::getEmptySlots(CGarrisonSlot::EGarrisonType type) { std::vector emptySlots; - for(CGarrisonSlot * slot : availableSlots) + for(auto slot : availableSlots) { if(type == slot->upg && ((slot->our() || slot->ally()) && slot->creature == nullptr)) - emptySlots.push_back(slot); + emptySlots.push_back(slot.get()); } return emptySlots; } -void CGarrisonInt::setArmy(const CArmedInstance *army, bool bottomGarrison) +void CGarrisonInt::setArmy(const CArmedInstance * army, bool bottomGarrison) { owned[bottomGarrison] = army ? (army->tempOwner == LOCPLINT->playerID || army->tempOwner == PlayerColor::UNFLAGGABLE) : false; armedObjs[bottomGarrison] = army; } - -CGarrisonWindow::CGarrisonWindow( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits ): - CWindowObject(PLAYER_COLORED, "GARRISON") -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - - garr = new CGarrisonInt(92, 127, 4, Point(0,96), background->bg, Point(93,127), up, down, removableUnits); - { - CButton *split = new CButton(Point(88, 314), "IDV6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3], ""), [&](){ garr->splitClick(); } ); - removeChild(split); - garr->addSplitBtn(split); - } - quit = new CButton(Point(399, 314), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[8], ""), [&](){ close(); }, SDLK_RETURN); - - std::string titleText; - if (down->tempOwner == up->tempOwner) - titleText = CGI->generaltexth->allTexts[709]; - else - { - //assume that this is joining monsters dialog - if(up->Slots().size() > 0) - { - titleText = CGI->generaltexth->allTexts[35]; - boost::algorithm::replace_first(titleText, "%s", up->Slots().begin()->second->type->namePl); - } - else - logGlobal->error("Invalid armed instance for garrison window."); - } - new CLabel(275, 30, FONT_BIG, CENTER, Colors::YELLOW, titleText); - - new CAnimImage("CREST58", up->getOwner().getNum(), 0, 28, 124); - new CAnimImage("PortraitsLarge", down->portrait, 0, 29, 222); -} - -CGarrisonHolder::CGarrisonHolder() -{ -} - -void CWindowWithGarrison::updateGarrisons() -{ - garr->recreateSlots(); -} diff --git a/client/widgets/CGarrisonInt.h b/client/widgets/CGarrisonInt.h index 27d6547b6..1defc7b08 100644 --- a/client/widgets/CGarrisonInt.h +++ b/client/widgets/CGarrisonInt.h @@ -25,8 +25,8 @@ class CGarrisonSlot : public CIntObject { SlotID ID; //for identification CGarrisonInt *owner; - const CStackInstance *myStack; //nullptr if slot is empty - const CCreature *creature; + const CStackInstance * myStack; //nullptr if slot is empty + const CCreature * creature; /// Type of Garrison for slot (up or down) enum EGarrisonType @@ -35,9 +35,9 @@ class CGarrisonSlot : public CIntObject DOWN, ///< 1 - down garrison (Visiting) } upg; ///< Flag indicating if it is the up or down garrison - CAnimImage * creatureImage; - CAnimImage * selectionImage; // image for selection, not always visible - CLabel * stackCount; + std::shared_ptr creatureImage; + std::shared_ptr selectionImage; // image for selection, not always visible + std::shared_ptr stackCount; bool viewInfo(); bool highlightOrDropArtifact(); @@ -65,19 +65,15 @@ public: class CGarrisonInt :public CIntObject { /// Chosen slot. Should be changed only via selectSlot. - CGarrisonSlot *highlighted; + CGarrisonSlot * highlighted; bool inSplittingMode; + std::vector> availableSlots; ///< Slots of upper and lower garrison + void createSlots(); public: - void selectSlot(CGarrisonSlot * slot); ///< @param slot null = deselect - const CGarrisonSlot * getSelection(); - - void setSplittingMode(bool on); - bool getSplittingMode(); - int interx; ///< Space between slots Point garOffset; ///< Offset between garrisons (not used if only one hero) - std::vector splitButtons; ///< May be empty if no buttons + std::vector> splitButtons; ///< May be empty if no buttons SlotID p2; ///< TODO: comment me bool pb, @@ -86,15 +82,19 @@ public: twoRows, ///< slots Will be placed in 2 rows owned[2]; ///< player Owns up or down army ([0] upper, [1] lower) - std::vector availableSlots; ///< Slots of upper and lower garrison + void selectSlot(CGarrisonSlot * slot); ///< @param slot null = deselect + const CGarrisonSlot * getSelection(); + + void setSplittingMode(bool on); + bool getSplittingMode(); + std::vector getEmptySlots(CGarrisonSlot::EGarrisonType type); - const CArmedInstance *armedObjs[2]; ///< [0] is upper, [1] is down + const CArmedInstance * armedObjs[2]; ///< [0] is upper, [1] is down - void setArmy(const CArmedInstance *army, bool bottomGarrison); - void addSplitBtn(CButton * button); + void setArmy(const CArmedInstance * army, bool bottomGarrison); + void addSplitBtn(std::shared_ptr button); - void createSlots(); void recreateSlots(); void splitClick(); ///< handles click on split button @@ -104,40 +104,21 @@ public: /// @param x, y Position /// @param inx Distance between slots; /// @param garsOffset - /// @param pomsur, SurOffset UNUSED /// @param s1, s2 Top and bottom armies /// @param _removableUnits You can take units from top /// @param smallImgs Units images size 64x58 or 32x32 /// @param _twoRows Display slots in 2 row (1st row = 4 slots, 2nd = 3 slots) - CGarrisonInt(int x, int y, - int inx, - const Point &garsOffset, - SDL_Surface *pomsur, const Point &SurOffset, - const CArmedInstance *s1, const CArmedInstance *s2=nullptr, - bool _removableUnits = true, - bool smallImgs = false, - bool _twoRows=false); + CGarrisonInt(int x, int y, int inx, + const Point & garsOffset, + const CArmedInstance * s1, const CArmedInstance * s2 = nullptr, + bool _removableUnits = true, + bool smallImgs = false, + bool _twoRows = false); }; class CGarrisonHolder { public: - CGarrisonHolder(); - virtual void updateGarrisons()=0; + virtual void updateGarrisons() = 0; }; -class CWindowWithGarrison : public virtual CGarrisonHolder -{ -public: - CGarrisonInt *garr; - virtual void updateGarrisons() override; -}; - -/// Garrison window where you can take creatures out of the hero to place it on the garrison -class CGarrisonWindow : public CWindowObject, public CWindowWithGarrison -{ -public: - CButton * quit; - - CGarrisonWindow(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits); -}; diff --git a/client/widgets/Images.cpp b/client/widgets/Images.cpp index 710504f67..4261a0ef1 100644 --- a/client/widgets/Images.cpp +++ b/client/widgets/Images.cpp @@ -179,13 +179,6 @@ void CPicture::createSimpleRect(const Rect &r, bool screenFormat, ui32 color) freeSurf = true; } -void CPicture::colorizeAndConvert(PlayerColor player) -{ - assert(bg); - colorize(player); - convertToScreenBPP(); -} - void CPicture::colorize(PlayerColor player) { assert(bg); @@ -257,9 +250,6 @@ void CAnimImage::init() CAnimImage::~CAnimImage() { - anim->unload(frame, group); - if (flags & CShowableAnim::BASE) - anim->unload(0,group); } void CAnimImage::showAll(SDL_Surface * to) @@ -281,7 +271,6 @@ void CAnimImage::setFrame(size_t Frame, size_t Group) return; if (anim->size(Group) > Frame) { - anim->unload(frame, group); anim->load(Frame, Group); frame = Frame; group = Group; @@ -348,8 +337,9 @@ bool CShowableAnim::set(size_t Group, size_t from, size_t to) if (max < from || max == 0) return false; - anim->load(Group); - anim->unload(group); + anim->unloadGroup(group); + anim->loadGroup(Group); + group = Group; frame = first = from; last = max; @@ -363,8 +353,9 @@ bool CShowableAnim::set(size_t Group) return false; if (group != Group) { - anim->loadGroup(Group); anim->unloadGroup(group); + anim->loadGroup(Group); + first = 0; group = Group; last = anim->size(Group); diff --git a/client/widgets/Images.h b/client/widgets/Images.h index 1cc38a639..71defa97f 100644 --- a/client/widgets/Images.h +++ b/client/widgets/Images.h @@ -50,7 +50,6 @@ public: void show(SDL_Surface * to) override; void showAll(SDL_Surface * to) override; void convertToScreenBPP(); - void colorizeAndConvert(PlayerColor player); void colorize(PlayerColor player); }; diff --git a/client/widgets/MiscWidgets.cpp b/client/widgets/MiscWidgets.cpp index 7d1a124bd..33265b424 100644 --- a/client/widgets/MiscWidgets.cpp +++ b/client/widgets/MiscWidgets.cpp @@ -87,7 +87,7 @@ void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState) { if((!down) && previousState) { - std::vector comp(1, createComponent()); + std::vector> comp(1, createComponent()); LOCPLINT->showInfoDialog(text, comp); } } @@ -98,19 +98,19 @@ LRClickableAreaWTextComp::LRClickableAreaWTextComp(const Rect &Pos, int BaseType type = -1; } -CComponent * LRClickableAreaWTextComp::createComponent() const +std::shared_ptr LRClickableAreaWTextComp::createComponent() const { if(baseType >= 0) - return new CComponent(CComponent::Etype(baseType), type, bonusValue); + return std::make_shared(CComponent::Etype(baseType), type, bonusValue); else - return nullptr; + return std::shared_ptr(); } void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState) { if(down) { - if(CComponent *comp = createComponent()) + if(auto comp = createComponent()) { CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp)); return; @@ -120,16 +120,19 @@ void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState) LRClickableAreaWText::clickRight(down, previousState); //only if with-component variant not occurred } -CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero):hero(_hero) +CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero) + : CIntObject(LCLICK | RCLICK | HOVER), + hero(_hero) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - addUsedEvents(LCLICK | RCLICK | HOVER); - pos.x += x; pos.w = 58; - pos.y += y; pos.h = 64; + pos.x += x; + pos.w = 58; + pos.y += y; + pos.h = 64; - if (hero) - new CAnimImage("PortraitsLarge", hero->portrait); + if(hero) + portrait = std::make_shared("PortraitsLarge", hero->portrait); } void CHeroArea::clickLeft(tribool down, bool previousState) @@ -181,7 +184,8 @@ void CMinorResDataBar::show(SDL_Surface * to) void CMinorResDataBar::showAll(SDL_Surface * to) { - blitAt(bg,pos.x,pos.y,to); + CIntObject::showAll(to); + for (Res::ERes i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1)) { std::string text = boost::lexical_cast(LOCPLINT->cb->getResourceAmount(i)); @@ -202,34 +206,34 @@ void CMinorResDataBar::showAll(SDL_Surface * to) CMinorResDataBar::CMinorResDataBar() { - bg = BitmapHandler::loadBitmap("KRESBAR.bmp"); - CSDL_Ext::setDefaultColorKey(bg); - graphics->blueToPlayersAdv(bg,LOCPLINT->playerID); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + pos.x = 7; pos.y = 575; - pos.w = bg->w; - pos.h = bg->h; + + background = std::make_shared("KRESBAR.bmp"); + background->colorize(LOCPLINT->playerID); + + pos.w = background->pos.w; + pos.h = background->pos.h; } -CMinorResDataBar::~CMinorResDataBar() -{ - SDL_FreeSurface(bg); -} +CMinorResDataBar::~CMinorResDataBar() = default; void CArmyTooltip::init(const InfoAboutArmy &army) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - new CLabel(66, 2, FONT_SMALL, TOPLEFT, Colors::WHITE, army.name); + title = std::make_shared(66, 2, FONT_SMALL, TOPLEFT, Colors::WHITE, army.name); std::vector slotsPos; - slotsPos.push_back(Point(36,73)); - slotsPos.push_back(Point(72,73)); - slotsPos.push_back(Point(108,73)); - slotsPos.push_back(Point(18,122)); - slotsPos.push_back(Point(54,122)); - slotsPos.push_back(Point(90,122)); - slotsPos.push_back(Point(126,122)); + slotsPos.push_back(Point(36, 73)); + slotsPos.push_back(Point(72, 73)); + slotsPos.push_back(Point(108, 73)); + slotsPos.push_back(Point(18, 122)); + slotsPos.push_back(Point(54, 122)); + slotsPos.push_back(Point(90, 122)); + slotsPos.push_back(Point(126, 122)); for(auto & slot : army.army) { @@ -239,24 +243,26 @@ void CArmyTooltip::init(const InfoAboutArmy &army) continue; } - new CAnimImage("CPRSMALL", slot.second.type->iconIndex, 0, slotsPos[slot.first.getNum()].x, slotsPos[slot.first.getNum()].y); + icons.push_back(std::make_shared("CPRSMALL", slot.second.type->iconIndex, 0, slotsPos[slot.first.getNum()].x, slotsPos[slot.first.getNum()].y)); std::string subtitle; if(army.army.isDetailed) + { subtitle = boost::lexical_cast(slot.second.count); + } else { //if =0 - we have no information about stack size at all - if (slot.second.count) + if(slot.second.count) subtitle = CGI->generaltexth->arraytxt[171 + 3*(slot.second.count)]; } - new CLabel(slotsPos[slot.first.getNum()].x + 17, slotsPos[slot.first.getNum()].y + 41, FONT_TINY, CENTER, Colors::WHITE, subtitle); + subtitles.push_back(std::make_shared(slotsPos[slot.first.getNum()].x + 17, slotsPos[slot.first.getNum()].y + 41, FONT_TINY, CENTER, Colors::WHITE, subtitle)); } } -CArmyTooltip::CArmyTooltip(Point pos, const InfoAboutArmy &army): +CArmyTooltip::CArmyTooltip(Point pos, const InfoAboutArmy & army): CIntObject(0, pos) { init(army); @@ -268,22 +274,21 @@ CArmyTooltip::CArmyTooltip(Point pos, const CArmedInstance * army): init(InfoAboutArmy(army, true)); } -void CHeroTooltip::init(const InfoAboutHero &hero) +void CHeroTooltip::init(const InfoAboutHero & hero) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CAnimImage("PortraitsLarge", hero.portrait, 0, 3, 2); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + portrait = std::make_shared("PortraitsLarge", hero.portrait, 0, 3, 2); if(hero.details) { - for (size_t i = 0; i < hero.details->primskills.size(); i++) - new CLabel(75 + 28 * i, 58, FONT_SMALL, CENTER, Colors::WHITE, - boost::lexical_cast(hero.details->primskills[i])); + for(size_t i = 0; i < hero.details->primskills.size(); i++) + labels.push_back(std::make_shared(75 + 28 * i, 58, FONT_SMALL, CENTER, Colors::WHITE, + boost::lexical_cast(hero.details->primskills[i]))); - new CLabel(158, 98, FONT_TINY, CENTER, Colors::WHITE, - boost::lexical_cast(hero.details->mana)); + labels.push_back(std::make_shared(158, 98, FONT_TINY, CENTER, Colors::WHITE, boost::lexical_cast(hero.details->mana))); - new CAnimImage("IMRL22", hero.details->morale + 3, 0, 5, 74); - new CAnimImage("ILCK22", hero.details->luck + 3, 0, 5, 91); + morale = std::make_shared("IMRL22", hero.details->morale + 3, 0, 5, 74); + luck = std::make_shared("ILCK22", hero.details->luck + 3, 0, 5, 91); } } @@ -299,61 +304,64 @@ CHeroTooltip::CHeroTooltip(Point pos, const CGHeroInstance * hero): init(InfoAboutHero(hero, InfoAboutHero::EInfoLevel::DETAILED)); } -void CTownTooltip::init(const InfoAboutTown &town) +void CTownTooltip::init(const InfoAboutTown & town) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); //order of icons in def: fort, citadel, castle, no fort size_t fortIndex = town.fortLevel ? town.fortLevel - 1 : 3; - new CAnimImage("ITMCLS", fortIndex, 0, 105, 31); + fort = std::make_shared("ITMCLS", fortIndex, 0, 105, 31); assert(town.tType); size_t iconIndex = town.tType->clientInfo.icons[town.fortLevel > 0][town.built >= CGI->modh->settings.MAX_BUILDING_PER_TURN]; - new CAnimImage("itpt", iconIndex, 0, 3, 2); + build = std::make_shared("itpt", iconIndex, 0, 3, 2); if(town.details) { - new CAnimImage("ITMTLS", town.details->hallLevel, 0, 67, 31); + fort = std::make_shared("ITMTLS", town.details->hallLevel, 0, 67, 31); - if (town.details->goldIncome) - new CLabel(157, 58, FONT_TINY, CENTER, Colors::WHITE, + if(town.details->goldIncome) + { + income = std::make_shared(157, 58, FONT_TINY, CENTER, Colors::WHITE, boost::lexical_cast(town.details->goldIncome)); - + } if(town.details->garrisonedHero) //garrisoned hero icon - new CPicture("TOWNQKGH", 149, 76); + garrisonedHero = std::make_shared("TOWNQKGH", 149, 76); if(town.details->customRes)//silo is built { - if (town.tType->primaryRes == Res::WOOD_AND_ORE )// wood & ore + if(town.tType->primaryRes == Res::WOOD_AND_ORE )// wood & ore { - new CAnimImage("SMALRES", Res::WOOD, 0, 7, 75); - new CAnimImage("SMALRES", Res::ORE , 0, 7, 88); + res1 = std::make_shared("SMALRES", Res::WOOD, 0, 7, 75); + res2 = std::make_shared("SMALRES", Res::ORE , 0, 7, 88); } else - new CAnimImage("SMALRES", town.tType->primaryRes, 0, 7, 81); + { + res1 = std::make_shared("SMALRES", town.tType->primaryRes, 0, 7, 81); + } } } } -CTownTooltip::CTownTooltip(Point pos, const InfoAboutTown &town): - CArmyTooltip(pos, town) +CTownTooltip::CTownTooltip(Point pos, const InfoAboutTown & town) + : CArmyTooltip(pos, town) { init(town); } -CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town): - CArmyTooltip(pos, InfoAboutTown(town, true)) +CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town) + : CArmyTooltip(pos, InfoAboutTown(town, true)) { init(InfoAboutTown(town, true)); } - -void MoraleLuckBox::set(const IBonusBearer *node) +void MoraleLuckBox::set(const IBonusBearer * node) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + const int textId[] = {62, 88}; //eg %s \n\n\n {Current Luck Modifiers:} const int noneTxtId = 108; //Russian version uses same text for neutral morale\luck const int neutralDescr[] = {60, 86}; //eg {Neutral Morale} \n\n Neutral morale means your armies will neither be blessed with extra attacks or freeze in combat. @@ -363,13 +371,15 @@ void MoraleLuckBox::set(const IBonusBearer *node) int (IBonusBearer::*getValue[])() const = {&IBonusBearer::LuckVal, &IBonusBearer::MoraleVal}; TBonusListPtr modifierList(new BonusList()); - if (node) + if(node) { modifierList = node->getBonuses(Selector::type(bonusType[morale])); bonusValue = (node->*getValue[morale])(); } else + { bonusValue = 0; + } int mrlt = (bonusValue>0)-(bonusValue<0); //signum: -1 - bad luck / morale, 0 - neutral, 1 - good hoverText = CGI->generaltexth->heroscrn[hoverTextBase[morale] - mrlt]; @@ -420,23 +430,22 @@ void MoraleLuckBox::set(const IBonusBearer *node) else imageName = morale ? "IMRL42" : "ILCK42"; - delete image; - image = new CAnimImage(imageName, bonusValue + 3); + image = std::make_shared(imageName, bonusValue + 3); image->moveBy(Point(pos.w/2 - image->pos.w/2, pos.h/2 - image->pos.h/2));//center icon } -MoraleLuckBox::MoraleLuckBox(bool Morale, const Rect &r, bool Small): - image(nullptr), - morale(Morale), +MoraleLuckBox::MoraleLuckBox(bool Morale, const Rect &r, bool Small) + : morale(Morale), small(Small) { bonusValue = 0; pos = r + pos; + defActions = 255-DISPOSE; } -CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool Animated) +CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool Animated) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); pos.x+=x; pos.y+=y; @@ -445,20 +454,20 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool An assert(CGI->townh->factions.size() > faction); if(Big) - bg = new CPicture(CGI->townh->factions[faction]->creatureBg130); + bg = std::make_shared(CGI->townh->factions[faction]->creatureBg130); else - bg = new CPicture(CGI->townh->factions[faction]->creatureBg120); - anim = new CCreatureAnim(0, 0, cre->animDefName, Rect()); + bg = std::make_shared(CGI->townh->factions[faction]->creatureBg120); + anim = std::make_shared(0, 0, cre->animDefName, Rect()); anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h); anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON)); - amount = new CLabel(bg->pos.w, bg->pos.h, FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE); + amount = std::make_shared(bg->pos.w, bg->pos.h, FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE); pos.w = bg->pos.w; pos.h = bg->pos.h; } -void CCreaturePic::show(SDL_Surface *to) +void CCreaturePic::show(SDL_Surface * to) { // redraw everything in a proper order bg->showAll(to); @@ -468,7 +477,7 @@ void CCreaturePic::show(SDL_Surface *to) void CCreaturePic::setAmount(int newAmount) { - if (newAmount != 0) + if(newAmount != 0) amount->setText(boost::lexical_cast(newAmount)); else amount->setText(""); diff --git a/client/widgets/MiscWidgets.h b/client/widgets/MiscWidgets.h index 0ccad2131..c5f1088d7 100644 --- a/client/widgets/MiscWidgets.h +++ b/client/widgets/MiscWidgets.h @@ -15,7 +15,6 @@ class CLabel; class CCreatureAnim; class CComponent; class CGGarrison; -class CSelectableComponent; struct InfoAboutArmy; class CArmedInstance; class IBonusBearer; @@ -40,7 +39,7 @@ public: std::string text; LRClickableAreaWText(); - LRClickableAreaWText(const Rect &Pos, const std::string &HoverText = "", const std::string &ClickText = ""); + LRClickableAreaWText(const Rect & Pos, const std::string & HoverText = "", const std::string & ClickText = ""); virtual ~LRClickableAreaWText(); void init(); @@ -51,9 +50,12 @@ public: /// base class for hero/town/garrison tooltips class CArmyTooltip : public CIntObject { - void init(const InfoAboutArmy &army); + std::shared_ptr title; + std::vector> icons; + std::vector> subtitles; + void init(const InfoAboutArmy & army); public: - CArmyTooltip(Point pos, const InfoAboutArmy &army); + CArmyTooltip(Point pos, const InfoAboutArmy & army); CArmyTooltip(Point pos, const CArmedInstance * army); }; @@ -62,9 +64,14 @@ public: /// background for tooltip: HEROQVBK class CHeroTooltip : public CArmyTooltip { - void init(const InfoAboutHero &hero); + std::shared_ptr portrait; + std::vector> labels; + std::shared_ptr morale; + std::shared_ptr luck; + + void init(const InfoAboutHero & hero); public: - CHeroTooltip(Point pos, const InfoAboutHero &hero); + CHeroTooltip(Point pos, const InfoAboutHero & hero); CHeroTooltip(Point pos, const CGHeroInstance * hero); }; @@ -73,9 +80,17 @@ public: /// background for tooltip: TOWNQVBK class CTownTooltip : public CArmyTooltip { - void init(const InfoAboutTown &town); + std::shared_ptr fort; + std::shared_ptr hall; + std::shared_ptr build; + std::shared_ptr income; + std::shared_ptr garrisonedHero; + std::shared_ptr res1; + std::shared_ptr res2; + + void init(const InfoAboutTown & town); public: - CTownTooltip(Point pos, const InfoAboutTown &town); + CTownTooltip(Point pos, const InfoAboutTown & town); CTownTooltip(Point pos, const CGTownInstance * town); }; @@ -83,22 +98,21 @@ public: class CCreaturePic : public CIntObject { private: - CPicture *bg; - CCreatureAnim *anim; //displayed animation - CLabel * amount; + std::shared_ptr bg; + std::shared_ptr anim; //displayed animation + std::shared_ptr amount; - void show(SDL_Surface *to) override; + void show(SDL_Surface * to) override; public: - CCreaturePic(int x, int y, const CCreature *cre, bool Big=true, bool Animated=true); - + CCreaturePic(int x, int y, const CCreature * cre, bool Big=true, bool Animated=true); void setAmount(int newAmount); }; /// Resource bar like that at the bottom of the adventure map screen class CMinorResDataBar : public CIntObject { + std::shared_ptr background; public: - SDL_Surface *bg; //background bitmap void show(SDL_Surface * to) override; void showAll(SDL_Surface * to) override; CMinorResDataBar(); @@ -109,8 +123,9 @@ public: class CHeroArea: public CIntObject { const CGHeroInstance * hero; -public: + std::shared_ptr portrait; +public: CHeroArea(int x, int y, const CGHeroInstance * _hero); void clickLeft(tribool down, bool previousState) override; @@ -128,7 +143,7 @@ public: virtual void clickRight(tribool down, bool previousState) override; LRClickableAreaWTextComp(const Rect &Pos = Rect(0,0,0,0), int BaseType = -1); - CComponent * createComponent() const; + std::shared_ptr createComponent() const; }; /// Opens town screen by left-clicking on it @@ -143,7 +158,7 @@ public: class MoraleLuckBox : public LRClickableAreaWTextComp { - CAnimImage *image; + std::shared_ptr image; public: bool morale; //true if morale, false if luck bool small; diff --git a/client/widgets/ObjectLists.cpp b/client/widgets/ObjectLists.cpp index 7b65aff0f..91300898b 100644 --- a/client/widgets/ObjectLists.cpp +++ b/client/widgets/ObjectLists.cpp @@ -13,53 +13,45 @@ #include "../gui/CGuiHandler.h" #include "Buttons.h" - -static void intDeleter(CIntObject* object) +CObjectList::CObjectList(CreateFunc create) + : createObject(create) { - delete object; } -CObjectList::CObjectList(CreateFunc create, DestroyFunc destroy): -createObject(create), -destroyObject(destroy) +void CObjectList::deleteItem(std::shared_ptr item) { - if (!destroyObject) - destroyObject = intDeleter; -} - -void CObjectList::deleteItem(CIntObject* item) -{ - if (!item) + if(!item) return; - removeChild(item); - destroyObject(item); + item->deactivate(); + removeChild(item.get()); } -CIntObject* CObjectList::createItem(size_t index) +std::shared_ptr CObjectList::createItem(size_t index) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - CIntObject * item = createObject(index); - if (item == nullptr) - item = new CIntObject(); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + std::shared_ptr item = createObject(index); + if(!item) + item = std::make_shared(); item->recActions = defActions; - - addChild(item); + addChild(item.get()); + item->activate(); return item; } -CTabbedInt::CTabbedInt(CreateFunc create, DestroyFunc destroy, Point position, size_t ActiveID): -CObjectList(create, destroy), -activeTab(nullptr), -activeID(ActiveID) +CTabbedInt::CTabbedInt(CreateFunc create, Point position, size_t ActiveID) + : CObjectList(create), + activeTab(nullptr), + activeID(ActiveID) { + defActions &= ~DISPOSE; pos += position; reset(); } void CTabbedInt::setActive(size_t which) { - if (which != activeID) + if(which != activeID) { activeID = which; reset(); @@ -72,30 +64,29 @@ void CTabbedInt::reset() activeTab = createItem(activeID); activeTab->moveTo(pos.topLeft()); - if (active) + if(active) redraw(); } -CIntObject * CTabbedInt::getItem() +std::shared_ptr CTabbedInt::getItem() { return activeTab; } -CListBox::CListBox(CreateFunc create, DestroyFunc destroy, Point Pos, Point ItemOffset, size_t VisibleSize, - size_t TotalSize, size_t InitialPos, int Slider, Rect SliderPos): - CObjectList(create, destroy), +CListBox::CListBox(CreateFunc create, Point Pos, Point ItemOffset, size_t VisibleSize, + size_t TotalSize, size_t InitialPos, int Slider, Rect SliderPos) + : CObjectList(create), first(InitialPos), totalSize(TotalSize), - itemOffset(ItemOffset), - slider(nullptr) + itemOffset(ItemOffset) { pos += Pos; items.resize(VisibleSize, nullptr); - if (Slider & 1) + if(Slider & 1) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - slider = new CSlider(SliderPos.topLeft(), SliderPos.w, std::bind(&CListBox::moveToPos, this, _1), + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + slider = std::make_shared(SliderPos.topLeft(), SliderPos.w, std::bind(&CListBox::moveToPos, this, _1), VisibleSize, TotalSize, InitialPos, Slider & 2, Slider & 4 ? CSlider::BLUE : CSlider::BROWN); } reset(); @@ -142,22 +133,22 @@ size_t CListBox::size() return totalSize; } -CIntObject * CListBox::getItem(size_t which) +std::shared_ptr CListBox::getItem(size_t which) { - if (which < first || which > first + items.size() || which > totalSize) - return nullptr; + if(which < first || which > first + items.size() || which > totalSize) + return std::shared_ptr(); size_t i=first; for (auto iter = items.begin(); iter != items.end(); iter++, i++) if( i == which) return *iter; - return nullptr; + return std::shared_ptr(); } -size_t CListBox::getIndexOf(CIntObject *item) +size_t CListBox::getIndexOf(std::shared_ptr item) { size_t i=first; - for (auto iter = items.begin(); iter != items.end(); iter++, i++) + for(auto iter = items.begin(); iter != items.end(); iter++, i++) if(*iter == item) return i; return size_t(-1); @@ -166,7 +157,7 @@ size_t CListBox::getIndexOf(CIntObject *item) void CListBox::scrollTo(size_t which) { //scroll up - if (first > which) + if(first > which) moveToPos(which); //scroll down else if (first + items.size() <= which && which < totalSize) @@ -177,7 +168,7 @@ void CListBox::moveToPos(size_t which) { //Calculate new position size_t maxPossible; - if (totalSize > items.size()) + if(totalSize > items.size()) maxPossible = totalSize - items.size(); else maxPossible = 0; @@ -185,11 +176,15 @@ void CListBox::moveToPos(size_t which) size_t newPos = std::min(which, maxPossible); //If move distance is 1 (most of calls from Slider) - use faster shifts instead of resetting all items - if (first - newPos == 1) + if(first - newPos == 1) + { moveToPrev(); - else if (newPos - first == 1) + } + else if(newPos - first == 1) + { moveToNext(); - else if (newPos != first) + } + else if(newPos != first) { first = newPos; reset(); @@ -199,7 +194,7 @@ void CListBox::moveToPos(size_t which) void CListBox::moveToNext() { //Remove front item and insert new one to end - if (first + items.size() < totalSize) + if(first + items.size() < totalSize) { first++; deleteItem(items.front()); @@ -212,7 +207,7 @@ void CListBox::moveToNext() void CListBox::moveToPrev() { //Remove last item and insert new one at start - if (first) + if(first) { first--; deleteItem(items.back()); @@ -227,7 +222,7 @@ size_t CListBox::getPos() return first; } -const std::list &CListBox::getItems() +const std::list> & CListBox::getItems() { return items; } diff --git a/client/widgets/ObjectLists.h b/client/widgets/ObjectLists.h index 9b42fa36d..dfc490d58 100644 --- a/client/widgets/ObjectLists.h +++ b/client/widgets/ObjectLists.h @@ -22,52 +22,50 @@ class CAnimation; class CObjectList : public CIntObject { public: - typedef std::function CreateFunc; - typedef std::function DestroyFunc; + typedef std::function(size_t)> CreateFunc; private: CreateFunc createObject; - DestroyFunc destroyObject; protected: //Internal methods for safe creation of items (Children capturing and activation/deactivation if needed) - void deleteItem(CIntObject* item); - CIntObject* createItem(size_t index); + void deleteItem(std::shared_ptr item); + std::shared_ptr createItem(size_t index); - CObjectList(CreateFunc create, DestroyFunc destroy = DestroyFunc());//Protected constructor + CObjectList(CreateFunc create); }; /// Window element with multiple tabs class CTabbedInt : public CObjectList { private: - CIntObject * activeTab; + std::shared_ptr activeTab; size_t activeID; public: //CreateFunc, DestroyFunc - see CObjectList //Pos - position of object, all tabs will be moved to this position //ActiveID - ID of initially active tab - CTabbedInt(CreateFunc create, DestroyFunc destroy = DestroyFunc(), Point position=Point(), size_t ActiveID=0); + CTabbedInt(CreateFunc create, Point position=Point(), size_t ActiveID=0); void setActive(size_t which); //recreate active tab void reset(); //return currently active item - CIntObject * getItem(); + std::shared_ptr getItem(); }; /// List of IntObjects with optional slider class CListBox : public CObjectList { private: - std::list< CIntObject* > items; + std::list> items; size_t first; size_t totalSize; Point itemOffset; - CSlider * slider; + std::shared_ptr slider; void updatePositions(); public: @@ -78,7 +76,7 @@ public: //TotalSize //Slider - slider style, bit field: 1 = present(disabled), 2=horisontal(vertical), 4=blue(brown) //SliderPos - position of slider, if present - CListBox(CreateFunc create, DestroyFunc destroy, Point Pos, Point ItemOffset, size_t VisibleSize, + CListBox(CreateFunc create, Point Pos, Point ItemOffset, size_t VisibleSize, size_t TotalSize, size_t InitialPos=0, int Slider=0, Rect SliderPos=Rect() ); //recreate all visible items @@ -89,13 +87,13 @@ public: size_t size(); //return item with index which or null if not present - CIntObject * getItem(size_t which); + std::shared_ptr getItem(size_t which); //return currently active items - const std::list< CIntObject * > & getItems(); + const std::list> & getItems(); //get index of this item. -1 if not found - size_t getIndexOf(CIntObject * item); + size_t getIndexOf(std::shared_ptr item); //scroll list to make item which visible void scrollTo(size_t which); diff --git a/client/widgets/TextControls.cpp b/client/widgets/TextControls.cpp index 676105426..7646f9392 100644 --- a/client/widgets/TextControls.cpp +++ b/client/widgets/TextControls.cpp @@ -36,17 +36,16 @@ void CLabel::showAll(SDL_Surface * to) } -CLabel::CLabel(int x, int y, EFonts Font, EAlignment Align, const SDL_Color &Color, const std::string &Text) -:CTextContainer(Align, Font, Color), text(Text) +CLabel::CLabel(int x, int y, EFonts Font, EAlignment Align, const SDL_Color & Color, const std::string & Text) + : CTextContainer(Align, Font, Color), text(Text) { type |= REDRAW_PARENT; autoRedraw = true; pos.x += x; pos.y += y; pos.w = pos.h = 0; - bg = nullptr; - if (alignment == TOPLEFT) // causes issues for MIDDLE + if(alignment == TOPLEFT) // causes issues for MIDDLE { pos.w = graphics->fonts[font]->getStringWidth(visibleText().c_str()); pos.h = graphics->fonts[font]->getLineHeight(); @@ -73,7 +72,7 @@ void CLabel::setText(const std::string &Txt) text = Txt; if(autoRedraw) { - if(bg || !parent) + if(background || !parent) redraw(); else parent->redraw(); @@ -85,7 +84,7 @@ void CLabel::setColor(const SDL_Color & Color) color = Color; if(autoRedraw) { - if(bg || !parent) + if(background || !parent) redraw(); else parent->redraw(); @@ -259,14 +258,16 @@ Rect CMultiLineLabel::getTextLocation() return Rect(); } -CLabelGroup::CLabelGroup(EFonts Font, EAlignment Align, const SDL_Color &Color): - font(Font), align(Align), color(Color) -{} +CLabelGroup::CLabelGroup(EFonts Font, EAlignment Align, const SDL_Color & Color) + : font(Font), align(Align), color(Color) +{ + defActions = 255-DISPOSE; +} void CLabelGroup::add(int x, int y, const std::string &text) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - labels.push_back(new CLabel(x, y, font, align, color, text)); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + labels.push_back(std::make_shared(x, y, font, align, color, text)); } size_t CLabelGroup::currentSize() const @@ -278,8 +279,8 @@ CTextBox::CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts F sliderStyle(SliderStyle), slider(nullptr) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - label = new CMultiLineLabel(rect, Font, Align, Color); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + label = std::make_shared(rect, Font, Align, Color); type |= REDRAW_PARENT; pos.x += rect.x; @@ -302,9 +303,8 @@ void CTextBox::resize(Point newSize) pos.h = newSize.y; label->pos.w = pos.w; label->pos.h = pos.h; - if (slider) - vstd::clear_pointer(slider); // will be recreated if needed later + slider.reset(); setText(label->getText()); // force refresh } @@ -315,7 +315,7 @@ void CTextBox::setText(const std::string &text) if(label->textSize.y <= label->pos.h && slider) { // slider is no longer needed - vstd::clear_pointer(slider); + slider.reset(); } else if(slider) { @@ -330,8 +330,8 @@ void CTextBox::setText(const std::string &text) label->pos.w = pos.w - 32; label->setText(text); - OBJ_CONSTRUCTION_CAPTURING_ALL; - slider = new CSlider(Point(pos.w - 32, 0), pos.h, std::bind(&CTextBox::sliderMoved, this, _1), + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + slider = std::make_shared(Point(pos.w - 32, 0), pos.h, std::bind(&CTextBox::sliderMoved, this, _1), label->pos.h, label->textSize.y, 0, false, CSlider::EStyle(sliderStyle)); slider->setScrollStep(graphics->fonts[label->font]->getLineHeight()); } @@ -348,28 +348,28 @@ void CGStatusBar::clear() setText(""); } -CGStatusBar::CGStatusBar(CPicture *BG, EFonts Font, EAlignment Align, const SDL_Color &Color) -: CLabel(BG->pos.x, BG->pos.y, Font, Align, Color, "") +CGStatusBar::CGStatusBar(std::shared_ptr background_, EFonts Font, EAlignment Align, const SDL_Color & Color) + : CLabel(background_->pos.x, background_->pos.y, Font, Align, Color, "") { init(); - bg = BG; - addChild(bg); - pos = bg->pos; + background = background_; + addChild(background.get()); + pos = background->pos; getBorderSize(); textLock = false; } CGStatusBar::CGStatusBar(int x, int y, std::string name, int maxw) -: CLabel(x, y, FONT_SMALL, CENTER) + : CLabel(x, y, FONT_SMALL, CENTER) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); init(); - bg = new CPicture(name); - pos = bg->pos; + background = std::make_shared(name); + pos = background->pos; if((unsigned int)maxw < pos.w) { vstd::amin(pos.w, maxw); - bg->srcRect = new Rect(0, 0, maxw, pos.h); + background->srcRect = new Rect(0, 0, maxw, pos.h); } textLock = false; } @@ -410,8 +410,8 @@ void CGStatusBar::lock(bool shouldLock) textLock = shouldLock; } -CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList &CB): - CLabel(Pos.x, Pos.y, font, CENTER), +CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList &CB) + : CLabel(Pos.x, Pos.y, font, CENTER), cb(CB) { type |= REDRAW_PARENT; @@ -419,38 +419,38 @@ CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList &CB ) -:cb(CB) +CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const std::string & bgName, const CFunctionList & CB) + :cb(CB) { focus = false; pos += Pos; captureAllKeys = true; OBJ_CONSTRUCTION; - bg = new CPicture(bgName, bgOffset.x, bgOffset.y); + background = std::make_shared(bgName, bgOffset.x, bgOffset.y); addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); giveFocus(); } -CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf) +CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf) { focus = false; pos += Pos; captureAllKeys = true; OBJ_CONSTRUCTION; - bg = new CPicture(Pos, 0, true); + background = std::make_shared(Pos, 0, true); Rect hlp = Pos; if(srf) - CSDL_Ext::blitSurface(srf, &hlp, *bg, nullptr); + CSDL_Ext::blitSurface(srf, &hlp, *background.get(), nullptr); else - SDL_FillRect(*bg, nullptr, 0); - pos.w = bg->pos.w; - pos.h = bg->pos.h; - bg->pos = pos; + SDL_FillRect(*background.get(), nullptr, 0); + pos.w = background->pos.w; + pos.h = background->pos.h; + background->pos = pos; addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); giveFocus(); } diff --git a/client/widgets/TextControls.h b/client/widgets/TextControls.h index b3b5b1a78..fee051a23 100644 --- a/client/widgets/TextControls.h +++ b/client/widgets/TextControls.h @@ -40,7 +40,7 @@ protected: Point getBorderSize() override; virtual std::string visibleText(); - CPicture *bg; + std::shared_ptr background; public: std::string text; @@ -60,7 +60,7 @@ public: /// Small helper class to manage group of similar labels class CLabelGroup : public CIntObject { - std::list labels; + std::vector> labels; EFonts font; EAlignment align; SDL_Color color; @@ -103,13 +103,13 @@ class CTextBox : public CIntObject { int sliderStyle; public: - CMultiLineLabel * label; - CSlider *slider; + std::shared_ptr label; + std::shared_ptr slider; - CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE); + CTextBox(std::string Text, const Rect & rect, int SliderStyle, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color & Color = Colors::WHITE); void resize(Point newSize); - void setText(const std::string &Txt); + void setText(const std::string & Txt); void sliderMoved(int to); }; @@ -119,19 +119,18 @@ class CGStatusBar : public CLabel bool textLock; //Used for blocking changes to the text void init(); - CGStatusBar *oldStatusBar; + CGStatusBar * oldStatusBar; protected: Point getBorderSize() override; public: - void clear();//clears statusbar and refreshes void setText(const std::string & Text) override; //prints text and refreshes statusbar void show(SDL_Surface * to) override; //shows statusbar (with current text) - CGStatusBar(CPicture *BG, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::WHITE); //given CPicture will be captured by created sbar and it's pos will be used as pos for sbar - CGStatusBar(int x, int y, std::string name, int maxw=-1); + CGStatusBar(std::shared_ptr background_, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color & Color = Colors::WHITE); + CGStatusBar(int x, int y, std::string name, int maxw = -1); ~CGStatusBar(); void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called @@ -180,7 +179,7 @@ public: void clickLeft(tribool down, bool previousState) override; void keyPressed(const SDL_KeyboardEvent & key) override; bool captureThisEvent(const SDL_KeyboardEvent & key) override; - + void textInputed(const SDL_TextInputEvent & event) override; void textEdited(const SDL_TextEditingEvent & event) override; diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index 913d049af..fdb6a580f 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -90,7 +90,7 @@ static void setScrollingCursor(ui8 direction) CTerrainRect::CTerrainRect() : fadeSurface(nullptr), lastRedrawStatus(EMapAnimRedrawStatus::OK), - fadeAnim(new CFadeAnimation()), + fadeAnim(std::make_shared()), curHoveredTile(-1,-1,-1), currentPath(nullptr) { @@ -106,9 +106,8 @@ CTerrainRect::CTerrainRect() CTerrainRect::~CTerrainRect() { - if (fadeSurface) + if(fadeSurface) SDL_FreeSurface(fadeSurface); - delete fadeAnim; } void CTerrainRect::deactivate() @@ -475,12 +474,16 @@ void CResDataBar::clickRight(tribool down, bool previousState) { } -CResDataBar::CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist) +CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist) { - bg = BitmapHandler::loadBitmap(defname); - CSDL_Ext::setDefaultColorKey(bg); - graphics->blueToPlayersAdv(bg,LOCPLINT->playerID); - pos = genRect(bg->h, bg->w, pos.x+x, pos.y+y); + pos.x += x; + pos.y += y; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background = std::make_shared(defname, 0, 0); + background->colorize(LOCPLINT->playerID); + + pos.w = background->bg->w; + pos.h = background->bg->h; txtpos.resize(8); for (int i = 0; i < 8 ; i++) @@ -496,10 +499,15 @@ CResDataBar::CResDataBar(const std::string &defname, int x, int y, int offx, int CResDataBar::CResDataBar() { - bg = BitmapHandler::loadBitmap(ADVOPT.resdatabarG); - CSDL_Ext::setDefaultColorKey(bg); - graphics->blueToPlayersAdv(bg,LOCPLINT->playerID); - pos = genRect(bg->h,bg->w,ADVOPT.resdatabarX,ADVOPT.resdatabarY); + pos.x += ADVOPT.resdatabarX; + pos.y += ADVOPT.resdatabarY; + + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background = std::make_shared(ADVOPT.resdatabarG, 0, 0); + background->colorize(LOCPLINT->playerID); + + pos.w = background->bg->w; + pos.h = background->bg->h; txtpos.resize(8); for (int i = 0; i < 8 ; i++) @@ -512,13 +520,11 @@ CResDataBar::CResDataBar() + ": %s, " + CGI->generaltexth->allTexts[64] + ": %s"; } -CResDataBar::~CResDataBar() -{ - SDL_FreeSurface(bg); -} +CResDataBar::~CResDataBar() = default; + void CResDataBar::draw(SDL_Surface * to) { - blitAt(bg,pos.x,pos.y,to); + //TODO: all this should be labels, but they require proper text update on change for (auto i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1)) { std::string text = boost::lexical_cast(LOCPLINT->cb->getResourceAmount(i)); @@ -541,6 +547,7 @@ void CResDataBar::show(SDL_Surface * to) void CResDataBar::showAll(SDL_Surface * to) { + CIntObject::showAll(to); draw(to); } @@ -552,13 +559,13 @@ CAdvMapInt::CAdvMapInt(): heroList(ADVOPT.hlistSize, Point(ADVOPT.hlistX, ADVOPT.hlistY), ADVOPT.hlistAU, ADVOPT.hlistAD), townList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD), infoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192)), state(NA), - spellBeingCasted(nullptr), position(int3(0, 0, 0)), selection(nullptr), - updateScreen(false), anim(0), animValHitCount(0), heroAnim(0), heroAnimValHitCount(0), + spellBeingCasted(nullptr), position(int3(0, 0, 0)), selection(nullptr), + updateScreen(false), anim(0), animValHitCount(0), heroAnim(0), heroAnimValHitCount(0), activeMapPanel(nullptr), duringAITurn(false), scrollingDir(0), scrollingState(false), swipeEnabled(settings["general"]["swipe"].Bool()), swipeMovementRequested(false), swipeTargetPosition(int3(-1, -1, -1)) { - adventureInt = this; + adventureInt = this; pos.x = pos.y = 0; pos.w = screen->w; pos.h = screen->h; @@ -580,18 +587,17 @@ CAdvMapInt::CAdvMapInt(): } worldViewIcons = std::make_shared("VwSymbol");//todo: customize with ADVOPT - //preload all for faster map drawing - worldViewIcons->load();//TODO: make special method in CAnimation fro that + worldViewIcons->preload(); - for (int g=0; g(ADVOPT.gemG[g], 0, 0, ADVOPT.gemX[g], ADVOPT.gemY[g])); } - auto makeButton = [&] (int textID, std::function callback, config::ButtonInfo info, int key) -> CButton * + auto makeButton = [&](int textID, std::function callback, config::ButtonInfo info, int key) -> std::shared_ptr { - auto button = new CButton(Point(info.x, info.y), info.defName, CGI->generaltexth->zelp[textID], callback, key, info.playerColoured); - for (auto image : info.additionalDefs) + auto button = std::make_shared(Point(info.x, info.y), info.defName, CGI->generaltexth->zelp[textID], callback, key, info.playerColoured); + for(auto image : info.additionalDefs) button->addImage(image); return button; }; @@ -609,9 +615,9 @@ CAdvMapInt::CAdvMapInt(): int panelSpaceBottom = screen->h - resdatabar.pos.h - 4; - panelMain = new CAdvMapPanel(nullptr, Point(0, 0)); + panelMain = std::make_shared(nullptr, Point(0, 0)); // TODO correct drawing position - panelWorldView = new CAdvMapWorldViewPanel(worldViewIcons, bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID); + panelWorldView = std::make_shared(worldViewIcons, bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID); panelMain->addChildColorableButton(kingOverview); panelMain->addChildColorableButton(underground); @@ -640,7 +646,7 @@ CAdvMapInt::CAdvMapInt(): worldViewPuzzleConfig.y = 343 + 195; worldViewPuzzleConfig.playerColoured = false; panelWorldView->addChildToPanel( // no help text for this one - new CButton(Point(worldViewPuzzleConfig.x, worldViewPuzzleConfig.y), worldViewPuzzleConfig.defName, std::pair(), + std::make_shared(Point(worldViewPuzzleConfig.x, worldViewPuzzleConfig.y), worldViewPuzzleConfig.defName, std::pair(), std::bind(&CPlayerInterface::showPuzzleMap,LOCPLINT), SDLK_p, worldViewPuzzleConfig.playerColoured), ACTIVATE | DEACTIVATE); config::ButtonInfo worldViewScale1xConfig = config::ButtonInfo(); @@ -684,19 +690,19 @@ CAdvMapInt::CAdvMapInt(): for (int i = 0; i < 5; ++i) { panelWorldView->addChildIcon(std::pair(i, Point(5, 58 + i * 20)), iconColorMultiplier); - panelWorldView->addChildToPanel(new CLabel(wvLeft + 45, 263 + i * 20, EFonts::FONT_SMALL, EAlignment::TOPLEFT, + panelWorldView->addChildToPanel(std::make_shared(wvLeft + 45, 263 + i * 20, EFonts::FONT_SMALL, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[612 + i])); } for (int i = 0; i < 7; ++i) { panelWorldView->addChildIcon(std::pair(i + 5, Point(5, 182 + i * 20)), iconColorMultiplier); panelWorldView->addChildIcon(std::pair(i + 12, Point(160, 182 + i * 20)), iconColorMultiplier); - panelWorldView->addChildToPanel(new CLabel(wvLeft + 45, 387 + i * 20, EFonts::FONT_SMALL, EAlignment::TOPLEFT, + panelWorldView->addChildToPanel(std::make_shared(wvLeft + 45, 387 + i * 20, EFonts::FONT_SMALL, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[619 + i])); } - panelWorldView->addChildToPanel(new CLabel(wvLeft + 5, 367, EFonts::FONT_SMALL, EAlignment::TOPLEFT, + panelWorldView->addChildToPanel(std::make_shared(wvLeft + 5, 367, EFonts::FONT_SMALL, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[617])); - panelWorldView->addChildToPanel(new CLabel(wvLeft + 185, 387, EFonts::FONT_SMALL, EAlignment::BOTTOMRIGHT, + panelWorldView->addChildToPanel(std::make_shared(wvLeft + 45, 367, EFonts::FONT_SMALL, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[618])); activeMapPanel = panelMain; @@ -713,8 +719,6 @@ CAdvMapInt::CAdvMapInt(): CAdvMapInt::~CAdvMapInt() { SDL_FreeSurface(bg); - - worldViewIcons->unload(); } void CAdvMapInt::fshowOverview() @@ -846,7 +850,7 @@ void CAdvMapInt::fendTurn() auto path = LOCPLINT->getAndVerifyPath(hero); if(!path || path->nodes.size() < 2 || !path->nodes[path->nodes.size()-2].turns) { - LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[55], std::bind(&CAdvMapInt::endingTurn, this), 0, false); + LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[55], std::bind(&CAdvMapInt::endingTurn, this), nullptr); return; } } @@ -996,7 +1000,7 @@ void CAdvMapInt::showAll(SDL_Surface * to) show(to); - resdatabar.draw(to); + resdatabar.showAll(to); statusbar.show(to); @@ -1240,8 +1244,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) if(isActive() && LOCPLINT->ctrlPressed()) { LOCPLINT->showYesNoDialog("Are you sure you want to restart game?", - [](){ LOCPLINT->sendCustomEvent(EUserEvent::RESTART_GAME); }, - [](){}, true); + [](){ LOCPLINT->sendCustomEvent(EUserEvent::RESTART_GAME); }, nullptr); } return; case SDLK_SPACE: //space - try to revisit current object with selected hero @@ -1503,7 +1506,7 @@ void CAdvMapInt::setPlayer(PlayerColor Player) panelMain->setPlayerColor(player); panelWorldView->setPlayerColor(player); panelWorldView->recolorIcons(player, player.getNum() * 19); - graphics->blueToPlayersAdv(resdatabar.bg,player); + resdatabar.background->colorize(player); } void CAdvMapInt::startTurn() @@ -1926,24 +1929,24 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale) } } -CAdventureOptions::CAdventureOptions(): - CWindowObject(PLAYER_COLORED, "ADVOPTS") +CAdventureOptions::CAdventureOptions() + : CWindowObject(PLAYER_COLORED, "ADVOPTS") { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - viewWorld = new CButton(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v); + viewWorld = std::make_shared(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v); viewWorld->addCallback(std::bind(&CPlayerInterface::viewWorldMap, LOCPLINT)); - exit = new CButton(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN); + exit = std::make_shared(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN); exit->assignedKeys.insert(SDLK_ESCAPE); - scenInfo = new CButton(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_i); + scenInfo = std::make_shared(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_i); scenInfo->addCallback(CAdventureOptions::showScenarioInfo); - puzzle = new CButton(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_p); + puzzle = std::make_shared(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_p); puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT)); - dig = new CButton(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d); + dig = std::make_shared(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d); if(const CGHeroInstance *h = adventureInt->curHero()) dig->addCallback(std::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h)); else diff --git a/client/windows/CAdvmapInterface.h b/client/windows/CAdvmapInterface.h index 13b766b2e..72dfbc173 100644 --- a/client/windows/CAdvmapInterface.h +++ b/client/windows/CAdvmapInterface.h @@ -38,23 +38,27 @@ enum class EAdvMapMode WORLD_VIEW }; -/// Adventure options dialogue where you can view the world, dig, play the replay of the last turn,... +/// Adventure options dialog where you can view the world, dig, play the replay of the last turn,... class CAdventureOptions : public CWindowObject { public: - CButton *exit, *viewWorld, *puzzle, *dig, *scenInfo/*, *replay*/; + std::shared_ptr exit; + std::shared_ptr viewWorld; + std::shared_ptr puzzle; + std::shared_ptr dig; + std::shared_ptr scenInfo; + /*std::shared_ptr replay*/ CAdventureOptions(); static void showScenarioInfo(); }; /// Holds information about which tiles of the terrain are shown/not shown at the screen -class CTerrainRect - : public CIntObject +class CTerrainRect : public CIntObject { SDL_Surface * fadeSurface; EMapAnimRedrawStatus lastRedrawStatus; - CFadeAnimation * fadeAnim; + std::shared_ptr fadeAnim; int3 swipeInitialMapPos; int3 swipeInitialRealPos; @@ -69,10 +73,10 @@ public: int tilesw, tilesh; //width and height of terrain to blit in tiles int3 curHoveredTile; int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels) + CGPath * currentPath; CTerrainRect(); virtual ~CTerrainRect(); - CGPath * currentPath; void deactivate() override; void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; @@ -90,7 +94,6 @@ public: /// animates view by caching current surface and crossfading it with normal screen void fadeFromCurrentView(); bool needsAnimUpdate(); - }; /// Resources bar which shows information about how many gold, crystals,... you have @@ -98,7 +101,8 @@ public: class CResDataBar : public CIntObject { public: - SDL_Surface * bg; + std::shared_ptr background; + std::vector > txtpos; std::string datetext; @@ -162,22 +166,22 @@ public: SDL_Surface * bg; SDL_Surface * bgWorldView; - std::vector gems; + std::vector> gems; CMinimap minimap; CGStatusBar statusbar; - CButton * kingOverview; - CButton * underground; - CButton * questlog; - CButton * sleepWake; - CButton * moveHero; - CButton * spellbook; - CButton * advOptions; - CButton * sysOptions; - CButton * nextHero; - CButton * endTurn; + std::shared_ptr kingOverview; + std::shared_ptr underground; + std::shared_ptr questlog; + std::shared_ptr sleepWake; + std::shared_ptr moveHero; + std::shared_ptr spellbook; + std::shared_ptr advOptions; + std::shared_ptr sysOptions; + std::shared_ptr nextHero; + std::shared_ptr endTurn; - CButton * worldViewUnderground; + std::shared_ptr worldViewUnderground; CTerrainRect terrain; //visible terrain CResDataBar resdatabar; @@ -185,9 +189,9 @@ public: CTownList townList; CInfoBar infoBar; - CAdvMapPanel *panelMain; // panel that holds all right-side buttons in normal view - CAdvMapWorldViewPanel *panelWorldView; // panel that holds all buttons and other ui in world view - CAdvMapPanel *activeMapPanel; // currently active panel (either main or world view, depending on current mode) + std::shared_ptr panelMain; // panel that holds all right-side buttons in normal view + std::shared_ptr panelWorldView; // panel that holds all buttons and other ui in world view + std::shared_ptr activeMapPanel; // currently active panel (either main or world view, depending on current mode) std::shared_ptr worldViewIcons;// images for world view overlay diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 77851a3b5..403f715e0 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -40,19 +40,8 @@ #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGTownInstance.h" -const CBuilding * CBuildingRect::getBuilding() -{ - if (!str->building) - return nullptr; - - if (str->hiddenUpgrade) // hidden upgrades, e.g. hordes - return base (dwelling for hordes) - return town->town->buildings.at(str->building->getBase()); - - return str->building; -} - -CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str) - :CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE | CShowableAnim::USE_RLE), +CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town, const CStructure * Str) + : CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE | CShowableAnim::USE_RLE), parent(Par), town(Town), str(Str), @@ -63,12 +52,12 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, pos.x += str->pos.x; pos.y += str->pos.y; - if (!str->borderName.empty()) + if(!str->borderName.empty()) border = BitmapHandler::loadBitmap(str->borderName, true); else border = nullptr; - if (!str->areaName.empty()) + if(!str->areaName.empty()) area = BitmapHandler::loadBitmap(str->areaName); else area = nullptr; @@ -76,8 +65,21 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, CBuildingRect::~CBuildingRect() { - SDL_FreeSurface(border); - SDL_FreeSurface(area); + if(border) + SDL_FreeSurface(border); + if(area) + SDL_FreeSurface(area); +} + +const CBuilding * CBuildingRect::getBuilding() +{ + if (!str->building) + return nullptr; + + if (str->hiddenUpgrade) // hidden upgrades, e.g. hordes - return base (dwelling for hordes) + return town->town->buildings.at(str->building->getBase()); + + return str->building; } bool CBuildingRect::operator<(const CBuildingRect & p2) const @@ -124,7 +126,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState) if (bid < BuildingID::DWELL_FIRST) { CRClickPopup::createAndPush(CInfoWindow::genText(bld->Name(), bld->Description()), - new CComponent(CComponent::building, bld->town->faction->index, bld->bid)); + std::make_shared(CComponent::building, bld->town->faction->index, bld->bid)); } else { @@ -134,7 +136,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState) } } -SDL_Color multiplyColors (const SDL_Color &b, const SDL_Color &a, double f) +SDL_Color multiplyColors(const SDL_Color & b, const SDL_Color & a, double f) { SDL_Color ret; ret.r = a.r*f + b.r*(1-f); @@ -153,7 +155,7 @@ void CBuildingRect::show(SDL_Surface * to) const ui32 S3_YELLOW_B= 48; //0.5 sec border glows from yellow to normal const ui32 BUILDED = 80; // 1 sec delay, nothing happens - if (stateCounter < S1_TRANSP) + if(stateCounter < S1_TRANSP) { setAlpha(255*stateCounter/stageDelay); CShowableAnim::show(to); @@ -164,15 +166,15 @@ void CBuildingRect::show(SDL_Surface * to) CShowableAnim::show(to); } - if (border && stateCounter > S1_TRANSP) + if(border && stateCounter > S1_TRANSP) { - if (stateCounter == BUILDED) + if(stateCounter == BUILDED) { - if (parent->selectedBuilding == this) + if(parent->selectedBuilding == this) blitAtLoc(border,0,0,to); return; } - if (border->format->palette != nullptr) + if(border->format->palette != nullptr) { // key colors in glowing border SDL_Color c1 = {200, 200, 200, 255}; @@ -192,11 +194,11 @@ void CBuildingRect::show(SDL_Surface * to) newColor = oldColor; SDL_SetColors(border, &newColor, colorID, 1); - blitAtLoc(border,0,0,to); + blitAtLoc(border, 0, 0, to); SDL_SetColors(border, &oldColor, colorID, 1); } } - if (stateCounter < BUILDED) + if(stateCounter < BUILDED) stateCounter++; } @@ -259,26 +261,27 @@ void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent) } } -CDwellingInfoBox::CDwellingInfoBox(int centerX, int centerY, const CGTownInstance *Town, int level): -CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "CRTOINFO", Point(centerX, centerY)) +CDwellingInfoBox::CDwellingInfoBox(int centerX, int centerY, const CGTownInstance * Town, int level) + : CWindowObject(RCLICK_POPUP, "CRTOINFO", Point(centerX, centerY)) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background->colorize(Town->tempOwner); const CCreature * creature = CGI->creh->creatures.at(Town->creatures.at(level).second.back()); - title = new CLabel(80, 30, FONT_SMALL, CENTER, Colors::WHITE, creature->namePl); - animation = new CCreaturePic(30, 44, creature, true, true); + title = std::make_shared(80, 30, FONT_SMALL, CENTER, Colors::WHITE, creature->namePl); + animation = std::make_shared(30, 44, creature, true, true); std::string text = boost::lexical_cast(Town->creatures.at(level).first); - available = new CLabel(80,190, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[217] + text); - costPerTroop = new CLabel(80, 227, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[346]); + available = std::make_shared(80,190, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[217] + text); + costPerTroop = std::make_shared(80, 227, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[346]); for(int i = 0; icost[i]) { - resPicture.push_back(new CAnimImage("RESOURCE", i, 0, 0, 0)); - resAmount.push_back(new CLabel(0,0, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast(creature->cost[i]))); + resPicture.push_back(std::make_shared("RESOURCE", i, 0, 0, 0)); + resAmount.push_back(std::make_shared(0,0, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast(creature->cost[i]))); } } @@ -292,23 +295,52 @@ CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "CRTOINFO", Point(centerX, centerY) } } -void CHeroGSlot::hover (bool on) +CDwellingInfoBox::~CDwellingInfoBox() = default; + +CHeroGSlot::CHeroGSlot(int x, int y, int updown, const CGHeroInstance * h, HeroSlots * Owner) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + owner = Owner; + pos.x += x; + pos.y += y; + pos.w = 58; + pos.h = 64; + upg = updown; + + portrait = std::make_shared("PortraitsLarge", 0, 0, 0, 0); + portrait->visible = false; + + flag = std::make_shared("CREST58", 0, 0, 0, 0); + flag->visible = false; + + selection = std::make_shared("TWCRPORT", 1, 0); + selection->visible = false; + + set(h); + + addUsedEvents(LCLICK | RCLICK | HOVER); +} + +CHeroGSlot::~CHeroGSlot() = default; + +void CHeroGSlot::hover(bool on) { if(!on) { GH.statusbar->clear(); return; } - CHeroGSlot *other = upg ? owner->garrisonedHero : owner->visitingHero; + std::shared_ptr other = upg ? owner->garrisonedHero : owner->visitingHero; std::string temp; if(hero) { - if(selection)//view NNN + if(isSelected())//view NNN { temp = CGI->generaltexth->tcommands[4]; boost::algorithm::replace_first(temp,"%s",hero->name); } - else if(other->hero && other->selection)//exchange + else if(other->hero && other->isSelected())//exchange { temp = CGI->generaltexth->tcommands[7]; boost::algorithm::replace_first(temp,"%s",hero->name); @@ -330,7 +362,7 @@ void CHeroGSlot::hover (bool on) } else //we are empty slot { - if(other->selection && other->hero) //move NNNN + if(other->isSelected() && other->hero) //move NNNN { temp = CGI->generaltexth->tcommands[6]; boost::algorithm::replace_first(temp,"%s",other->hero->name); @@ -346,18 +378,18 @@ void CHeroGSlot::hover (bool on) void CHeroGSlot::clickLeft(tribool down, bool previousState) { - CHeroGSlot *other = upg ? owner->garrisonedHero : owner->visitingHero; + std::shared_ptr other = upg ? owner->garrisonedHero : owner->visitingHero; if(!down) { owner->garr->setSplittingMode(false); owner->garr->selectSlot(nullptr); - if(hero && selection) + if(hero && isSelected()) { setHighlight(false); LOCPLINT->openHeroWindow(hero); } - else if(other->hero && other->selection) + else if(other->hero && other->isSelected()) { bool allow = true; if(upg) //moving hero out of town - check if it is allowed @@ -366,12 +398,12 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState) { std::string tmp = CGI->generaltexth->allTexts[18]; //You already have %d adventuring heroes under your command. boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast(LOCPLINT->cb->howManyHeroes(false))); - LOCPLINT->showInfoDialog(tmp,std::vector(), soundBase::sound_todo); + LOCPLINT->showInfoDialog(tmp, std::vector>(), soundBase::sound_todo); allow = false; } else if(!other->hero->stacksCount()) //hero has no creatures - strange, but if we have appropriate error message... { - LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[19],std::vector(), soundBase::sound_todo); //This hero has no creatures. A hero must have creatures before he can brave the dangers of the countryside. + LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[19], std::vector>(), soundBase::sound_todo); //This hero has no creatures. A hero must have creatures before he can brave the dangers of the countryside. allow = false; } } @@ -391,7 +423,10 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState) owner->garr->selectSlot(nullptr); showAll(screen2); } - hover(false);hover(true); //refresh statusbar + + //refresh statusbar + hover(false); + hover(true); } } @@ -405,35 +440,18 @@ void CHeroGSlot::clickRight(tribool down, bool previousState) void CHeroGSlot::deactivate() { - vstd::clear_pointer(selection); + selection->visible = false; CIntObject::deactivate(); } -CHeroGSlot::CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, HeroSlots * Owner) +bool CHeroGSlot::isSelected() const { - owner = Owner; - pos.x += x; - pos.y += y; - pos.w = 58; - pos.h = 64; - upg = updown; - selection = nullptr; - image = nullptr; - set(h); - - addUsedEvents(LCLICK | RCLICK | HOVER); + return selection->visible; } -CHeroGSlot::~CHeroGSlot() +void CHeroGSlot::setHighlight(bool on) { -} - -void CHeroGSlot::setHighlight( bool on ) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - vstd::clear_pointer(selection); - if (on) - selection = new CAnimImage("TWCRPORT", 1, 0); + selection->visible = on; if(owner->garrisonedHero->hero && owner->visitingHero->hero) //two heroes in town { @@ -442,55 +460,101 @@ void CHeroGSlot::setHighlight( bool on ) } } -void CHeroGSlot::set(const CGHeroInstance *newHero) +void CHeroGSlot::set(const CGHeroInstance * newHero) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - if (image) - delete image; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + hero = newHero; - if (newHero) - image = new CAnimImage("PortraitsLarge", newHero->portrait, 0, 0, 0); + + selection->visible = false; + portrait->visible = false; + flag->visible = false; + + if(newHero) + { + portrait->visible = true; + portrait->setFrame(newHero->portrait); + } else if(!upg && owner->showEmpty) //up garrison - image = new CAnimImage("CREST58", LOCPLINT->castleInt->town->getOwner().getNum(), 0, 0, 0); - else - image = nullptr; + { + flag->visible = true; + flag->setFrame(LOCPLINT->castleInt->town->getOwner().getNum()); + } } -template +HeroSlots::HeroSlots(const CGTownInstance * Town, Point garrPos, Point visitPos, std::shared_ptr Garrison, bool ShowEmpty): + showEmpty(ShowEmpty), + town(Town), + garr(Garrison) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + garrisonedHero = std::make_shared(garrPos.x, garrPos.y, 0, town->garrisonHero, this); + visitingHero = std::make_shared(visitPos.x, visitPos.y, 1, town->visitingHero, this); +} + +HeroSlots::~HeroSlots() = default; + +void HeroSlots::update() +{ + garrisonedHero->set(town->garrisonHero); + visitingHero->set(town->visitingHero); +} + +void HeroSlots::splitClicked() +{ + if(!!town->visitingHero && town->garrisonHero && (visitingHero->isSelected() || garrisonedHero->isSelected())) + { + LOCPLINT->heroExchangeStarted(town->visitingHero->id, town->garrisonHero->id, QueryID(-1)); + } +} + +void HeroSlots::swapArmies() +{ + if(!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies: town army => hero army + { + if(!town->visitingHero->canBeMergedWith(*town)) + { + LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[275], std::vector>(), soundBase::sound_todo); + return; + } + } + LOCPLINT->cb->swapGarrisonHero(town); +} + + +template class SORTHELP { public: - bool operator () - (const ptr *a , - const ptr *b) + bool operator() (const std::shared_ptr a, const std::shared_ptr b) { return (*a)<(*b); } }; SORTHELP buildSorter; -SORTHELP structSorter; CCastleBuildings::CCastleBuildings(const CGTownInstance* Town): town(Town), selectedBuilding(nullptr) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - background = new CPicture(town->town->clientInfo.townBackground); + background = std::make_shared(town->town->clientInfo.townBackground); pos.w = background->pos.w; pos.h = background->pos.h; recreate(); } +CCastleBuildings::~CCastleBuildings() = default; + void CCastleBuildings::recreate() { selectedBuilding = nullptr; - OBJ_CONSTRUCTION_CAPTURING_ALL; - //clear existing buildings - for(auto build : buildings) - delete build; + //TODO: remove show[all] method and try UPDATE+SHOWALL + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(ACTIVATE+SHARE_POS); + buildings.clear(); groups.clear(); @@ -513,12 +577,12 @@ void CCastleBuildings::recreate() for(const CStructure * structure : town->town->clientInfo.structures) { - if (!structure->building) + if(!structure->building) { - buildings.push_back(new CBuildingRect(this, town, structure)); + buildings.push_back(std::make_shared(this, town, structure)); continue; } - if (vstd::contains(buildingsCopy, structure->building->bid)) + if(vstd::contains(buildingsCopy, structure->building->bid)) { groups[structure->building->getBase()].push_back(structure); } @@ -534,16 +598,9 @@ void CCastleBuildings::recreate() < build->getDistance(b->building->bid); }); - buildings.push_back(new CBuildingRect(this, town, toAdd)); + buildings.push_back(std::make_shared(this, town, toAdd)); } - boost::sort(buildings, [] (const CBuildingRect * a, const CBuildingRect * b) - { - return *a < *b; - }); -} - -CCastleBuildings::~CCastleBuildings() -{ + boost::sort(buildings, buildSorter); } void CCastleBuildings::addBuilding(BuildingID building) @@ -555,15 +612,15 @@ void CCastleBuildings::addBuilding(BuildingID building) auto & structures = groups.at(base); - for(CBuildingRect * rect : buildings) + for(auto buildingRect : buildings) { - if (vstd::contains(structures, rect->str)) + if(vstd::contains(structures, buildingRect->str)) { //reset animation - if (structures.size() == 1) - rect->stateCounter = 0; // transparency -> fully visible stage + if(structures.size() == 1) + buildingRect->stateCounter = 0; // transparency -> fully visible stage else - rect->stateCounter = 16; // already in fully visible stage + buildingRect->stateCounter = 16; // already in fully visible stage break; } } @@ -578,24 +635,23 @@ void CCastleBuildings::removeBuilding(BuildingID building) void CCastleBuildings::show(SDL_Surface * to) { CIntObject::show(to); - for(CBuildingRect * str : buildings) + for(auto str : buildings) str->show(to); } void CCastleBuildings::showAll(SDL_Surface * to) { CIntObject::showAll(to); - for(CBuildingRect * str : buildings) + for(auto str : buildings) str->showAll(to); } -const CGHeroInstance* CCastleBuildings::getHero() +const CGHeroInstance * CCastleBuildings::getHero() { - if (town->visitingHero) + if(town->visitingHero) return town->visitingHero; - if (town->garrisonHero) + else return town->garrisonHero; - return nullptr; } void CCastleBuildings::buildingClicked(BuildingID building) @@ -759,10 +815,8 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID) void CCastleBuildings::enterBuilding(BuildingID building) { - std::vector comps(1, new CComponent(CComponent::building, town->subID, building)); - - LOCPLINT->showInfoDialog( - town->town->buildings.find(building)->second->Description(),comps); + std::vector> comps(1, std::make_shared(CComponent::building, town->subID, building)); + LOCPLINT->showInfoDialog( town->town->buildings.find(building)->second->Description(), comps); } void CCastleBuildings::enterCastleGate() @@ -783,9 +837,9 @@ void CCastleBuildings::enterCastleGate() availableTowns.push_back(t->id.getNum());//add to the list } } - auto gateIcon = new CAnimImage(town->town->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window - GH.pushInt (new CObjectListWindow(availableTowns, gateIcon, CGI->generaltexth->jktexts[40], - CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1))); + auto gateIcon = std::make_shared(town->town->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window + GH.pushInt(new CObjectListWindow(availableTowns, gateIcon, CGI->generaltexth->jktexts[40], + CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1))); } void CCastleBuildings::enterDwelling(int level) @@ -802,7 +856,7 @@ void CCastleBuildings::enterToTheQuickRecruitmentWindow() void CCastleBuildings::enterFountain(BuildingID building) { - std::vector comps(1, new CComponent(CComponent::building,town->subID,building)); + std::vector> comps(1, std::make_shared(CComponent::building,town->subID,building)); std::string descr = town->town->buildings.find(building)->second->Description(); @@ -836,9 +890,9 @@ void CCastleBuildings::enterMagesGuild() CFunctionList onYes = [this](){ openMagesGuild(); }; CFunctionList onNo = onYes; onYes += [hero](){ LOCPLINT->cb->buyArtifact(hero, ArtifactID::SPELLBOOK); }; - std::vector components(1, new CComponent(CComponent::artifact,ArtifactID::SPELLBOOK,0)); + std::vector> components(1, std::make_shared(CComponent::artifact,ArtifactID::SPELLBOOK,0)); - LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[214], onYes, onNo, true, components); + LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[214], onYes, onNo, components); } } else @@ -856,8 +910,7 @@ void CCastleBuildings::enterTownHall() { LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[597], //Do you wish this to be the permanent home of the Grail? [&](){ LOCPLINT->cb->buildBuilding(town, BuildingID::GRAIL); }, - [&](){ openTownHall(); }, - true); + [&](){ openTownHall(); }); } else { @@ -883,48 +936,200 @@ void CCastleBuildings::openTownHall() GH.pushInt(new CHallInterface(town)); } +CCreaInfo::CCreaInfo(Point position, const CGTownInstance * Town, int Level, bool compact, bool ShowAvailable): + town(Town), + level(Level), + showAvailable(ShowAvailable) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + pos += position; + + if(town->creatures.size() <= level || town->creatures[level].second.empty()) + { + level = -1; + return;//No creature + } + addUsedEvents(LCLICK | RCLICK | HOVER); + + ui32 creatureID = town->creatures[level].second.back(); + creature = CGI->creh->creatures[creatureID]; + + picture = std::make_shared("CPRSMALL", creature->iconIndex, 0, 8, 0); + + std::string value; + if(showAvailable) + value = boost::lexical_cast(town->creatures[level].first); + else + value = boost::lexical_cast(town->creatureGrowth(level)); + + if(compact) + { + label = std::make_shared(40, 32, FONT_TINY, BOTTOMRIGHT, Colors::WHITE, value); + pos.x += 8; + pos.w = 32; + pos.h = 32; + } + else + { + label = std::make_shared(24, 40, FONT_SMALL, CENTER, Colors::WHITE, value); + pos.w = 48; + pos.h = 48; + } +} + +void CCreaInfo::update() +{ + if(label) + { + std::string value; + if(showAvailable) + value = boost::lexical_cast(town->creatures[level].first); + else + value = boost::lexical_cast(town->creatureGrowth(level)); + + if(value != label->text) + label->setText(value); + } +} + +void CCreaInfo::hover(bool on) +{ + std::string message = CGI->generaltexth->allTexts[588]; + boost::algorithm::replace_first(message, "%s", creature->namePl); + + if(on) + { + GH.statusbar->setText(message); + } + else if (message == GH.statusbar->getText()) + { + GH.statusbar->clear(); + } +} + +void CCreaInfo::clickLeft(tribool down, bool previousState) +{ + if(previousState && (!down)) + { + int offset = LOCPLINT->castleInt? (-87) : 0; + auto recruitCb = [=](CreatureID id, int count) + { + LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level); + }; + GH.pushInt(new CRecruitmentWindow(town, level, town, recruitCb, offset)); + } +} + +std::string CCreaInfo::genGrowthText() +{ + GrowthInfo gi = town->getGrowthInfo(level); + std::string descr = boost::str(boost::format(CGI->generaltexth->allTexts[589]) % creature->nameSing % gi.totalGrowth()); + + for(const GrowthInfo::Entry & entry : gi.entries) + descr +="\n" + entry.description; + + return descr; +} + +void CCreaInfo::clickRight(tribool down, bool previousState) +{ + if(down) + { + if (showAvailable) + GH.pushInt(new CDwellingInfoBox(screen->w/2, screen->h/2, town, level)); + else + CRClickPopup::createAndPush(genGrowthText(), std::make_shared(CComponent::creature, creature->idNumber)); + } +} + +CTownInfo::CTownInfo(int posX, int posY, const CGTownInstance * Town, bool townHall) + : town(Town), + building(nullptr) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + addUsedEvents(RCLICK | HOVER); + pos.x += posX; + pos.y += posY; + int buildID; + + if(townHall) + { + buildID = 10 + town->hallLevel(); + picture = std::make_shared("ITMTL.DEF", town->hallLevel()); + } + else + { + buildID = 6 + town->fortLevel(); + if(buildID == 6) + return;//FIXME: suspicious statement, fix or comment + picture = std::make_shared("ITMCL.DEF", town->fortLevel()-1); + } + building = town->town->buildings.at(BuildingID(buildID)); + pos = picture->pos; +} + +void CTownInfo::hover(bool on) +{ + if(on) + { + if(building ) + GH.statusbar->setText(building->Name()); + } + else + { + GH.statusbar->clear(); + } +} + +void CTownInfo::clickRight(tribool down, bool previousState) +{ + if(building && down) + { + auto c = std::make_shared(CComponent::building, building->town->faction->index, building->bid); + CRClickPopup::createAndPush(CInfoWindow::genText(building->Name(), building->Description()), c); + } +} + CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInstance * from): CWindowObject(PLAYER_COLORED | BORDERED), - hall(nullptr), - fort(nullptr), - fastArmyPurhase(nullptr), town(Town) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); LOCPLINT->castleInt = this; addUsedEvents(KEYBOARD); - builds = new CCastleBuildings(town); - panel = new CPicture("TOWNSCRN", 0, builds->pos.h); + builds = std::make_shared(town); + panel = std::make_shared("TOWNSCRN", 0, builds->pos.h); panel->colorize(LOCPLINT->playerID); pos.w = panel->pos.w; pos.h = builds->pos.h + panel->pos.h; center(); updateShadow(); - garr = new CGarrisonInt(305, 387, 4, Point(0,96), panel->bg, Point(62,374), town->getUpperArmy(), town->visitingHero); + garr = std::make_shared(305, 387, 4, Point(0,96), town->getUpperArmy(), town->visitingHero); garr->type |= REDRAW_PARENT; - heroes = new HeroSlots(town, Point(241, 387), Point(241, 483), garr, true); - title = new CLabel(85, 387, FONT_MEDIUM, TOPLEFT, Colors::WHITE, town->name); - income = new CLabel(195, 443, FONT_SMALL, CENTER); - icon = new CAnimImage("ITPT", 0, 0, 15, 387); + heroes = std::make_shared(town, Point(241, 387), Point(241, 483), garr, true); + title = std::make_shared(85, 387, FONT_MEDIUM, TOPLEFT, Colors::WHITE, town->name); + income = std::make_shared(195, 443, FONT_SMALL, CENTER); + icon = std::make_shared("ITPT", 0, 0, 15, 387); - exit = new CButton(Point(744, 544), "TSBTNS", CButton::tooltip(CGI->generaltexth->tcommands[8]), [&](){close();}, SDLK_RETURN); + exit = std::make_shared(Point(744, 544), "TSBTNS", CButton::tooltip(CGI->generaltexth->tcommands[8]), [&](){close();}, SDLK_RETURN); exit->assignedKeys.insert(SDLK_ESCAPE); exit->setImageOrder(4, 5, 6, 7); - split = new CButton(Point(744, 382), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), [&](){garr->splitClick();}); + auto split = std::make_shared(Point(744, 382), "TSBTNS", CButton::tooltip(CGI->generaltexth->tcommands[3]), [&](){garr->splitClick();}); split->addCallback(std::bind(&HeroSlots::splitClicked, heroes)); garr->addSplitBtn(split); Rect barRect(9, 182, 732, 18); - statusbar = new CGStatusBar(new CPicture(*panel, barRect, 9, 555, false)); - resdatabar = new CResDataBar("ARESBAR", 3, 575, 32, 2, 85, 85); + auto statusbarBackground = std::make_shared(*(panel.get()), barRect, 9, 555, false); + statusbar = std::make_shared(statusbarBackground); + resdatabar = std::make_shared("ARESBAR", 3, 575, 32, 2, 85, 85); - townlist = new CTownList(3, Point(744, 414), "IAM014", "IAM015"); - if (from) + townlist = std::make_shared(3, Point(744, 414), "IAM014", "IAM015"); + if(from) townlist->select(from); townlist->select(town); //this will scroll list to select current town @@ -939,6 +1144,11 @@ CCastleInterface::~CCastleInterface() LOCPLINT->castleInt = nullptr; } +void CCastleInterface::updateGarrisons() +{ + garr->recreateSlots(); +} + void CCastleInterface::close() { if(town->tempOwner == LOCPLINT->playerID) //we may have opened window for an allied town @@ -986,236 +1196,35 @@ void CCastleInterface::removeBuilding(BuildingID bid) void CCastleInterface::recreateIcons() { - OBJ_CONSTRUCTION_CAPTURING_ALL; - delete fort; - delete hall; - delete fastArmyPurhase; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN]; icon->setFrame(iconIndex); TResources townIncome = town->dailyIncome(); income->setText(boost::lexical_cast(townIncome[Res::GOLD])); - hall = new CTownInfo( 80, 413, town, true); - fort = new CTownInfo(122, 413, town, false); + hall = std::make_shared(80, 413, town, true); + fort = std::make_shared(122, 413, town, false); - fastArmyPurhase = new CButton(Point(122, 413), "itmcl.def", CButton::tooltip(), [&](){builds->enterToTheQuickRecruitmentWindow();}); - fastArmyPurhase->setImageOrder(town->fortLevel()-1,town->fortLevel()-1,town->fortLevel()-1,town->fortLevel()-1); + fastArmyPurhase = std::make_shared(Point(122, 413), "itmcl.def", CButton::tooltip(), [&](){builds->enterToTheQuickRecruitmentWindow();}); + fastArmyPurhase->setImageOrder(town->fortLevel()-1, town->fortLevel()-1, town->fortLevel()-1, town->fortLevel()-1); fastArmyPurhase->setAnimateLonelyFrame(true); - for (auto & elem : creainfo) - delete elem; + creainfo.clear(); - for (size_t i=0; i<4; i++) - creainfo.push_back(new CCreaInfo(Point(14+55*i, 459), town, i)); + for(size_t i=0; i<4; i++) + creainfo.push_back(std::make_shared(Point(14+55*i, 459), town, i)); - for (size_t i=0; i<4; i++) - creainfo.push_back(new CCreaInfo(Point(14+55*i, 507), town, i+4)); + for(size_t i=0; i<4; i++) + creainfo.push_back(std::make_shared(Point(14+55*i, 507), town, i+4)); } -CCreaInfo::CCreaInfo(Point position, const CGTownInstance *Town, int Level, bool compact, bool ShowAvailable): - town(Town), - level(Level), - showAvailable(ShowAvailable) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - pos += position; - - if ( town->creatures.size() <= level || town->creatures[level].second.empty()) - { - level = -1; - label = nullptr; - picture = nullptr; - creature = nullptr; - return;//No creature - } - addUsedEvents(LCLICK | RCLICK | HOVER); - - ui32 creatureID = town->creatures[level].second.back(); - creature = CGI->creh->creatures[creatureID]; - - picture = new CAnimImage("CPRSMALL", creature->iconIndex, 0, 8, 0); - - std::string value; - if (showAvailable) - value = boost::lexical_cast(town->creatures[level].first); - else - value = boost::lexical_cast(town->creatureGrowth(level)); - - if (compact) - { - label = new CLabel(40, 32, FONT_TINY, BOTTOMRIGHT, Colors::WHITE, value); - pos.x += 8; - pos.w = 32; - pos.h = 32; - } - else - { - label = new CLabel(24, 40, FONT_SMALL, CENTER, Colors::WHITE, value); - pos.w = 48; - pos.h = 48; - } -} - -void CCreaInfo::update() -{ - if (label) - { - std::string value; - if (showAvailable) - value = boost::lexical_cast(town->creatures[level].first); - else - value = boost::lexical_cast(town->creatureGrowth(level)); - - if (value != label->text) - label->setText(value); - } -} - -void CCreaInfo::hover(bool on) -{ - std::string message = CGI->generaltexth->allTexts[588]; - boost::algorithm::replace_first(message,"%s",creature->namePl); - - if(on) - { - GH.statusbar->setText(message); - } - else if (message == GH.statusbar->getText()) - GH.statusbar->clear(); -} - -void CCreaInfo::clickLeft(tribool down, bool previousState) -{ - if(previousState && (!down)) - { - int offset = LOCPLINT->castleInt? (-87) : 0; - auto recruitCb = [=](CreatureID id, int count) { LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level); }; - GH.pushInt(new CRecruitmentWindow(town, level, town, recruitCb, offset)); - } -} - -int CCreaInfo::AddToString(std::string from, std::string & to, int numb) -{ - if (numb == 0) - return 0; - boost::algorithm::replace_first(from,"%+d", (numb > 0 ? "+" : "")+boost::lexical_cast(numb)); //negative values don't need "+" - to+="\n"+from; - return numb; -} - -std::string CCreaInfo::genGrowthText() -{ - GrowthInfo gi = town->getGrowthInfo(level); - std::string descr = boost::str(boost::format(CGI->generaltexth->allTexts[589]) % creature->nameSing % gi.totalGrowth()); - - for(const GrowthInfo::Entry &entry : gi.entries) - { - descr +="\n" + entry.description; - } - - return descr; -} - -void CCreaInfo::clickRight(tribool down, bool previousState) -{ - if(down) - { - if (showAvailable) - GH.pushInt(new CDwellingInfoBox(screen->w/2, screen->h/2, town, level)); - else - CRClickPopup::createAndPush(genGrowthText(), new CComponent(CComponent::creature, creature->idNumber)); - } -} - -CTownInfo::CTownInfo(int posX, int posY, const CGTownInstance* Town, bool townHall): - town(Town), - building(nullptr) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - addUsedEvents(RCLICK | HOVER); - pos.x += posX; - pos.y += posY; - int buildID; - - picture = nullptr; - - if (townHall) - { - buildID = 10 + town->hallLevel(); - picture = new CAnimImage("ITMTL.DEF", town->hallLevel()); - } - else - { - buildID = 6 + town->fortLevel(); - if (buildID == 6) - return;//FIXME: suspicious statement, fix or comment - picture = new CAnimImage("ITMCL.DEF", town->fortLevel()-1); - } - building = town->town->buildings.at(BuildingID(buildID)); - pos = picture->pos; -} - -void CTownInfo::hover(bool on) -{ - if(on) - { - if ( building ) - GH.statusbar->setText(building->Name()); - } - else - GH.statusbar->clear(); -} - -void CTownInfo::clickRight(tribool down, bool previousState) -{ - if(building && down) - CRClickPopup::createAndPush(CInfoWindow::genText(building->Name(), building->Description()), - new CComponent(CComponent::building, building->town->faction->index, building->bid)); - -} - -void CCastleInterface::keyPressed( const SDL_KeyboardEvent & key ) +void CCastleInterface::keyPressed(const SDL_KeyboardEvent & key) { if(key.state != SDL_PRESSED) return; switch(key.keysym.sym) { -#if 0 // code that can be used to fix blit order in towns using +/- keys. Quite ugly but works - case SDLK_KP_PLUS : - if (builds->selectedBuilding) - { - OBJ_CONSTRUCTION_CAPTURING_ALL; - CStructure * str = const_cast(builds->selectedBuilding->str); - str->pos.z++; - delete builds; - builds = new CCastleBuildings(town); - - for(const CStructure * str : town->town->clientInfo.structures) - { - if (str->building) - logGlobal->error("%d -> %d", int(str->building->bid), int(str->pos.z)); - } - } - break; - case SDLK_KP_MINUS: - if (builds->selectedBuilding) - { - OBJ_CONSTRUCTION_CAPTURING_ALL; - CStructure * str = const_cast(builds->selectedBuilding->str); - str->pos.z--; - delete builds; - builds = new CCastleBuildings(town); - - for(const CStructure * str : town->town->clientInfo.structures) - { - if (str->building) - logGlobal->error("%d -> %d", int(str->building->bid), int(str->pos.z)); - } - - } - break; -#endif case SDLK_UP: townlist->selectPrev(); break; @@ -1234,41 +1243,37 @@ void CCastleInterface::keyPressed( const SDL_KeyboardEvent & key ) } } -HeroSlots::HeroSlots(const CGTownInstance * Town, Point garrPos, Point visitPos, CGarrisonInt *Garrison, bool ShowEmpty): - showEmpty(ShowEmpty), +CHallInterface::CBuildingBox::CBuildingBox(int x, int y, const CGTownInstance * Town, const CBuilding * Building): town(Town), - garr(Garrison) + building(Building) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - garrisonedHero = new CHeroGSlot(garrPos.x, garrPos.y, 0, town->garrisonHero, this); - visitingHero = new CHeroGSlot(visitPos.x, visitPos.y, 1, town->visitingHero, this); -} + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + addUsedEvents(LCLICK | RCLICK | HOVER); + pos.x += x; + pos.y += y; + pos.w = 154; + pos.h = 92; -void HeroSlots::update() -{ - garrisonedHero->set(town->garrisonHero); - visitingHero->set(town->visitingHero); -} + state = LOCPLINT->cb->canBuildStructure(town, building->bid); -void HeroSlots::splitClicked() -{ - if(!!town->visitingHero && town->garrisonHero && (visitingHero->selection || garrisonedHero->selection)) + static int panelIndex[12] = { - LOCPLINT->heroExchangeStarted(town->visitingHero->id, town->garrisonHero->id, QueryID(-1)); - } -} - -void HeroSlots::swapArmies() -{ - if(!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies: town army => hero army + 3, 3, 3, 0, 0, 2, 2, 1, 2, 2, 3, 3 + }; + static int iconIndex[12] = { - if(!town->visitingHero->canBeMergedWith(*town)) - { - LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[275], std::vector(), soundBase::sound_todo); - return; - } - } - LOCPLINT->cb->swapGarrisonHero(town); + -1, -1, -1, 0, 0, 1, 2, -1, 1, 1, -1, -1 + }; + + icon = std::make_shared(town->town->clientInfo.buildingsIcons, building->bid, 0, 2, 2); + header = std::make_shared("TPTHBAR", panelIndex[state], 0, 1, 73); + if(iconIndex[state] >=0) + mark = std::make_shared("TPTHCHK", iconIndex[state], 0, 136, 56); + name = std::make_shared(75, 81, FONT_SMALL, CENTER, Colors::WHITE, building->Name()); + + //todo: add support for all possible states + if(state >= EBuildingState::BUILDING_ERROR) + state = EBuildingState::FORBIDDEN; } void CHallInterface::CBuildingBox::hover(bool on) @@ -1286,7 +1291,9 @@ void CHallInterface::CBuildingBox::hover(bool on) GH.statusbar->setText(toPrint); } else + { GH.statusbar->clear(); + } } void CHallInterface::CBuildingBox::clickLeft(tribool down, bool previousState) @@ -1301,47 +1308,21 @@ void CHallInterface::CBuildingBox::clickRight(tribool down, bool previousState) GH.pushInt(new CBuildWindow(town,building,state,1)); } -CHallInterface::CBuildingBox::CBuildingBox(int x, int y, const CGTownInstance * Town, const CBuilding * Building): - town(Town), - building(Building) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - addUsedEvents(LCLICK | RCLICK | HOVER); - pos.x += x; - pos.y += y; - pos.w = 154; - pos.h = 92; - - state = LOCPLINT->cb->canBuildStructure(town,building->bid); - - static int panelIndex[12] = { 3, 3, 3, 0, 0, 2, 2, 1, 2, 2, 3, 3}; - static int iconIndex[12] = {-1, -1, -1, 0, 0, 1, 2, -1, 1, 1, -1, -1}; - - new CAnimImage(town->town->clientInfo.buildingsIcons, building->bid, 0, 2, 2); - new CAnimImage("TPTHBAR", panelIndex[state], 0, 1, 73); - if (iconIndex[state] >=0) - new CAnimImage("TPTHCHK", iconIndex[state], 0, 136, 56); - new CLabel(75, 81, FONT_SMALL, CENTER, Colors::WHITE, building->Name()); - - //todo: add support for all possible states - if(state >= EBuildingState::BUILDING_ERROR) - state = EBuildingState::FORBIDDEN; -} - -CHallInterface::CHallInterface(const CGTownInstance *Town): +CHallInterface::CHallInterface(const CGTownInstance * Town): CWindowObject(PLAYER_COLORED | BORDERED, Town->town->clientInfo.hallBackground), town(Town) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - resdatabar = new CMinorResDataBar(); - resdatabar->pos.x += pos.x; - resdatabar->pos.y += pos.y; + resdatabar = std::make_shared(); + resdatabar->moveBy(pos.topLeft(), true); Rect barRect(5, 556, 740, 18); - statusBar = new CGStatusBar(new CPicture(*background, barRect, 5, 556, false)); - title = new CLabel(399, 12, FONT_MEDIUM, CENTER, Colors::WHITE, town->town->buildings.at(BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL))->Name()); - exit = new CButton(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->hcommands[8]), [&](){close();}, SDLK_RETURN); + auto statusbarBackground = std::make_shared(*background, barRect, 5, 556, false); + statusbar = std::make_shared(statusbarBackground); + + title = std::make_shared(399, 12, FONT_MEDIUM, CENTER, Colors::WHITE, town->town->buildings.at(BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL))->Name()); + exit = std::make_shared(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->hcommands[8]), [&](){close();}, SDLK_RETURN); exit->assignedKeys.insert(SDLK_ESCAPE); auto & boxList = town->town->clientInfo.hallSlots; @@ -1370,12 +1351,52 @@ CHallInterface::CHallInterface(const CGTownInstance *Town): int posX = pos.w/2 - boxList[row].size()*154/2 - (boxList[row].size()-1)*20 + 194*col, posY = 35 + 104*row; - if (building) - boxes[row].push_back(new CBuildingBox(posX, posY, town, building)); + if(building) + boxes[row].push_back(std::make_shared(posX, posY, town, building)); } } } +CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Building, int state, bool rightClick): + CWindowObject(PLAYER_COLORED | (rightClick ? RCLICK_POPUP : 0), "TPUBUILD"), + town(Town), + building(Building) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + icon = std::make_shared(town->town->clientInfo.buildingsIcons, building->bid, 0, 125, 50); + auto statusbarBackground = std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26); + statusbar = std::make_shared(statusbarBackground); + + name = std::make_shared(197, 30, FONT_MEDIUM, CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->hcommands[7]) % building->Name())); + description = std::make_shared(building->Description(), Rect(33, 135, 329, 67), 0, FONT_MEDIUM, CENTER); + stateText = std::make_shared(getTextForState(state), Rect(33, 216, 329, 67), 0, FONT_SMALL, CENTER); + + //Create components for all required resources + std::vector> components; + + for(int i = 0; iresources[i]) + components.push_back(std::make_shared(CComponent::resource, i, building->resources[i], CComponent::small)); + } + + cost = std::make_shared(components, Rect(25, 300, pos.w - 50, 130)); + + if(!rightClick) + { //normal window + std::string tooltipYes = boost::str(boost::format(CGI->generaltexth->allTexts[595]) % building->Name()); + std::string tooltipNo = boost::str(boost::format(CGI->generaltexth->allTexts[596]) % building->Name()); + + buy = std::make_shared(Point(45, 446), "IBUY30", CButton::tooltip(tooltipYes), [&](){ buyFunc(); }, SDLK_RETURN); + buy->setBorderColor(Colors::METALLIC_GOLD); + buy->block(state!=7 || LOCPLINT->playerID != town->tempOwner); + + cancel = std::make_shared(Point(290, 445), "ICANCEL", CButton::tooltip(tooltipNo), [&](){ close();}, SDLK_ESCAPE); + cancel->setBorderColor(Colors::METALLIC_GOLD); + } +} + void CBuildWindow::buyFunc() { LOCPLINT->cb->buildBuilding(town,building->bid); @@ -1417,122 +1438,9 @@ std::string CBuildWindow::getTextForState(int state) return ret; } -CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Building, int state, bool rightClick): - CWindowObject(PLAYER_COLORED | (rightClick ? RCLICK_POPUP : 0), "TPUBUILD"), - town(Town), - building(Building) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - - new CAnimImage(town->town->clientInfo.buildingsIcons, building->bid, 0, 125, 50); - new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); - - new CLabel(197, 30, FONT_MEDIUM, CENTER, Colors::WHITE, - boost::str(boost::format(CGI->generaltexth->hcommands[7]) % building->Name())); - new CTextBox(building->Description(), Rect(33, 135, 329, 67), 0, FONT_MEDIUM, CENTER); - new CTextBox(getTextForState(state), Rect(33, 216, 329, 67), 0, FONT_SMALL, CENTER); - - //Create components for all required resources - std::vector components; - - for(int i = 0; iresources[i]) - { - components.push_back(new CComponent(CComponent::resource, i, building->resources[i], CComponent::small)); - } - } - - new CComponentBox(components, Rect(25, 300, pos.w - 50, 130)); - - if(!rightClick) - { //normal window - std::string tooltipYes = boost::str(boost::format(CGI->generaltexth->allTexts[595]) % building->Name()); - std::string tooltipNo = boost::str(boost::format(CGI->generaltexth->allTexts[596]) % building->Name()); - - CButton * buy = new CButton(Point(45, 446), "IBUY30", CButton::tooltip(tooltipYes), [&](){ buyFunc(); }, SDLK_RETURN); - buy->setBorderColor(Colors::METALLIC_GOLD); - buy->block(state!=7 || LOCPLINT->playerID != town->tempOwner); - - CButton * cancel = new CButton(Point(290, 445), "ICANCEL", CButton::tooltip(tooltipNo), [&](){ close();}, SDLK_ESCAPE); - cancel->setBorderColor(Colors::METALLIC_GOLD); - } -} - - -std::string CFortScreen::getBgName(const CGTownInstance *town) -{ - ui32 fortSize = town->creatures.size(); - if (fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty()) - fortSize--; - - if (fortSize == GameConstants::CREATURES_PER_TOWN) - return "TPCASTL7"; - else - return "TPCASTL8"; -} - -CFortScreen::CFortScreen(const CGTownInstance * town): - CWindowObject(PLAYER_COLORED | BORDERED, getBgName(town)) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - ui32 fortSize = town->creatures.size(); - if (fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty()) - fortSize--; - - const CBuilding *fortBuilding = town->town->buildings.at(BuildingID(town->fortLevel()+6)); - title = new CLabel(400, 12, FONT_BIG, CENTER, Colors::WHITE, fortBuilding->Name()); - - std::string text = boost::str(boost::format(CGI->generaltexth->fcommands[6]) % fortBuilding->Name()); - exit = new CButton(Point(748, 556), "TPMAGE1", CButton::tooltip(text), [&](){ close(); }, SDLK_RETURN); - exit->assignedKeys.insert(SDLK_ESCAPE); - - std::vector positions = - { - Point(10, 22), Point(404, 22), - Point(10, 155), Point(404,155), - Point(10, 288), Point(404,288) - }; - - if (fortSize == GameConstants::CREATURES_PER_TOWN) - positions.push_back(Point(206,421)); - else - { - positions.push_back(Point(10, 421)); - positions.push_back(Point(404,421)); - } - - for (ui32 i=0; ibuiltBuildings, BuildingID::DWELL_UP_FIRST+i)) - buildingID = BuildingID(BuildingID::DWELL_UP_FIRST+i); - else - buildingID = BuildingID(BuildingID::DWELL_FIRST+i); - } - else - buildingID = BuildingID::SPECIAL_3; - recAreas.push_back(new RecruitArea(positions[i].x, positions[i].y, town, i)); - } - - resdatabar = new CMinorResDataBar(); - resdatabar->pos.x += pos.x; - resdatabar->pos.y += pos.y; - - Rect barRect(4, 554, 740, 18); - statusBar = new CGStatusBar(new CPicture(*background, barRect, 4, 554, false)); -} - -void CFortScreen::creaturesChanged() -{ - for (auto & elem : recAreas) - elem->creaturesChanged(); -} - LabeledValue::LabeledValue(Rect size, std::string name, std::string descr, int min, int max) { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); pos.x+=size.x; pos.y+=size.y; pos.w = size.w; @@ -1542,6 +1450,7 @@ LabeledValue::LabeledValue(Rect size, std::string name, std::string descr, int m LabeledValue::LabeledValue(Rect size, std::string name, std::string descr, int val) { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); pos.x+=size.x; pos.y+=size.y; pos.w = size.w; @@ -1551,24 +1460,25 @@ LabeledValue::LabeledValue(Rect size, std::string name, std::string descr, int v void LabeledValue::init(std::string nameText, std::string descr, int min, int max) { - OBJ_CONSTRUCTION_CAPTURING_ALL; addUsedEvents(HOVER); hoverText = descr; std::string valueText; - if (min && max) + if(min && max) { valueText = boost::lexical_cast(min); - if (min != max) + if(min != max) valueText += '-' + boost::lexical_cast(max); } - name = new CLabel(3, 0, FONT_SMALL, TOPLEFT, Colors::WHITE, nameText); - value = new CLabel(pos.w-3, pos.h-2, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, valueText); + name = std::make_shared(3, 0, FONT_SMALL, TOPLEFT, Colors::WHITE, nameText); + value = std::make_shared(pos.w-3, pos.h-2, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, valueText); } void LabeledValue::hover(bool on) { if(on) + { GH.statusbar->setText(hoverText); + } else { GH.statusbar->clear(); @@ -1576,11 +1486,138 @@ void LabeledValue::hover(bool on) } } +CFortScreen::CFortScreen(const CGTownInstance * town): + CWindowObject(PLAYER_COLORED | BORDERED, getBgName(town)) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + ui32 fortSize = town->creatures.size(); + if(fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty()) + fortSize--; + + const CBuilding * fortBuilding = town->town->buildings.at(BuildingID(town->fortLevel()+6)); + title = std::make_shared(400, 12, FONT_BIG, CENTER, Colors::WHITE, fortBuilding->Name()); + + std::string text = boost::str(boost::format(CGI->generaltexth->fcommands[6]) % fortBuilding->Name()); + exit = std::make_shared(Point(748, 556), "TPMAGE1", CButton::tooltip(text), [&](){ close(); }, SDLK_RETURN); + exit->assignedKeys.insert(SDLK_ESCAPE); + + std::vector positions = + { + Point(10, 22), Point(404, 22), + Point(10, 155), Point(404,155), + Point(10, 288), Point(404,288) + }; + + if(fortSize == GameConstants::CREATURES_PER_TOWN) + { + positions.push_back(Point(206,421)); + } + else + { + positions.push_back(Point(10, 421)); + positions.push_back(Point(404,421)); + } + + for(ui32 i=0; ibuiltBuildings, BuildingID::DWELL_UP_FIRST+i)) + buildingID = BuildingID(BuildingID::DWELL_UP_FIRST+i); + else + buildingID = BuildingID(BuildingID::DWELL_FIRST+i); + } + else + { + buildingID = BuildingID::SPECIAL_3; + } + + recAreas.push_back(std::make_shared(positions[i].x, positions[i].y, town, i)); + } + + resdatabar = std::make_shared(); + resdatabar->moveBy(pos.topLeft(), true); + + Rect barRect(4, 554, 740, 18); + + auto statusbarBackground = std::make_shared(*background, barRect, 4, 554, false); + statusbar = std::make_shared(statusbarBackground); +} + +std::string CFortScreen::getBgName(const CGTownInstance * town) +{ + ui32 fortSize = town->creatures.size(); + if(fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty()) + fortSize--; + + if(fortSize == GameConstants::CREATURES_PER_TOWN) + return "TPCASTL7"; + else + return "TPCASTL8"; +} + +void CFortScreen::creaturesChanged() +{ + for(auto & elem : recAreas) + elem->creaturesChanged(); +} + +CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance * Town, int Level): + town(Town), + level(Level), + availableCount(nullptr) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + pos.x +=posX; + pos.y +=posY; + pos.w = 386; + pos.h = 126; + + if(!town->creatures[level].second.empty()) + addUsedEvents(LCLICK | RCLICK | HOVER);//Activate only if dwelling is present + + icons = std::make_shared("TPCAINFO", 261, 3); + + if(getMyBuilding() != nullptr) + { + buildingIcon = std::make_shared(town->town->clientInfo.buildingsIcons, getMyBuilding()->bid, 0, 4, 21); + buildingName = std::make_shared(78, 101, FONT_SMALL, CENTER, Colors::WHITE, getMyBuilding()->Name()); + + if(vstd::contains(town->builtBuildings, getMyBuilding()->bid)) + { + ui32 available = town->creatures[level].first; + std::string availableText = CGI->generaltexth->allTexts[217]+ boost::lexical_cast(available); + availableCount = std::make_shared(78, 119, FONT_SMALL, CENTER, Colors::WHITE, availableText); + } + } + + if(getMyCreature() != nullptr) + { + hoverText = boost::str(boost::format(CGI->generaltexth->tcommands[21]) % getMyCreature()->namePl); + new CCreaturePic(159, 4, getMyCreature(), false); + new CLabel(78, 11, FONT_SMALL, CENTER, Colors::WHITE, getMyCreature()->namePl); + + Rect sizes(287, 4, 96, 18); + values.push_back(std::make_shared(sizes, CGI->generaltexth->allTexts[190], CGI->generaltexth->fcommands[0], getMyCreature()->getAttack(false))); + sizes.y+=20; + values.push_back(std::make_shared(sizes, CGI->generaltexth->allTexts[191], CGI->generaltexth->fcommands[1], getMyCreature()->getDefence(false))); + sizes.y+=21; + values.push_back(std::make_shared(sizes, CGI->generaltexth->allTexts[199], CGI->generaltexth->fcommands[2], getMyCreature()->getMinDamage(false), getMyCreature()->getMaxDamage(false))); + sizes.y+=20; + values.push_back(std::make_shared(sizes, CGI->generaltexth->allTexts[388], CGI->generaltexth->fcommands[3], getMyCreature()->MaxHealth())); + sizes.y+=21; + values.push_back(std::make_shared(sizes, CGI->generaltexth->allTexts[193], CGI->generaltexth->fcommands[4], getMyCreature()->valOfBonuses(Bonus::STACKS_SPEED))); + sizes.y+=20; + values.push_back(std::make_shared(sizes, CGI->generaltexth->allTexts[194], CGI->generaltexth->fcommands[5], town->creatureGrowth(level))); + } +} + const CCreature * CFortScreen::RecruitArea::getMyCreature() { - if (!town->creatures.at(level).second.empty()) // built + if(!town->creatures.at(level).second.empty()) // built return VLC->creh->creatures[town->creatures.at(level).second.back()]; - if (!town->town->creatures.at(level).empty()) // there are creatures on this level + if(!town->town->creatures.at(level).empty()) // there are creatures on this level return VLC->creh->creatures[town->town->creatures.at(level).front()]; return nullptr; } @@ -1605,56 +1642,6 @@ const CBuilding * CFortScreen::RecruitArea::getMyBuilding() return build; } -CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *Town, int Level): - town(Town), - level(Level), - availableCount(nullptr) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - pos.x +=posX; - pos.y +=posY; - pos.w = 386; - pos.h = 126; - - if (!town->creatures[level].second.empty()) - addUsedEvents(LCLICK | RCLICK | HOVER);//Activate only if dwelling is present - - icons = new CPicture("TPCAINFO", 261, 3); - - if (getMyBuilding() != nullptr) - { - new CAnimImage(town->town->clientInfo.buildingsIcons, getMyBuilding()->bid, 0, 4, 21); - new CLabel(78, 101, FONT_SMALL, CENTER, Colors::WHITE, getMyBuilding()->Name()); - - if (vstd::contains(town->builtBuildings, getMyBuilding()->bid)) - { - ui32 available = town->creatures[level].first; - std::string availableText = CGI->generaltexth->allTexts[217]+ boost::lexical_cast(available); - availableCount = new CLabel(78, 119, FONT_SMALL, CENTER, Colors::WHITE, availableText); - } - } - - if (getMyCreature() != nullptr) - { - hoverText = boost::str(boost::format(CGI->generaltexth->tcommands[21]) % getMyCreature()->namePl); - new CCreaturePic(159, 4, getMyCreature(), false); - new CLabel(78, 11, FONT_SMALL, CENTER, Colors::WHITE, getMyCreature()->namePl); - - Rect sizes(287, 4, 96, 18); - values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[190], CGI->generaltexth->fcommands[0], getMyCreature()->getAttack(false))); - sizes.y+=20; - values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[191], CGI->generaltexth->fcommands[1], getMyCreature()->getDefence(false))); - sizes.y+=21; - values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[199], CGI->generaltexth->fcommands[2], getMyCreature()->getMinDamage(false), getMyCreature()->getMaxDamage(false))); - sizes.y+=20; - values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[388], CGI->generaltexth->fcommands[3], getMyCreature()->MaxHealth())); - sizes.y+=21; - values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[193], CGI->generaltexth->fcommands[4], getMyCreature()->valOfBonuses(Bonus::STACKS_SPEED))); - sizes.y+=20; - values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[194], CGI->generaltexth->fcommands[5], town->creatureGrowth(level))); - } -} - void CFortScreen::RecruitArea::hover(bool on) { if(on) @@ -1665,10 +1652,9 @@ void CFortScreen::RecruitArea::hover(bool on) void CFortScreen::RecruitArea::creaturesChanged() { - if (availableCount) + if(availableCount) { - std::string availableText = CGI->generaltexth->allTexts[217] + - boost::lexical_cast(town->creatures[level].first); + std::string availableText = CGI->generaltexth->allTexts[217] + boost::lexical_cast(town->creatures[level].first); availableCount->setText(availableText); } } @@ -1684,19 +1670,22 @@ void CFortScreen::RecruitArea::clickRight(tribool down, bool previousState) clickLeft(down, false); //r-click does same as l-click - opens recr. window } -CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner,std::string imagem) :CWindowObject(BORDERED,imagem) +CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner,std::string imagem) + : CWindowObject(BORDERED, imagem) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - window = new CPicture(owner->town->town->clientInfo.guildWindow , 332, 76); + window = std::make_shared(owner->town->town->clientInfo.guildWindow, 332, 76); + + resdatabar = std::make_shared(); + resdatabar->moveBy(pos.topLeft(), true); - resdatabar = new CMinorResDataBar(); - resdatabar->pos.x += pos.x; - resdatabar->pos.y += pos.y; Rect barRect(7, 556, 737, 18); - statusBar = new CGStatusBar(new CPicture(*background, barRect, 7, 556, false)); - exit = new CButton(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[593]), [&](){ close(); }, SDLK_RETURN); + auto statusbarBackground = std::make_shared(*background, barRect, 7, 556, false); + statusbar = std::make_shared(statusbarBackground); + + exit = std::make_shared(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[593]), [&](){ close(); }, SDLK_RETURN); exit->assignedKeys.insert(SDLK_ESCAPE); static const std::vector > positions = @@ -1714,33 +1703,34 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner,std::string imagem) for(size_t j=0; jtown->mageGuildLevel() && owner->town->spells[i].size()>j) - spells.push_back( new Scroll(positions[i][j], CGI->spellh->objects[owner->town->spells[i][j]])); + spells.push_back(std::make_shared(positions[i][j], CGI->spellh->objects[owner->town->spells[i][j]])); else - new CAnimImage("TPMAGES.DEF", 1, 0, positions[i][j].x, positions[i][j].y);//closed scroll + emptyScrolls.push_back(std::make_shared("TPMAGES.DEF", 1, 0, positions[i][j].x, positions[i][j].y)); } } } CMageGuildScreen::Scroll::Scroll(Point position, const CSpell *Spell) - :spell(Spell) + : spell(Spell) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + addUsedEvents(LCLICK | RCLICK | HOVER); pos += position; - image = new CAnimImage("SPELLSCR", spell->id); + image = std::make_shared("SPELLSCR", spell->id); pos = image->pos; } void CMageGuildScreen::Scroll::clickLeft(tribool down, bool previousState) { if(down) - LOCPLINT->showInfoDialog(spell->getLevelInfo(0).description, new CComponent(CComponent::spell,spell->id)); + LOCPLINT->showInfoDialog(spell->getLevelInfo(0).description, std::make_shared(CComponent::spell, spell->id)); } void CMageGuildScreen::Scroll::clickRight(tribool down, bool previousState) { if(down) - CRClickPopup::createAndPush(spell->getLevelInfo(0).description, new CComponent(CComponent::spell, spell->id)); + CRClickPopup::createAndPush(spell->getLevelInfo(0).description, std::make_shared(CComponent::spell, spell->id)); } void CMageGuildScreen::Scroll::hover(bool on) @@ -1755,33 +1745,36 @@ void CMageGuildScreen::Scroll::hover(bool on) CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, ArtifactID aid, ObjectInstanceID hid): CWindowObject(PLAYER_COLORED, "TPSMITH") { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - statusBar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + Rect barRect(8, pos.h - 26, pos.w - 16, 19); - animBG = new CPicture("TPSMITBK", 64, 50); + auto statusbarBackground = std::make_shared(*background, barRect, 8, pos.h - 26, false); + statusbar = std::make_shared(statusbarBackground); + + animBG = std::make_shared("TPSMITBK", 64, 50); animBG->needRefresh = true; - const CCreature *creature = CGI->creh->creatures[creMachineID]; - anim = new CCreatureAnim(64, 50, creature->animDefName, Rect()); + const CCreature * creature = CGI->creh->creatures[creMachineID]; + anim = std::make_shared(64, 50, creature->animDefName, Rect()); anim->clipRect(113,125,200,150); - title = new CLabel(165, 28, FONT_BIG, CENTER, Colors::YELLOW, + title = std::make_shared(165, 28, FONT_BIG, CENTER, Colors::YELLOW, boost::str(boost::format(CGI->generaltexth->allTexts[274]) % creature->nameSing)); - costText = new CLabel(165, 218, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->jktexts[43]); - costValue = new CLabel(165, 290, FONT_MEDIUM, CENTER, Colors::WHITE, + costText = std::make_shared(165, 218, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->jktexts[43]); + costValue = std::make_shared(165, 290, FONT_MEDIUM, CENTER, Colors::WHITE, boost::lexical_cast(CGI->arth->artifacts[aid]->price)); std::string text = boost::str(boost::format(CGI->generaltexth->allTexts[595]) % creature->nameSing); - buy = new CButton(Point(42, 312), "IBUY30.DEF", CButton::tooltip(text), [&](){ close(); }, SDLK_RETURN); + buy = std::make_shared(Point(42, 312), "IBUY30.DEF", CButton::tooltip(text), [&](){ close(); }, SDLK_RETURN); text = boost::str(boost::format(CGI->generaltexth->allTexts[596]) % creature->nameSing); - cancel = new CButton(Point(224, 312), "ICANCEL.DEF", CButton::tooltip(text), [&](){ close(); }, SDLK_ESCAPE); + cancel = std::make_shared(Point(224, 312), "ICANCEL.DEF", CButton::tooltip(text), [&](){ close(); }, SDLK_ESCAPE); if(possible) buy->addCallback([=](){ LOCPLINT->cb->buyArtifact(LOCPLINT->cb->getHero(hid),aid); }); else buy->block(true); - new CAnimImage("RESOURCE", 6, 0, 148, 244); + costIcon = std::make_shared("RESOURCE", Res::GOLD, 0, 148, 244); } diff --git a/client/windows/CCastleInterface.h b/client/windows/CCastleInterface.h index 307afb345..f3fdb52e2 100644 --- a/client/windows/CCastleInterface.h +++ b/client/windows/CCastleInterface.h @@ -29,6 +29,8 @@ struct CStructure; class CGHeroInstance; class CGarrisonInt; class CCreature; +class CComponent; +class CComponentBox; /// Building "button" class CBuildingRect : public CShowableAnim @@ -60,38 +62,43 @@ public: /// Dwelling info box - right-click screen for dwellings class CDwellingInfoBox : public CWindowObject { - CLabel *title; - CCreaturePic *animation; - CLabel *available; - CLabel *costPerTroop; + std::shared_ptr title; + std::shared_ptr animation; + std::shared_ptr available; + std::shared_ptr costPerTroop; - std::vector resPicture; - std::vector resAmount; + std::vector> resPicture; + std::vector> resAmount; public: - CDwellingInfoBox(int centerX, int centerY, const CGTownInstance *Town, int level); + CDwellingInfoBox(int centerX, int centerY, const CGTownInstance * Town, int level); + ~CDwellingInfoBox(); }; class HeroSlots; /// Hero icon slot class CHeroGSlot : public CIntObject { -public: - HeroSlots *owner; - const CGHeroInstance *hero; + std::shared_ptr portrait; + std::shared_ptr flag; + std::shared_ptr selection; //selection border. nullptr if not selected + + HeroSlots * owner; + const CGHeroInstance * hero; int upg; //0 - up garrison, 1 - down garrison - CAnimImage *image; - CAnimImage *selection; //selection border. nullptr if not selected +public: + CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, HeroSlots * Owner); + ~CHeroGSlot(); + + bool isSelected() const; void setHighlight(bool on); - void set(const CGHeroInstance *newHero); + void set(const CGHeroInstance * newHero); void hover (bool on) override; void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; void deactivate() override; - CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, HeroSlots * Owner); - ~CHeroGSlot(); }; /// Two hero slots that can interact with each other @@ -101,11 +108,12 @@ public: bool showEmpty; const CGTownInstance * town; - CGarrisonInt *garr; - CHeroGSlot * garrisonedHero; - CHeroGSlot * visitingHero; + std::shared_ptr garr; + std::shared_ptr garrisonedHero; + std::shared_ptr visitingHero; - HeroSlots(const CGTownInstance * town, Point garrPos, Point visitPos, CGarrisonInt *Garrison, bool ShowEmpty); + HeroSlots(const CGTownInstance * town, Point garrPos, Point visitPos, std::shared_ptr Garrison, bool ShowEmpty); + ~HeroSlots(); void splitClicked(); //for hero meeting only (splitting stacks is handled by garrison int) void update(); @@ -115,11 +123,11 @@ public: /// Class for town screen management (town background and structures) class CCastleBuildings : public CIntObject { - CPicture *background; + std::shared_ptr background; //List of buildings and structures that can represent them - std::map< BuildingID, std::vector > groups; + std::map > groups; // actual IntObject's visible on screen - std::vector< CBuildingRect * > buildings; + std::vector> buildings; const CGTownInstance * town; @@ -139,7 +147,7 @@ class CCastleBuildings : public CIntObject public: CBuildingRect * selectedBuilding; - CCastleBuildings(const CGTownInstance* town); + CCastleBuildings(const CGTownInstance * town); ~CCastleBuildings(); void enterDwelling(int level); @@ -157,18 +165,17 @@ public: class CCreaInfo : public CIntObject { const CGTownInstance * town; - const CCreature *creature; + const CCreature * creature; int level; bool showAvailable; - CAnimImage *picture; - CLabel * label; + std::shared_ptr picture; + std::shared_ptr label; - int AddToString(std::string from, std::string & to, int numb); std::string genGrowthText(); public: - CCreaInfo(Point position, const CGTownInstance *Town, int Level, bool compact=false, bool showAvailable=false); + CCreaInfo(Point position, const CGTownInstance * Town, int Level, bool compact=false, bool showAvailable=false); void update(); void hover(bool on) override; @@ -179,48 +186,53 @@ public: /// Town hall and fort icons for town screen class CTownInfo : public CIntObject { - const CGTownInstance *town; - const CBuilding *building; + const CGTownInstance * town; + const CBuilding * building; public: - CAnimImage * picture; + std::shared_ptr picture; //if (townHall) hall-capital else fort - castle - CTownInfo(int posX, int posY, const CGTownInstance* town, bool townHall); + CTownInfo(int posX, int posY, const CGTownInstance * town, bool townHall); void hover(bool on) override; void clickRight(tribool down, bool previousState) override; }; /// Class which manages the castle window -class CCastleInterface : public CWindowObject, public CWindowWithGarrison +class CCastleInterface : public CWindowObject, public CGarrisonHolder { - CLabel *title; - CLabel *income; - CAnimImage *icon; + std::shared_ptr title; + std::shared_ptr income; + std::shared_ptr icon; - CPicture * panel; - CResDataBar *resdatabar; - CGStatusBar * statusbar; + std::shared_ptr panel; + std::shared_ptr resdatabar; + std::shared_ptr statusbar; - CTownInfo *hall, *fort; + std::shared_ptr hall; + std::shared_ptr fort; - CButton *exit; - CButton *split; - CButton * fastArmyPurhase; + std::shared_ptr exit; + std::shared_ptr split; + std::shared_ptr fastArmyPurhase; - std::vector creainfo;//small icons of creatures (bottom-left corner); + std::vector> creainfo;//small icons of creatures (bottom-left corner); public: - CTownList * townlist; + std::shared_ptr townlist; //TODO: move to private const CGTownInstance * town; - HeroSlots *heroes; - CCastleBuildings *builds; + std::shared_ptr heroes; + std::shared_ptr builds; + + std::shared_ptr garr; //from - previously selected castle (if any) CCastleInterface(const CGTownInstance * Town, const CGTownInstance * from = nullptr); ~CCastleInterface(); + virtual void updateGarrisons() override; + void castleTeleport(int where); void townChange(); void keyPressed(const SDL_KeyboardEvent & key) override; @@ -233,13 +245,17 @@ public: /// Hall window where you can build things class CHallInterface : public CWindowObject { - /// Building box from town hall (building icon + subtitle) class CBuildingBox : public CIntObject { const CGTownInstance * town; const CBuilding * building; ui32 state;//Buildings::EBuildStructure enum + + std::shared_ptr header; + std::shared_ptr icon; + std::shared_ptr mark; + std::shared_ptr name; public: CBuildingBox(int x, int y, const CGTownInstance * Town, const CBuilding * Building); void hover(bool on) override; @@ -248,11 +264,11 @@ class CHallInterface : public CWindowObject }; const CGTownInstance * town; - std::vector< std::vector >boxes; - CLabel *title; - CGStatusBar *statusBar; - CMinorResDataBar * resdatabar; - CButton *exit; + std::vector>> boxes; + std::shared_ptr title; + std::shared_ptr resdatabar; + std::shared_ptr statusbar; + std::shared_ptr exit; public: CHallInterface(const CGTownInstance * Town); @@ -261,8 +277,18 @@ public: /// Window where you can decide to buy a building or not class CBuildWindow: public CWindowObject { - const CGTownInstance *town; - const CBuilding *building; + const CGTownInstance * town; + const CBuilding * building; + + std::shared_ptr icon; + std::shared_ptr statusbar; + std::shared_ptr name; + std::shared_ptr description; + std::shared_ptr stateText; + std::shared_ptr cost; + + std::shared_ptr buy; + std::shared_ptr cancel; std::string getTextForState(int state); void buyFunc(); @@ -274,8 +300,8 @@ public: class LabeledValue : public CIntObject { std::string hoverText; - CLabel *name; - CLabel *value; + std::shared_ptr name; + std::shared_ptr value; void init(std::string name, std::string descr, int min, int max); public: @@ -289,14 +315,16 @@ class CFortScreen : public CWindowObject { class RecruitArea : public CIntObject { - const CGTownInstance *town; + const CGTownInstance * town; int level; std::string hoverText; - CLabel * availableCount; + std::shared_ptr availableCount; - std::vector values; - CPicture *icons; + std::vector> values; + std::shared_ptr icons; + std::shared_ptr buildingIcon; + std::shared_ptr buildingName; const CCreature * getMyCreature(); const CBuilding * getMyBuilding(); @@ -308,13 +336,13 @@ class CFortScreen : public CWindowObject void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; }; - CLabel *title; - std::vector recAreas; - CMinorResDataBar * resdatabar; - CGStatusBar *statusBar; - CButton *exit; + std::shared_ptr title; + std::vector> recAreas; + std::shared_ptr resdatabar; + std::shared_ptr statusbar; + std::shared_ptr exit; - std::string getBgName(const CGTownInstance *town); + std::string getBgName(const CGTownInstance * town); public: CFortScreen(const CGTownInstance * town); @@ -327,8 +355,8 @@ class CMageGuildScreen : public CWindowObject { class Scroll : public CIntObject { - const CSpell *spell; - CAnimImage *image; + const CSpell * spell; + std::shared_ptr image; public: Scroll(Point position, const CSpell *Spell); @@ -336,11 +364,13 @@ class CMageGuildScreen : public CWindowObject void clickRight(tribool down, bool previousState) override; void hover(bool on) override; }; - CPicture *window; - CButton *exit; - std::vector spells; - CMinorResDataBar * resdatabar; - CGStatusBar *statusBar; + std::shared_ptr window; + std::shared_ptr exit; + std::vector> spells; + std::vector> emptyScrolls; + + std::shared_ptr resdatabar; + std::shared_ptr statusbar; public: CMageGuildScreen(CCastleInterface * owner,std::string image); @@ -349,13 +379,15 @@ public: /// The blacksmith window where you can buy available in town war machine class CBlacksmithDialog : public CWindowObject { - CButton *buy, *cancel; - CPicture *animBG; - CCreatureAnim * anim; - CLabel * title; - CLabel * costText; - CLabel * costValue; - CGStatusBar *statusBar; + std::shared_ptr buy; + std::shared_ptr cancel; + std::shared_ptr animBG; + std::shared_ptr anim; + std::shared_ptr title; + std::shared_ptr costIcon; + std::shared_ptr costText; + std::shared_ptr costValue; + std::shared_ptr statusbar; public: CBlacksmithDialog(bool possible, CreatureID creMachineID, ArtifactID aid, ObjectInstanceID hid); diff --git a/client/windows/CCreatureWindow.cpp b/client/windows/CCreatureWindow.cpp index f45ea8590..51786cde1 100644 --- a/client/windows/CCreatureWindow.cpp +++ b/client/windows/CCreatureWindow.cpp @@ -34,8 +34,9 @@ using namespace CSDL_Ext; class CCreatureArtifactInstance; class CSelectableSkill; -struct StackWindowInfo +class UnitView { +public: // helper structs struct CommanderLevelInfo { @@ -68,69 +69,787 @@ struct StackWindowInfo unsigned int creatureCount; bool popupWindow; - StackWindowInfo(); + UnitView() + : creature(nullptr), + commander(nullptr), + stackNode(nullptr), + stack(nullptr), + owner(nullptr), + creatureCount(0), + popupWindow(false) + { + } + + + std::string getName() const + { + if(commander) + return commander->type->nameSing; + else + return creature->namePl; + } +private: + }; -namespace +CCommanderSkillIcon::CCommanderSkillIcon(std::shared_ptr object_, std::function callback) + : object(), + callback(callback) { - namespace EStat + pos = object_->pos; + setObject(object_); +} + +void CCommanderSkillIcon::setObject(std::shared_ptr newObject) +{ + if(object) + removeChild(object.get()); + object = newObject; + addChild(object.get()); + object->moveTo(pos.topLeft()); + redraw(); +} + +void CCommanderSkillIcon::clickLeft(tribool down, bool previousState) +{ + if(down) + callback(); +} + +void CCommanderSkillIcon::clickRight(tribool down, bool previousState) +{ + if(down) + LRClickableAreaWText::clickRight(down, previousState); +} + +static std::string skillToFile(int skill, int level, bool selected) +{ + // FIXME: is this a correct hadling? + // level 0 = skill not present, use image with "no" suffix + // level 1-5 = skill available, mapped to images indexed as 0-4 + // selecting skill means that it will appear one level higher (as if alredy upgraded) + std::string file = "zvs/Lib1.res/_"; + switch (skill) { - enum EStat - { - ATTACK, - DEFENCE, - SHOTS, - DAMAGE, - HEALTH, - HEALTH_LEFT, - SPEED, - MANA - }; + case ECommander::ATTACK: + file += "AT"; + break; + case ECommander::DEFENSE: + file += "DF"; + break; + case ECommander::HEALTH: + file += "HP"; + break; + case ECommander::DAMAGE: + file += "DM"; + break; + case ECommander::SPEED: + file += "SP"; + break; + case ECommander::SPELL_POWER: + file += "MP"; + break; + } + std::string sufix; + if (selected) + level++; // UI will display resulting level + if (level == 0) + sufix = "no"; //not avaliable - no number + else + sufix = boost::lexical_cast(level-1); + if (selected) + sufix += "="; //level-up highlight + + return file + sufix + ".bmp"; +} + +CStackWindow::CWindowSection::CWindowSection(CStackWindow * parent, std::string backgroundPath, int yOffset) + : parent(parent) +{ + pos.y += yOffset; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + if(!backgroundPath.empty()) + { + background = std::make_shared("stackWindow/" + backgroundPath); + pos.w = background->pos.w; + pos.h = background->pos.h; } } -StackWindowInfo::StackWindowInfo(): - creature(nullptr), - commander(nullptr), - stackNode(nullptr), - stack(nullptr), - owner(nullptr), - creatureCount(0), - popupWindow(false) +CStackWindow::ActiveSpellsSection::ActiveSpellsSection(CStackWindow * owner, int yOffset) + : CWindowSection(owner, "spell-effects", yOffset) { + static const Point firstPos(6, 2); // position of 1st spell box + static const Point offset(54, 0); // offset of each spell box from previous + + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + const CStack * battleStack = parent->info->stack; + + assert(battleStack); // Section should be created only for battles + + //spell effects + int printed=0; //how many effect pics have been printed + std::vector spells = battleStack->activeSpells(); + for(si32 effect : spells) + { + const CSpell * sp = CGI->spellh->objects[effect]; + + std::string spellText; + + //not all effects have graphics (for eg. Acid Breath) + //for modded spells iconEffect is added to SpellInt.def + const bool hasGraphics = (effect < SpellID::THUNDERBOLT) || (effect >= SpellID::AFTER_LAST); + + if (hasGraphics) + { + spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds." + boost::replace_first(spellText, "%s", sp->name); + //FIXME: support permanent duration + int duration = battleStack->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT,effect))->turnsRemain; + boost::replace_first(spellText, "%d", boost::lexical_cast(duration)); + + spellIcons.push_back(std::make_shared("SpellInt", effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed)); + clickableAreas.push_back(std::make_shared(Rect(firstPos + offset * printed, Point(50, 38)), spellText, spellText)); + if(++printed >= 8) // interface limit reached + break; + } + } } -void CStackWindow::CWindowSection::createBackground(std::string path) +CStackWindow::BonusLineSection::BonusLineSection(CStackWindow * owner, size_t lineIndex) + : CWindowSection(owner, "bonus-effects", 0) { - CPicture * background = new CPicture("stackWindow/" + path); - pos = background->pos; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + static const std::array offset = + { + Point(6, 4), + Point(214, 4) + }; + + for(size_t leftRight : {0, 1}) + { + auto position = offset[leftRight]; + size_t bonusIndex = lineIndex * 2 + leftRight; + + if(parent->activeBonuses.size() > bonusIndex) + { + BonusInfo & bi = parent->activeBonuses[bonusIndex]; + icon[leftRight] = std::make_shared(bi.imagePath, position.x, position.y); + name[leftRight] = std::make_shared(position.x + 60, position.y + 2, FONT_SMALL, TOPLEFT, Colors::WHITE, bi.name); + description[leftRight] = std::make_shared(Rect(position.x + 60, position.y + 17, 137, 30), FONT_SMALL, TOPLEFT, Colors::WHITE, bi.description); + } + } } -void CStackWindow::CWindowSection::printStatString(int index, std::string name, std::string value) +CStackWindow::BonusesSection::BonusesSection(CStackWindow * owner, int yOffset, boost::optional preferredSize) + : CWindowSection(owner, "", yOffset) { - new CLabel(145, 32 + index*19, FONT_SMALL, TOPLEFT, Colors::WHITE, name); - new CLabel(307, 48 + index*19, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, value); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + // size of single image for an item + static const int itemHeight = 59; + + size_t totalSize = (owner->activeBonuses.size() + 1) / 2; + size_t visibleSize = preferredSize ? preferredSize.get() : std::min(3, totalSize); + + pos.w = owner->pos.w; + pos.h = itemHeight * visibleSize; + + auto onCreate = [=](size_t index) -> std::shared_ptr + { + return std::make_shared(owner, index); + }; + + lines = std::make_shared(onCreate, Point(0, 0), Point(0, itemHeight), visibleSize, totalSize, 0, 1, Rect(pos.w - 15, 0, pos.h, pos.h)); } -void CStackWindow::CWindowSection::printStatRange(int index, std::string name, int min, int max) +CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset) + : CWindowSection(owner, "button-panel", yOffset) { - if(min != max) - printStatString(index, name, boost::str(boost::format("%d - %d") % min % max)); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + if(parent->info->dismissInfo && parent->info->dismissInfo->callback) + { + auto onDismiss = [=]() + { + parent->info->dismissInfo->callback(); + parent->close(); + }; + auto onClick = [=] () + { + LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[12], onDismiss, nullptr); + }; + dismiss = std::make_shared(Point(5, 5),"IVIEWCR2.DEF", CGI->generaltexth->zelp[445], onClick, SDLK_d); + } + + if(parent->info->upgradeInfo && !parent->info->commander) + { + // used space overlaps with commander switch button + // besides - should commander really be upgradeable? + + UnitView::StackUpgradeInfo & upgradeInfo = parent->info->upgradeInfo.get(); + const size_t buttonsToCreate = std::min(upgradeInfo.info.newID.size(), upgrade.size()); + + for(size_t buttonIndex = 0; buttonIndex < buttonsToCreate; buttonIndex++) + { + TResources totalCost = upgradeInfo.info.cost[buttonIndex] * parent->info->creatureCount; + + auto onUpgrade = [=]() + { + upgradeInfo.callback(upgradeInfo.info.newID[buttonIndex]); + parent->close(); + }; + auto onClick = [=]() + { + std::vector> resComps; + for(TResources::nziterator i(totalCost); i.valid(); i++) + { + resComps.push_back(std::make_shared(CComponent::resource, i->resType, i->resVal)); + } + + if(LOCPLINT->cb->getResourceAmount().canAfford(totalCost)) + { + LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[207], onUpgrade, nullptr, resComps); + } + else + { + LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[314], resComps); + } + }; + auto upgradeBtn = std::make_shared(Point(221 + buttonIndex * 40, 5), "stackWindow/upgradeButton", CGI->generaltexth->zelp[446], onClick, SDLK_1); + + upgradeBtn->addOverlay(std::make_shared("CPRSMALL", VLC->creh->creatures[upgradeInfo.info.newID[buttonIndex]]->iconIndex)); + + upgrade[buttonIndex] = upgradeBtn; + } + } + + if(parent->info->commander) + { + for(size_t buttonIndex = 0; buttonIndex < 2; buttonIndex++) + { + std::string btnIDs[2] = { "showSkills", "showBonuses" }; + auto onSwitch = [buttonIndex, this]() + { + logAnim->debug("Switch %d->%d", parent->activeTab, buttonIndex); + + parent->switchButtons[parent->activeTab]->enable(); + parent->commanderTab->setActive(buttonIndex); + parent->switchButtons[buttonIndex]->disable(); + parent->redraw(); // FIXME: enable/disable don't redraw screen themselves + }; + + const JsonNode & text = VLC->generaltexth->localizedTexts["creatureWindow"][btnIDs[buttonIndex]]; + parent->switchButtons[buttonIndex] = std::make_shared(Point(302 + buttonIndex*40, 5), "stackWindow/upgradeButton", CButton::tooltip(text), onSwitch); + parent->switchButtons[buttonIndex]->addOverlay(std::make_shared("stackWindow/switchModeIcons", buttonIndex)); + } + parent->switchButtons[parent->activeTab]->disable(); + } + + exit = std::make_shared(Point(382, 5), "hsbtns.def", CGI->generaltexth->zelp[447], [=](){ parent->close(); }, SDLK_RETURN); + exit->assignedKeys.insert(SDLK_ESCAPE); +} + +CStackWindow::CommanderMainSection::CommanderMainSection(CStackWindow * owner, int yOffset) + : CWindowSection(owner, "commander-bg", yOffset) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + auto getSkillPos = [](int index) + { + return Point(10 + 80 * (index%3), 20 + 80 * (index/3)); + }; + + auto getSkillImage = [this](int skillIndex) -> std::string + { + bool selected = ((parent->selectedSkill == skillIndex) && parent->info->levelupInfo ); + return skillToFile(skillIndex, parent->info->commander->secondarySkills[skillIndex], selected); + }; + + auto getSkillDescription = [this](int skillIndex) -> std::string + { + if(CGI->generaltexth->znpc00.size() == 0) + return ""; + + return CGI->generaltexth->znpc00[151 + (12 * skillIndex) + (parent->info->commander->secondarySkills[skillIndex] * 2)]; + }; + + for(int index = ECommander::ATTACK; index <= ECommander::SPELL_POWER; ++index) + { + Point skillPos = getSkillPos(index); + + auto icon = std::make_shared(std::make_shared(getSkillImage(index), skillPos.x, skillPos.y), [=]() + { + LOCPLINT->showInfoDialog(getSkillDescription(index)); + }); + + icon->text = getSkillDescription(index); //used to handle right click description via LRClickableAreaWText::ClickRight() + + if(parent->selectedSkill == index) + parent->selectedIcon = icon; + + if(parent->info->levelupInfo && vstd::contains(parent->info->levelupInfo->skills, index)) // can be upgraded - enable selection switch + { + if(parent->selectedSkill == index) + parent->setSelection(index, icon); + + icon->callback = [=]() + { + parent->setSelection(index, icon); + }; + } + + skillIcons.push_back(icon); + } + + auto getArtifactPos = [](int index) + { + return Point(269 + 47 * (index % 3), 22 + 47 * (index / 3)); + }; + + for(auto equippedArtifact : parent->info->commander->artifactsWorn) + { + Point artPos = getArtifactPos(equippedArtifact.first); + auto artPlace = std::make_shared(artPos, parent->info->owner, equippedArtifact.first, equippedArtifact.second.artifact); + artifacts.push_back(artPlace); + } + + if(parent->info->levelupInfo) + { + abilitiesBackground = std::make_shared("stackWindow/commander-abilities.png"); + abilitiesBackground->moveBy(Point(0, pos.h)); + + size_t abilitiesCount = boost::range::count_if(parent->info->levelupInfo->skills, [](ui32 skillID) + { + return skillID >= 100; + }); + + auto onCreate = [=](int index)->std::shared_ptr + { + for(auto skillID : parent->info->levelupInfo->skills) + { + if(index == 0 && skillID >= 100) + { + const auto bonus = CGI->creh->skillRequirements[skillID-100].first; + const CStackInstance * stack = parent->info->commander; + auto icon = std::make_shared(std::make_shared(stack->bonusToGraphics(bonus)), [](){}); + icon->callback = [=]() + { + parent->setSelection(skillID, icon); + }; + icon->text = stack->bonusToString(bonus, true); + icon->hoverText = stack->bonusToString(bonus, false); + + return icon; + } + if(skillID >= 100) + index--; + } + return nullptr; + }; + + abilities = std::make_shared(onCreate, Point(38, 3+pos.h), Point(63, 0), 6, abilitiesCount); + + leftBtn = std::make_shared(Point(10, pos.h + 6), "hsbtns3.def", CButton::tooltip(), [=](){ abilities->moveToPrev(); }, SDLK_LEFT); + rightBtn = std::make_shared(Point(411, pos.h + 6), "hsbtns5.def", CButton::tooltip(), [=](){ abilities->moveToNext(); }, SDLK_RIGHT); + + if(abilitiesCount <= 6) + { + leftBtn->block(true); + rightBtn->block(true); + } + + pos.h += abilitiesBackground->pos.h; + } +} + +CStackWindow::MainSection::MainSection(CStackWindow * owner, int yOffset, bool showExp, bool showArt) + : CWindowSection(owner, getBackgroundName(showExp, showArt), yOffset) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + statNames = + { + CGI->generaltexth->primarySkillNames[0], //ATTACK + CGI->generaltexth->primarySkillNames[1],//DEFENCE + CGI->generaltexth->allTexts[198],//SHOTS + CGI->generaltexth->allTexts[199],//DAMAGE + + CGI->generaltexth->allTexts[388],//HEALTH + CGI->generaltexth->allTexts[200],//HEALTH_LEFT + CGI->generaltexth->zelp[441].first,//SPEED + CGI->generaltexth->allTexts[399]//MANA + }; + + statFormats = + { + "%d (%d)", + "%d (%d)", + "%d (%d)", + "%d - %d", + + "%d (%d)", + "%d (%d)", + "%d (%d)", + "%d (%d)" + }; + + animation = std::make_shared(5, 41, parent->info->creature); + + if(parent->info->stackNode != nullptr && parent->info->commander == nullptr) + { + //normal stack, not a commander and not non-existing stack (e.g. recruitment dialog) + animation->setAmount(parent->info->creatureCount); + } + + name = std::make_shared(215, 12, FONT_SMALL, CENTER, Colors::YELLOW, parent->info->getName()); + + int dmgMultiply = 1; + if(parent->info->owner && parent->info->stackNode->hasBonusOfType(Bonus::SIEGE_WEAPON)) + dmgMultiply += parent->info->owner->getPrimSkillLevel(PrimarySkill::ATTACK); + + icons = std::make_shared("stackWindow/icons", 117, 32); + + const CStack * battleStack = parent->info->stack; + + morale = std::make_shared(true, genRect(42, 42, 321, 110)); + luck = std::make_shared(false, genRect(42, 42, 375, 110)); + + if(battleStack != nullptr) // in battle + { + addStatLabel(EStat::ATTACK, parent->info->creature->getAttack(battleStack->isShooter()), battleStack->getAttack(battleStack->isShooter())); + addStatLabel(EStat::DEFENCE, parent->info->creature->getDefence(battleStack->isShooter()), battleStack->getDefence(battleStack->isShooter())); + addStatLabel(EStat::DAMAGE, parent->info->stackNode->getMinDamage(battleStack->isShooter()) * dmgMultiply, battleStack->getMaxDamage(battleStack->isShooter()) * dmgMultiply); + addStatLabel(EStat::HEALTH, parent->info->creature->MaxHealth(), battleStack->MaxHealth()); + addStatLabel(EStat::SPEED, parent->info->creature->Speed(), battleStack->Speed()); + + if(battleStack->isShooter()) + addStatLabel(EStat::SHOTS, battleStack->shots.total(), battleStack->shots.available()); + if(battleStack->isCaster()) + addStatLabel(EStat::MANA, battleStack->casts.total(), battleStack->casts.available()); + addStatLabel(EStat::HEALTH_LEFT, battleStack->getFirstHPleft()); + + morale->set(battleStack); + luck->set(battleStack); + } else - printStatString(index, name, boost::str(boost::format("%d") % min)); + { + const bool shooter = parent->info->stackNode->hasBonusOfType(Bonus::SHOOTER) && parent->info->stackNode->valOfBonuses(Bonus::SHOTS); + const bool caster = parent->info->stackNode->valOfBonuses(Bonus::CASTS); + + addStatLabel(EStat::ATTACK, parent->info->creature->getAttack(shooter), parent->info->stackNode->getAttack(shooter)); + addStatLabel(EStat::DEFENCE, parent->info->creature->getDefence(shooter), parent->info->stackNode->getDefence(shooter)); + addStatLabel(EStat::DAMAGE, parent->info->stackNode->getMinDamage(shooter) * dmgMultiply, parent->info->stackNode->getMaxDamage(shooter) * dmgMultiply); + addStatLabel(EStat::HEALTH, parent->info->creature->MaxHealth(), parent->info->stackNode->MaxHealth()); + addStatLabel(EStat::SPEED, parent->info->creature->Speed(), parent->info->stackNode->Speed()); + + if(shooter) + addStatLabel(EStat::SHOTS, parent->info->stackNode->valOfBonuses(Bonus::SHOTS)); + if(caster) + addStatLabel(EStat::MANA, parent->info->stackNode->valOfBonuses(Bonus::CASTS)); + + morale->set(parent->info->stackNode); + luck->set(parent->info->stackNode); + } + + if(showExp) + { + const CStackInstance * stack = parent->info->stackNode; + Point pos = showArt ? Point(321, 32) : Point(347, 32); + if(parent->info->commander) + { + const CCommanderInstance * commander = parent->info->commander; + expRankIcon = std::make_shared("PSKIL42", 4, 0, pos.x, pos.y); + + auto area = std::make_shared(Rect(pos.x, pos.y, 44, 44), CComponent::experience); + expArea = area; + area->text = CGI->generaltexth->allTexts[2]; + area->bonusValue = commander->getExpRank(); + boost::replace_first(area->text, "%d", boost::lexical_cast(commander->getExpRank())); + boost::replace_first(area->text, "%d", boost::lexical_cast(CGI->heroh->reqExp(commander->getExpRank() + 1))); + boost::replace_first(area->text, "%d", boost::lexical_cast(commander->experience)); + } + else + { + expRankIcon = std::make_shared("stackWindow/levels", stack->getExpRank(), 0, pos.x, pos.y); + expArea = std::make_shared(Rect(pos.x, pos.y, 44, 44)); + expArea->text = parent->generateStackExpDescription(); + } + expLabel = std::make_shared( + pos.x + 21, pos.y + 52, FONT_SMALL, CENTER, Colors::WHITE, + makeNumberShort(stack->experience, 6)); + } + + if(showArt) + { + Point pos = showExp ? Point(375, 32) : Point(347, 32); + // ALARMA: do not refactor this into a separate function + // otherwise, artifact icon is drawn near the hero's portrait + // this is really strange + auto art = parent->info->stackNode->getArt(ArtifactPosition::CREATURE_SLOT); + if(art) + { + parent->stackArtifactIcon = std::make_shared("ARTIFACT", art->artType->iconIndex, 0, pos.x, pos.y); + parent->stackArtifactHelp = std::make_shared(Rect(pos, Point(44, 44)), CComponent::artifact); + parent->stackArtifactHelp->type = art->artType->id; + const JsonNode & text = VLC->generaltexth->localizedTexts["creatureWindow"]["returnArtifact"]; + + if(parent->info->owner) + { + parent->stackArtifactButton = std::make_shared( + Point(pos.x - 2 , pos.y + 46), "stackWindow/cancelButton", + CButton::tooltip(text), [=]() + { + parent->removeStackArtifact(ArtifactPosition::CREATURE_SLOT); + }); + } + } + } } -void CStackWindow::CWindowSection::printStatBase(int index, std::string name, int base, int current) + +std::string CStackWindow::MainSection::getBackgroundName(bool showExp, bool showArt) { - if(base != current) - printStatString(index, name, boost::str(boost::format("%d (%d)") % base % current)); + if(showExp && showArt) + return "info-panel-2"; + else if(showExp || showArt) + return "info-panel-1"; else - printStatString(index, name, boost::str(boost::format("%d") % base)); + return "info-panel-0"; } -void CStackWindow::CWindowSection::printStat(int index, std::string name, int value) +void CStackWindow::MainSection::addStatLabel(EStat index, int64_t value1, int64_t value2) { - printStatBase(index, name, value, value); + const auto title = statNames.at(static_cast(index)); + stats.push_back(std::make_shared(145, 32 + (int)index*19, FONT_SMALL, TOPLEFT, Colors::WHITE, title)); + + const bool useRange = value1 != value2; + std::string formatStr = useRange ? statFormats.at(static_cast(index)) : "%d"; + + boost::format fmt(formatStr); + fmt % value1; + if(useRange) + fmt % value2; + + stats.push_back(std::make_shared(307, 48 + (int)index*19, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, fmt.str())); +} + +void CStackWindow::MainSection::addStatLabel(EStat index, int64_t value) +{ + addStatLabel(index, value, value); +} + +CStackWindow::CStackWindow(const CStack * stack, bool popup) + : CWindowObject(BORDERED | (popup ? RCLICK_POPUP : 0)), + info(new UnitView()) +{ + info->stack = stack; + info->stackNode = stack->base; + info->creature = stack->type; + info->creatureCount = stack->getCount(); + info->popupWindow = popup; + init(); +} + +CStackWindow::CStackWindow(const CCreature * creature, bool popup) + : CWindowObject(BORDERED | (popup ? RCLICK_POPUP : 0)), + info(new UnitView()) +{ + info->creature = creature; + info->popupWindow = popup; + init(); +} + +CStackWindow::CStackWindow(const CStackInstance * stack, bool popup) + : CWindowObject(BORDERED | (popup ? RCLICK_POPUP : 0)), + info(new UnitView()) +{ + info->stackNode = stack; + info->creature = stack->type; + info->creatureCount = stack->count; + info->popupWindow = popup; + info->owner = dynamic_cast (stack->armyObj); + init(); +} + +CStackWindow::CStackWindow(const CStackInstance * stack, std::function dismiss, const UpgradeInfo & upgradeInfo, std::function callback) + : CWindowObject(BORDERED), + info(new UnitView()) +{ + info->stackNode = stack; + info->creature = stack->type; + info->creatureCount = stack->count; + + info->upgradeInfo = boost::make_optional(UnitView::StackUpgradeInfo()); + info->dismissInfo = boost::make_optional(UnitView::StackDismissInfo()); + info->upgradeInfo->info = upgradeInfo; + info->upgradeInfo->callback = callback; + info->dismissInfo->callback = dismiss; + info->owner = dynamic_cast (stack->armyObj); + init(); +} + +CStackWindow::CStackWindow(const CCommanderInstance * commander, bool popup) + : CWindowObject(BORDERED | (popup ? RCLICK_POPUP : 0)), + info(new UnitView()) +{ + info->stackNode = commander; + info->creature = commander->type; + info->commander = commander; + info->creatureCount = 1; + info->popupWindow = popup; + info->owner = dynamic_cast (commander->armyObj); + init(); +} + +CStackWindow::CStackWindow(const CCommanderInstance * commander, std::vector &skills, std::function callback) + : CWindowObject(BORDERED), + info(new UnitView()) +{ + info->stackNode = commander; + info->creature = commander->type; + info->commander = commander; + info->creatureCount = 1; + info->levelupInfo = boost::make_optional(UnitView::CommanderLevelInfo()); + info->levelupInfo->skills = skills; + info->levelupInfo->callback = callback; + info->owner = dynamic_cast (commander->armyObj); + init(); +} + +CStackWindow::~CStackWindow() +{ + if(info->levelupInfo && !info->levelupInfo->skills.empty()) + info->levelupInfo->callback(vstd::find_pos(info->levelupInfo->skills, selectedSkill)); +} + +void CStackWindow::init() +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + if(!info->stackNode) + info->stackNode = new CStackInstance(info->creature, 1);// FIXME: free data + + selectedIcon = nullptr; + selectedSkill = -1; + if(info->levelupInfo && !info->levelupInfo->skills.empty()) + selectedSkill = info->levelupInfo->skills.front(); + + activeTab = 0; + + initBonusesList(); + initSections(); +} + +void CStackWindow::initBonusesList() +{ + BonusList output, input; + input = *(info->stackNode->getBonuses(CSelector(Bonus::Permanent), Selector::all)); + + while(!input.empty()) + { + auto b = input.front(); + output.push_back(std::make_shared(*b)); + output.back()->val = input.valOfBonuses(Selector::typeSubtype(b->type, b->subtype)); //merge multiple bonuses into one + input.remove_if (Selector::typeSubtype(b->type, b->subtype)); //remove used bonuses + } + + BonusInfo bonusInfo; + for(auto b : output) + { + bonusInfo.name = info->stackNode->bonusToString(b, false); + bonusInfo.description = info->stackNode->bonusToString(b, true); + bonusInfo.imagePath = info->stackNode->bonusToGraphics(b); + + //if it's possible to give any description or image for this kind of bonus + //TODO: figure out why half of bonuses don't have proper description + if(b->type == Bonus::MAGIC_RESISTANCE || (b->type == Bonus::SECONDARY_SKILL_PREMY && b->subtype == SecondarySkill::RESISTANCE)) + continue; + if(!bonusInfo.name.empty() || !bonusInfo.imagePath.empty()) + activeBonuses.push_back(bonusInfo); + } + + //handle Magic resistance separately :/ + int magicResistance = info->stackNode->magicResistance();//both MAGIC_RESITANCE and SECONDARY_SKILL_PREMY as one entry + + if(magicResistance) + { + BonusInfo bonusInfo; + auto b = std::make_shared(); + b->type = Bonus::MAGIC_RESISTANCE; + + bonusInfo.name = VLC->getBth()->bonusToString(b, info->stackNode, false); + bonusInfo.description = VLC->getBth()->bonusToString(b, info->stackNode, true); + bonusInfo.imagePath = info->stackNode->bonusToGraphics(b); + activeBonuses.push_back(bonusInfo); + } +} + +void CStackWindow::initSections() +{ + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + + bool showArt = CGI->modh->modules.STACK_ARTIFACT && info->commander == nullptr && info->stackNode; + bool showExp = (CGI->modh->modules.STACK_EXP || info->commander != nullptr) && info->stackNode; + + mainSection = std::make_shared(this, pos.h, showExp, showArt); + + pos.w = mainSection->pos.w; + pos.h += mainSection->pos.h; + + if(info->stack) // in battle + { + activeSpellsSection = std::make_shared(this, pos.h); + pos.h += activeSpellsSection->pos.h; + } + + if(info->commander) + { + auto onCreate = [=](size_t index) -> std::shared_ptr + { + auto obj = switchTab(index); + + if(obj) + { + obj->activate(); + obj->recActions |= (UPDATE | SHOWALL); + } + return obj; + }; + + auto deactivateObj = [=](std::shared_ptr obj) + { + obj->deactivate(); + obj->recActions &= ~(UPDATE | SHOWALL); + }; + + commanderMainSection = std::make_shared(this, 0); + + auto size = boost::make_optional((info->levelupInfo) ? 4 : 3); + commanderBonusesSection = std::make_shared(this, 0, size); + deactivateObj(commanderBonusesSection); + + commanderTab = std::make_shared(onCreate, Point(0, pos.h), 0); + + pos.h += commanderMainSection->pos.h; + } + + if(!info->commander && !activeBonuses.empty()) + { + bonusesSection = std::make_shared(this, pos.h); + pos.h += bonusesSection->pos.h; + } + + if(!info->popupWindow) + { + buttonsSection = std::make_shared(this, pos.h); + pos.h += buttonsSection->pos.h; + //FIXME: add status bar to image? + } + updateShadow(); + pos = center(pos); } std::string CStackWindow::generateStackExpDescription() @@ -176,376 +895,11 @@ std::string CStackWindow::generateStackExpDescription() return expText; } -void CStackWindow::removeStackArtifact(ArtifactPosition pos) -{ - auto art = info->stackNode->getArt(ArtifactPosition::CREATURE_SLOT); - if(!art) - { - logGlobal->error("Attempt to remove missing artifact"); - return; - } - LOCPLINT->cb->swapArtifacts(ArtifactLocation(info->stackNode, pos), - ArtifactLocation(info->owner, art->firstBackpackSlot(info->owner))); - stackArtifactButton.reset(); - stackArtifactHelp.reset(); - stackArtifactIcon.reset(); - redraw(); -} - -void CStackWindow::CWindowSection::createStackInfo(bool showExp, bool showArt) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - if (showExp && showArt) - createBackground("info-panel-2"); - else if (showExp || showArt) - createBackground("info-panel-1"); - else - createBackground("info-panel-0"); - - auto pic = new CCreaturePic(5, 41, parent->info->creature); - - if (parent->info->stackNode != nullptr && parent->info->commander == nullptr) - { - //normal stack, not a commander and not non-existing stack (e.g. recruitment dialog) - pic->setAmount(parent->info->creatureCount); - } - - std::string visibleName; - if (parent->info->commander != nullptr) - visibleName = parent->info->commander->type->nameSing; - else - visibleName = parent->info->creature->namePl; - new CLabel(215, 12, FONT_SMALL, CENTER, Colors::YELLOW, visibleName); - - int dmgMultiply = 1; - if(parent->info->owner && parent->info->stackNode->hasBonusOfType(Bonus::SIEGE_WEAPON)) - dmgMultiply += parent->info->owner->getPrimSkillLevel(PrimarySkill::ATTACK); - - new CPicture("stackWindow/icons", 117, 32); - - const CStack * battleStack = parent->info->stack; - - auto morale = new MoraleLuckBox(true, genRect(42, 42, 321, 110)); - auto luck = new MoraleLuckBox(false, genRect(42, 42, 375, 110)); - - if(battleStack != nullptr) // in battle - { - printStatBase(EStat::ATTACK, CGI->generaltexth->primarySkillNames[0], parent->info->creature->getAttack(battleStack->isShooter()), battleStack->getAttack(battleStack->isShooter())); - printStatBase(EStat::DEFENCE, CGI->generaltexth->primarySkillNames[1], parent->info->creature->getDefence(battleStack->isShooter()), battleStack->getDefence(battleStack->isShooter())); - printStatRange(EStat::DAMAGE, CGI->generaltexth->allTexts[199], parent->info->stackNode->getMinDamage(battleStack->isShooter()) * dmgMultiply, battleStack->getMaxDamage(battleStack->isShooter()) * dmgMultiply); - printStatBase(EStat::HEALTH, CGI->generaltexth->allTexts[388], parent->info->creature->MaxHealth(), battleStack->MaxHealth()); - printStatBase(EStat::SPEED, CGI->generaltexth->zelp[441].first, parent->info->creature->Speed(), battleStack->Speed()); - - if(battleStack->isShooter()) - printStatBase(EStat::SHOTS, CGI->generaltexth->allTexts[198], battleStack->shots.total(), battleStack->shots.available()); - if(battleStack->isCaster()) - printStatBase(EStat::MANA, CGI->generaltexth->allTexts[399], battleStack->casts.total(), battleStack->casts.available()); - printStat(EStat::HEALTH_LEFT, CGI->generaltexth->allTexts[200], battleStack->getFirstHPleft()); - - morale->set(battleStack); - luck->set(battleStack); - } - else - { - const bool shooter = parent->info->stackNode->hasBonusOfType(Bonus::SHOOTER) && parent->info->stackNode->valOfBonuses(Bonus::SHOTS); - const bool caster = parent->info->stackNode->valOfBonuses(Bonus::CASTS); - - printStatBase(EStat::ATTACK, CGI->generaltexth->primarySkillNames[0], parent->info->creature->getAttack(shooter), parent->info->stackNode->getAttack(shooter)); - printStatBase(EStat::DEFENCE, CGI->generaltexth->primarySkillNames[1], parent->info->creature->getDefence(shooter), parent->info->stackNode->getDefence(shooter)); - printStatRange(EStat::DAMAGE, CGI->generaltexth->allTexts[199], parent->info->stackNode->getMinDamage(shooter) * dmgMultiply, parent->info->stackNode->getMaxDamage(shooter) * dmgMultiply); - printStatBase(EStat::HEALTH, CGI->generaltexth->allTexts[388], parent->info->creature->MaxHealth(), parent->info->stackNode->MaxHealth()); - printStatBase(EStat::SPEED, CGI->generaltexth->zelp[441].first, parent->info->creature->Speed(), parent->info->stackNode->Speed()); - - if(shooter) - printStat(EStat::SHOTS, CGI->generaltexth->allTexts[198], parent->info->stackNode->valOfBonuses(Bonus::SHOTS)); - if(caster) - printStat(EStat::MANA, CGI->generaltexth->allTexts[399], parent->info->stackNode->valOfBonuses(Bonus::CASTS)); - - morale->set(parent->info->stackNode); - luck->set(parent->info->stackNode); - } - - if (showExp) - { - const CStackInstance * stack = parent->info->stackNode; - Point pos = showArt ? Point(321, 32) : Point(347, 32); - if (parent->info->commander) - { - const CCommanderInstance * commander = parent->info->commander; - parent->expRankIcon = new CAnimImage("PSKIL42", 4, 0, pos.x, pos.y); // experience icon - - parent->expArea = new LRClickableAreaWTextComp(Rect( - pos.x, pos.y, 44, 44), CComponent::experience); - parent->expArea->text = CGI->generaltexth->allTexts[2]; - reinterpret_cast(parent->expArea)->bonusValue = - commander->getExpRank(); - boost::replace_first(parent->expArea->text, "%d", - boost::lexical_cast(commander->getExpRank())); - boost::replace_first(parent->expArea->text, "%d", - boost::lexical_cast(CGI->heroh->reqExp(commander->getExpRank() + 1))); - boost::replace_first(parent->expArea->text, "%d", - boost::lexical_cast(commander->experience)); - } - else - { - parent->expRankIcon = new CAnimImage( - "stackWindow/levels", stack->getExpRank(), 0, pos.x, pos.y); - parent->expArea = new LRClickableAreaWText(Rect(pos.x, pos.y, 44, 44)); - parent->expArea->text = parent->generateStackExpDescription(); - } - parent->expLabel = new CLabel( - pos.x + 21, pos.y + 52, FONT_SMALL, CENTER, Colors::WHITE, - makeNumberShort(stack->experience, 6)); - } - - if (showArt) - { - Point pos = showExp ? Point(375, 32) : Point(347, 32); - // ALARMA: do not refactor this into a separate function - // otherwise, artifact icon is drawn near the hero's portrait - // this is really strange - auto art = parent->info->stackNode->getArt(ArtifactPosition::CREATURE_SLOT); - if (art) - { - parent->stackArtifactIcon.reset(new CAnimImage( - "ARTIFACT", art->artType->iconIndex, 0, pos.x, pos.y)); - parent->stackArtifactIcon->recActions &= ~DISPOSE; - parent->stackArtifactHelp.reset(new LRClickableAreaWTextComp(Rect( - pos, Point(44, 44)), CComponent::artifact)); - parent->stackArtifactHelp->recActions &= ~DISPOSE; - parent->stackArtifactHelp->type = art->artType->id; - const JsonNode & text = - VLC->generaltexth->localizedTexts["creatureWindow"]["returnArtifact"]; - - if (parent->info->owner) - { - parent->stackArtifactButton.reset(new CButton( - Point(pos.x - 2 , pos.y + 46), "stackWindow/cancelButton", - CButton::tooltip(text), - [=](){ parent->removeStackArtifact(ArtifactPosition::CREATURE_SLOT); })); - parent->stackArtifactButton->recActions &= ~DISPOSE; - } - } - } -} - -void CStackWindow::CWindowSection::createActiveSpells() -{ - static const Point firstPos(6, 2); // position of 1st spell box - static const Point offset(54, 0); // offset of each spell box from previous - - OBJ_CONSTRUCTION_CAPTURING_ALL; - createBackground("spell-effects"); - - const CStack * battleStack = parent->info->stack; - - assert(battleStack); // Section should be created only for battles - - //spell effects - int printed=0; //how many effect pics have been printed - std::vector spells = battleStack->activeSpells(); - for(si32 effect : spells) - { - const CSpell * sp = CGI->spellh->objects[effect]; - - std::string spellText; - - //not all effects have graphics (for eg. Acid Breath) - //for modded spells iconEffect is added to SpellInt.def - const bool hasGraphics = (effect < SpellID::THUNDERBOLT) || (effect >= SpellID::AFTER_LAST); - - if (hasGraphics) - { - spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds." - boost::replace_first(spellText, "%s", sp->name); - int duration = battleStack->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT,effect))->turnsRemain; - boost::replace_first(spellText, "%d", boost::lexical_cast(duration)); - - new CAnimImage("SpellInt", effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed); - new LRClickableAreaWText(Rect(firstPos + offset * printed, Point(50, 38)), spellText, spellText); - if (++printed >= 8) // interface limit reached - break; - } - } -} - -void CStackWindow::CWindowSection::createCommanderSection() -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - auto onCreate = [=](size_t index) -> CIntObject * - { - return parent->switchTab(index); - }; - auto onDestroy = [=](CIntObject * obj) - { - delete obj; - }; - parent->commanderTab = new CTabbedInt(onCreate, onDestroy, Point(0,0), 0); - pos.w = parent->pos.w; - pos.h = 177; // height of commander info - if (parent->info->levelupInfo) - pos.h += 59; // height of abilities selection -} - -static std::string skillToFile (int skill, int level, bool selected) -{ - // FIXME: is this a correct hadling? - // level 0 = skill not present, use image with "no" suffix - // level 1-5 = skill available, mapped to images indexed as 0-4 - // selecting skill means that it will appear one level higher (as if alredy upgraded) - std::string file = "zvs/Lib1.res/_"; - switch (skill) - { - case ECommander::ATTACK: - file += "AT"; - break; - case ECommander::DEFENSE: - file += "DF"; - break; - case ECommander::HEALTH: - file += "HP"; - break; - case ECommander::DAMAGE: - file += "DM"; - break; - case ECommander::SPEED: - file += "SP"; - break; - case ECommander::SPELL_POWER: - file += "MP"; - break; - } - std::string sufix; - if (selected) - level++; // UI will display resulting level - if (level == 0) - sufix = "no"; //not avaliable - no number - else - sufix = boost::lexical_cast(level-1); - if (selected) - sufix += "="; //level-up highlight - - return file + sufix + ".bmp"; -} - -void CStackWindow::CWindowSection::createCommander() -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - createBackground("commander-bg"); - - auto getSkillPos = [](int index) - { - return Point(10 + 80 * (index%3), 20 + 80 * (index/3)); - }; - - auto getSkillImage = [this](int skillIndex) -> std::string - { - bool selected = ((parent->selectedSkill == skillIndex) && parent->info->levelupInfo ); - return skillToFile(skillIndex, parent->info->commander->secondarySkills[skillIndex], selected); - }; - - auto getSkillDescription = [this](int skillIndex) -> std::string - { - if (CGI->generaltexth->znpc00.size() == 0) - return ""; - - return CGI->generaltexth->znpc00[151 + (12 * skillIndex) + (parent->info->commander->secondarySkills[skillIndex] * 2)]; - }; - - for (int index = ECommander::ATTACK; index <= ECommander::SPELL_POWER; ++index) - { - Point skillPos = getSkillPos(index); - - auto icon = new CCommanderSkillIcon(new CPicture(getSkillImage(index), skillPos.x, skillPos.y), - [=](){ LOCPLINT->showInfoDialog(getSkillDescription(index)); }); - - icon->text = getSkillDescription(index); //used to handle right click description via LRClickableAreaWText::ClickRight() - - if(parent->selectedSkill == index) - parent->selectedIcon = icon; - - if(parent->info->levelupInfo && vstd::contains(parent->info->levelupInfo->skills, index)) // can be upgraded - enable selection switch - { - if(parent->selectedSkill == index) - parent->setSelection(index, icon); - - icon->callback = [=]() - { - parent->setSelection(index, icon); - }; - } - } - - auto getArtifactPos = [](int index) - { - return Point(269 + 47 * (index % 3), 22 + 47 * (index / 3)); - }; - for (auto equippedArtifact : parent->info->commander->artifactsWorn) - { - Point artPos = getArtifactPos(equippedArtifact.first); - auto icon = new CCommanderArtPlace(artPos, parent->info->owner, equippedArtifact.first, equippedArtifact.second.artifact); - } -} - -CIntObject * CStackWindow::createSkillEntry(int index) -{ - for (auto skillID : info->levelupInfo->skills) - { - if (index == 0 && skillID >= 100) - { - const auto bonus = CGI->creh->skillRequirements[skillID-100].first; - const CStackInstance *stack = info->commander; - CCommanderSkillIcon * icon = new CCommanderSkillIcon(new CPicture(stack->bonusToGraphics(bonus)), [](){}); - icon->callback = [=]() - { - setSelection(skillID, icon); - }; - icon->text = stack->bonusToString(bonus, true); - icon->hoverText = stack->bonusToString(bonus, false); - return icon; - } - if (skillID >= 100) - index--; - } - return nullptr; -} - -void CStackWindow::CWindowSection::createCommanderAbilities() -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - - auto bg2 = new CPicture("stackWindow/commander-abilities.png"); - bg2->moveBy(Point(0, pos.h)); - size_t abilitiesCount = boost::range::count_if(parent->info->levelupInfo->skills, [](ui32 skillID) - { - return skillID >= 100; - }); - - auto list = new CListBox([=] (int index) - { - return parent->createSkillEntry(index); - }, - [=] (CIntObject * elem) - { - delete elem; - }, - Point(38, 3+pos.h), Point(63, 0), 6, abilitiesCount); - - auto leftBtn = new CButton(Point(10, pos.h + 6), "hsbtns3.def", CButton::tooltip(), [=](){ list->moveToPrev(); }, SDLK_LEFT); - auto rightBtn = new CButton(Point(411, pos.h + 6), "hsbtns5.def", CButton::tooltip(), [=](){ list->moveToNext(); }, SDLK_RIGHT); - - if (abilitiesCount <= 6) - { - leftBtn->block(true); - rightBtn->block(true); - } -} - -void CStackWindow::setSelection(si32 newSkill, CCommanderSkillIcon * newIcon) +void CStackWindow::setSelection(si32 newSkill, std::shared_ptr newIcon) { auto getSkillDescription = [this](int skillIndex, bool selected) -> std::string { - if (CGI->generaltexth->znpc00.size() == 0) + if(CGI->generaltexth->znpc00.size() == 0) return ""; if(selected) @@ -560,407 +914,60 @@ void CStackWindow::setSelection(si32 newSkill, CCommanderSkillIcon * newIcon) return skillToFile(skillIndex, info->commander->secondarySkills[skillIndex], selected); }; - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); int oldSelection = selectedSkill; // update selection selectedSkill = newSkill; - if (selectedIcon && oldSelection < 100) // recreate image on old selection, only for skills - selectedIcon->setObject(new CPicture(getSkillImage(oldSelection))); + if(selectedIcon && oldSelection < 100) // recreate image on old selection, only for skills + selectedIcon->setObject(std::make_shared(getSkillImage(oldSelection))); if(selectedIcon) selectedIcon->text = getSkillDescription(oldSelection, false); //update previously selected icon's message to existing skill level selectedIcon = newIcon; // update new selection - if (newSkill < 100) + if(newSkill < 100) { - newIcon->setObject(new CPicture(getSkillImage(newSkill))); + newIcon->setObject(std::make_shared(getSkillImage(newSkill))); newIcon->text = getSkillDescription(newSkill, true); //update currently selected icon's message to show upgrade description } } -void CStackWindow::CWindowSection::createBonuses(boost::optional preferredSize) +std::shared_ptr CStackWindow::switchTab(size_t index) { - // size of single image for an item - static const int itemHeight = 59; - OBJ_CONSTRUCTION_CAPTURING_ALL; - size_t totalSize = (parent->activeBonuses.size() + 1) / 2; - size_t visibleSize = preferredSize ? preferredSize.get() : std::min(3, totalSize); - - pos.w = parent->pos.w; - pos.h = itemHeight * visibleSize; - - auto onCreate = [=](size_t index) -> CIntObject * + std::shared_ptr ret; + switch(index) { - return parent->createBonusEntry(index); - }; - auto onDestroy = [=](CIntObject * obj) - { - delete obj; - }; - new CListBox(onCreate, onDestroy, Point(0, 0), Point(0, itemHeight), visibleSize, totalSize, 0, 1, Rect(pos.w - 15, 0, pos.h, pos.h)); -} - -void CStackWindow::CWindowSection::createButtonPanel() -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - createBackground("button-panel"); - - if (parent->info->dismissInfo && parent->info->dismissInfo->callback) - { - auto onDismiss = [=]() + case 0: { - parent->info->dismissInfo->callback(); - parent->close(); - }; - auto onClick = [=] () - { - LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[12], onDismiss, 0, false, std::vector()); - }; - new CButton(Point(5, 5),"IVIEWCR2.DEF", CGI->generaltexth->zelp[445], onClick, SDLK_d); - } - if (parent->info->upgradeInfo) - { - // used space overlaps with commander switch button - // besides - should commander really be upgradeable? - assert(!parent->info->commander); - - StackWindowInfo::StackUpgradeInfo & upgradeInfo = parent->info->upgradeInfo.get(); - size_t buttonsToCreate = std::min(upgradeInfo.info.newID.size(), 3); // no more than 3 windows on UI - space limit - - for (size_t i=0; iinfo->creatureCount; - - auto onUpgrade = [=]() - { - upgradeInfo.callback(upgradeInfo.info.newID[i]); - parent->close(); - }; - auto onClick = [=]() - { - std::vector resComps; - for(TResources::nziterator i(totalCost); i.valid(); i++) - { - resComps.push_back(new CComponent(CComponent::resource, i->resType, i->resVal)); - } - - if(LOCPLINT->cb->getResourceAmount().canAfford(totalCost)) - { - LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[207], onUpgrade, nullptr, true, resComps); - } - else - LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[314], resComps); - }; - auto upgradeBtn = new CButton(Point(221 + i * 40, 5), "stackWindow/upgradeButton", CGI->generaltexth->zelp[446], onClick, SDLK_1); - - upgradeBtn->addOverlay(new CAnimImage("CPRSMALL", VLC->creh->creatures[upgradeInfo.info.newID[i]]->iconIndex)); + activeTab = 0; + ret = commanderMainSection; } - } - - if (parent->info->commander) - { - for (size_t i=0; i<2; i++) + break; + case 1: { - std::string btnIDs[2] = { "showSkills", "showBonuses" }; - auto onSwitch = [&, i]() - { - parent->switchButtons[parent->activeTab]->enable(); - parent->commanderTab->setActive(i); - parent->switchButtons[i]->disable(); - parent->redraw(); // FIXME: enable/disable don't redraw screen themselves - }; - - const JsonNode & text = VLC->generaltexth->localizedTexts["creatureWindow"][btnIDs[i]]; - parent->switchButtons[i] = new CButton(Point(302 + i*40, 5), "stackWindow/upgradeButton", CButton::tooltip(text), onSwitch); - parent->switchButtons[i]->addOverlay(new CAnimImage("stackWindow/switchModeIcons", i)); + activeTab = 1; + ret = commanderBonusesSection; } - parent->switchButtons[parent->activeTab]->disable(); + break; + default: + break; } - auto exitBtn = new CButton(Point(382, 5), "hsbtns.def", CGI->generaltexth->zelp[447], [=](){ parent->close(); }, SDLK_RETURN); - exitBtn->assignedKeys.insert(SDLK_ESCAPE); + return ret; } -CStackWindow::CWindowSection::CWindowSection(CStackWindow * parent): - parent(parent) +void CStackWindow::removeStackArtifact(ArtifactPosition pos) { -} - -CCommanderSkillIcon::CCommanderSkillIcon(CIntObject *object, std::function callback): - object(nullptr), - callback(callback) -{ - pos = object->pos; - setObject(object); -} - -void CCommanderSkillIcon::setObject(CIntObject *newObject) -{ - delete object; - object = newObject; - addChild(object); - object->moveTo(pos.topLeft()); + auto art = info->stackNode->getArt(ArtifactPosition::CREATURE_SLOT); + if(!art) + { + logGlobal->error("Attempt to remove missing artifact"); + return; + } + LOCPLINT->cb->swapArtifacts(ArtifactLocation(info->stackNode, pos), ArtifactLocation(info->owner, art->firstBackpackSlot(info->owner))); + stackArtifactButton.reset(); + stackArtifactHelp.reset(); + stackArtifactIcon.reset(); redraw(); } -void CCommanderSkillIcon::clickLeft(tribool down, bool previousState) -{ - if(down) - callback(); -} - -void CCommanderSkillIcon::clickRight(tribool down, bool previousState) -{ - if(down) - LRClickableAreaWText::clickRight(down, previousState); -} - -CIntObject * CStackWindow::createBonusEntry(size_t index) -{ - auto section = new CWindowSection(this); - section->createBonusEntry(index); - return section; -} - -void CStackWindow::CWindowSection::createBonusEntry(size_t index) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - createBackground("bonus-effects"); - createBonusItem(index * 2, Point(6, 4)); - createBonusItem(index * 2 + 1, Point(214, 4)); -} - -void CStackWindow::CWindowSection::createBonusItem(size_t index, Point position) -{ - if (parent->activeBonuses.size() > index) - { - BonusInfo & bi = parent->activeBonuses[index]; - new CPicture(bi.imagePath, position.x, position.y); - new CLabel(position.x + 60, position.y + 2, FONT_SMALL, TOPLEFT, Colors::WHITE, bi.name); - new CMultiLineLabel(Rect(position.x + 60, position.y + 17, 137,30), FONT_SMALL, TOPLEFT, Colors::WHITE, bi.description); - } -} - -CIntObject * CStackWindow::switchTab(size_t index) -{ - switch (index) - { - case 0: - { - activeTab = 0; - auto ret = new CWindowSection(this); - ret->createCommander(); - if (info->levelupInfo) - ret->createCommanderAbilities(); - return ret; - } - case 1: - { - activeTab = 1; - auto ret = new CWindowSection(this); - if (info->levelupInfo) - ret->createBonuses(4); - else - ret->createBonuses(3); - return ret; - } - default: - { - return nullptr; - } - } -} - -void CStackWindow::initSections() -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - CWindowSection * currentSection; - - bool showArt = CGI->modh->modules.STACK_ARTIFACT && info->commander == nullptr && info->stackNode; - bool showExp = (CGI->modh->modules.STACK_EXP || info->commander != nullptr) && info->stackNode; - currentSection = new CWindowSection(this); - currentSection->createStackInfo(showExp, showArt); - pos.w = currentSection->pos.w; - pos.h += currentSection->pos.h; - - if (info->stack) // in battle - { - currentSection = new CWindowSection(this); - currentSection->pos.y += pos.h; - currentSection->createActiveSpells(); - pos.h += currentSection->pos.h; - } - if (info->commander) - { - currentSection = new CWindowSection(this); - currentSection->pos.y += pos.h; - currentSection->createCommanderSection(); - pos.h += currentSection->pos.h; - } - if (!info->commander && !activeBonuses.empty()) - { - currentSection = new CWindowSection(this); - currentSection->pos.y += pos.h; - currentSection->createBonuses(); - pos.h += currentSection->pos.h; - } - - if (!info->popupWindow) - { - currentSection = new CWindowSection(this); - currentSection->pos.y += pos.h; - currentSection->createButtonPanel(); - pos.h += currentSection->pos.h; - //FIXME: add status bar to image? - } - updateShadow(); - pos = center(pos); -} - -void CStackWindow::initBonusesList() -{ - BonusList output, input; - input = *(info->stackNode->getBonuses(CSelector(Bonus::Permanent), Selector::all)); - - while (!input.empty()) - { - auto b = input.front(); - output.push_back(std::make_shared(*b)); - output.back()->val = input.valOfBonuses(Selector::typeSubtype(b->type, b->subtype)); //merge multiple bonuses into one - input.remove_if (Selector::typeSubtype(b->type, b->subtype)); //remove used bonuses - } - - BonusInfo bonusInfo; - for(auto b : output) - { - bonusInfo.name = info->stackNode->bonusToString(b, false); - bonusInfo.description = info->stackNode->bonusToString(b, true); - bonusInfo.imagePath = info->stackNode->bonusToGraphics(b); - - //if it's possible to give any description or image for this kind of bonus - //TODO: figure out why half of bonuses don't have proper description - if (b->type == Bonus::MAGIC_RESISTANCE || b->type == Bonus::SECONDARY_SKILL_PREMY && b->subtype == SecondarySkill::RESISTANCE) - continue; - if ((!bonusInfo.name.empty() || !bonusInfo.imagePath.empty())) - activeBonuses.push_back(bonusInfo); - } - - //handle Magic resistance separately :/ - int magicResistance = info->stackNode->magicResistance();//both MAGIC_RESITANCE and SECONDARY_SKILL_PREMY as one entry - - if (magicResistance) - { - BonusInfo bonusInfo; - auto b = std::make_shared(); - b->type = Bonus::MAGIC_RESISTANCE; - - bonusInfo.name = VLC->getBth()->bonusToString(b, info->stackNode, false); - bonusInfo.description = VLC->getBth()->bonusToString(b, info->stackNode, true); - bonusInfo.imagePath = info->stackNode->bonusToGraphics(b); - activeBonuses.push_back(bonusInfo); - } -} - -void CStackWindow::init() -{ - expRankIcon = nullptr; - expArea = nullptr; - expLabel = nullptr; - if (!info->stackNode) - info->stackNode = new CStackInstance(info->creature, 1);// FIXME: free data - - selectedIcon = nullptr; - selectedSkill = -1; - if (info->levelupInfo && !info->levelupInfo->skills.empty()) - selectedSkill = info->levelupInfo->skills.front(); - - commanderTab = nullptr; - activeTab = 0; - - initBonusesList(); - initSections(); -} - -CStackWindow::CStackWindow(const CStack * stack, bool popup): - CWindowObject(BORDERED | (popup ? RCLICK_POPUP : 0)), - info(new StackWindowInfo()) -{ - info->stack = stack; - info->stackNode = stack->base; - info->creature = stack->type; - info->creatureCount = stack->getCount(); - info->popupWindow = popup; - init(); -} - -CStackWindow::CStackWindow(const CCreature * creature, bool popup): - CWindowObject(BORDERED | (popup ? RCLICK_POPUP : 0)), - info(new StackWindowInfo()) -{ - info->creature = creature; - info->popupWindow = popup; - init(); -} - -CStackWindow::CStackWindow(const CStackInstance * stack, bool popup): - CWindowObject(BORDERED | (popup ? RCLICK_POPUP : 0)), - info(new StackWindowInfo()) -{ - info->stackNode = stack; - info->creature = stack->type; - info->creatureCount = stack->count; - info->popupWindow = popup; - info->owner = dynamic_cast (stack->armyObj); - init(); -} - -CStackWindow::CStackWindow(const CStackInstance * stack, std::function dismiss, const UpgradeInfo & upgradeInfo, std::function callback): - CWindowObject(BORDERED), - info(new StackWindowInfo()) -{ - info->stackNode = stack; - info->creature = stack->type; - info->creatureCount = stack->count; - - info->upgradeInfo = boost::make_optional(StackWindowInfo::StackUpgradeInfo()); - info->dismissInfo = boost::make_optional(StackWindowInfo::StackDismissInfo()); - info->upgradeInfo->info = upgradeInfo; - info->upgradeInfo->callback = callback; - info->dismissInfo->callback = dismiss; - info->owner = dynamic_cast (stack->armyObj); - init(); -} - -CStackWindow::CStackWindow(const CCommanderInstance * commander, bool popup): - CWindowObject(BORDERED | (popup ? RCLICK_POPUP : 0)), - info(new StackWindowInfo()) -{ - info->stackNode = commander; - info->creature = commander->type; - info->commander = commander; - info->creatureCount = 1; - info->popupWindow = popup; - info->owner = dynamic_cast (commander->armyObj); - init(); -} - -CStackWindow::CStackWindow(const CCommanderInstance * commander, std::vector &skills, std::function callback): - CWindowObject(BORDERED), - info(new StackWindowInfo()) -{ - info->stackNode = commander; - info->creature = commander->type; - info->commander = commander; - info->creatureCount = 1; - info->levelupInfo = boost::make_optional(StackWindowInfo::CommanderLevelInfo()); - info->levelupInfo->skills = skills; - info->levelupInfo->callback = callback; - info->owner = dynamic_cast (commander->armyObj); - init(); -} - -CStackWindow::~CStackWindow() -{ - if (info->levelupInfo && !info->levelupInfo->skills.empty()) - info->levelupInfo->callback(vstd::find_pos(info->levelupInfo->skills, selectedSkill)); -} diff --git a/client/windows/CCreatureWindow.h b/client/windows/CCreatureWindow.h index a647ab9ed..f19f32689 100644 --- a/client/windows/CCreatureWindow.h +++ b/client/windows/CCreatureWindow.h @@ -13,26 +13,29 @@ #include "../widgets/MiscWidgets.h" #include "CWindowObject.h" -struct StackWindowInfo; +class UnitView; class CCommanderInstance; class CStackInstance; class CStack; struct UpgradeInfo; class CTabbedInt; class CButton; +class CMultiLineLabel; +class CListBox; +class CCommanderArtPlace; class CCommanderSkillIcon : public LRClickableAreaWText //TODO: maybe bring commander skill button initialization logic inside? { - CIntObject * object; // passive object that will be used to determine clickable area + std::shared_ptr object; // passive object that will be used to determine clickable area public: - CCommanderSkillIcon(CIntObject * object, std::function callback); + CCommanderSkillIcon(std::shared_ptr object_, std::function callback); std::function callback; void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; - void setObject(CIntObject * object); + void setObject(std::shared_ptr object); }; class CStackWindow : public CWindowObject @@ -46,48 +49,123 @@ class CStackWindow : public CWindowObject class CWindowSection : public CIntObject { - CStackWindow *parent; - - void createBackground(std::string path); - void createBonusItem(size_t index, Point position); - - void printStatString(int index, std::string name, std::string value); - void printStatRange(int index, std::string name, int min, int max); - void printStatBase(int index, std::string name, int base, int current); - void printStat(int index, std::string name, int value); + private: + std::shared_ptr background; + protected: + CStackWindow * parent; public: - void createStackInfo(bool showExp, bool showArt); - void createActiveSpells(); - void createCommanderSection(); - void createCommander(); - void createCommanderAbilities(); - void createBonuses(boost::optional size = boost::optional()); - void createBonusEntry(size_t index); - void createButtonPanel(); - - CWindowSection(CStackWindow * parent); + CWindowSection(CStackWindow * parent, std::string backgroundPath, int yOffset); }; - std::unique_ptr stackArtifactIcon; - std::unique_ptr stackArtifactHelp; - std::unique_ptr stackArtifactButton; - CAnimImage *expRankIcon; - LRClickableAreaWText *expArea; - CLabel *expLabel; + class ActiveSpellsSection : public CWindowSection + { + std::vector> spellIcons; + std::vector> clickableAreas; + public: + ActiveSpellsSection(CStackWindow * owner, int yOffset); + }; - std::unique_ptr info; + class BonusLineSection : public CWindowSection + { + std::array, 2> icon; + std::array, 2> name; + std::array, 2> description; + public: + BonusLineSection(CStackWindow * owner, size_t lineIndex); + }; + + class BonusesSection : public CWindowSection + { + std::shared_ptr lines; + public: + BonusesSection(CStackWindow * owner, int yOffset, boost::optional preferredSize = boost::optional()); + }; + + class ButtonsSection : public CWindowSection + { + std::shared_ptr dismiss; + std::array, 3> upgrade;// no more than 3 buttons - space limit + std::shared_ptr exit; + public: + ButtonsSection(CStackWindow * owner, int yOffset); + }; + + class CommanderMainSection : public CWindowSection + { + std::vector> skillIcons; + std::vector> artifacts; + + std::shared_ptr abilitiesBackground; + std::shared_ptr abilities; + + std::shared_ptr leftBtn; + std::shared_ptr rightBtn; + public: + CommanderMainSection(CStackWindow * owner, int yOffset); + }; + + class MainSection : public CWindowSection + { + enum class EStat : size_t + { + ATTACK, + DEFENCE, + SHOTS, + DAMAGE, + HEALTH, + HEALTH_LEFT, + SPEED, + MANA, + AFTER_LAST + }; + + std::shared_ptr animation; + std::shared_ptr name; + std::shared_ptr icons; + std::shared_ptr morale; + std::shared_ptr luck; + + std::vector> stats; + + std::shared_ptr expRankIcon; + std::shared_ptr expArea; + std::shared_ptr expLabel; + + void addStatLabel(EStat index, int64_t value1, int64_t value2); + void addStatLabel(EStat index, int64_t value); + + static std::string getBackgroundName(bool showExp, bool showArt); + + std::array statNames; + std::array statFormats; + public: + MainSection(CStackWindow * owner, int yOffset, bool showExp, bool showArt); + }; + + std::shared_ptr stackArtifactIcon; + std::shared_ptr stackArtifactHelp; + std::shared_ptr stackArtifactButton; + + + std::shared_ptr info; std::vector activeBonuses; size_t activeTab; - CTabbedInt *commanderTab; + std::shared_ptr commanderTab; - std::map switchButtons; + std::map> switchButtons; - void setSelection(si32 newSkill, CCommanderSkillIcon * newIcon); - CCommanderSkillIcon * selectedIcon; + std::shared_ptr mainSection; + std::shared_ptr activeSpellsSection; + std::shared_ptr commanderMainSection; + std::shared_ptr commanderBonusesSection; + std::shared_ptr bonusesSection; + std::shared_ptr buttonsSection; + + std::shared_ptr selectedIcon; si32 selectedSkill; - CIntObject * createBonusEntry(size_t index); - CIntObject * switchTab(size_t index); + void setSelection(si32 newSkill, std::shared_ptr newIcon); + std::shared_ptr switchTab(size_t index); void removeStackArtifact(ArtifactPosition pos); @@ -98,8 +176,6 @@ class CStackWindow : public CWindowObject std::string generateStackExpDescription(); - CIntObject * createSkillEntry(int index); - public: // for battles CStackWindow(const CStack * stack, bool popup); diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index 8e47c6fc3..6a8b06361 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -40,17 +40,15 @@ #include "../mapHandler.h" -const TBonusListPtr CHeroWithMaybePickedArtifact::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root, const std::string & cachingStr) const +const TBonusListPtr CHeroWithMaybePickedArtifact::getAllBonuses(const CSelector & selector, const CSelector & limit, const CBonusSystemNode * root, const std::string & cachingStr) const { TBonusListPtr out(new BonusList()); - TBonusListPtr heroBonuses = hero->getAllBonuses(selector, limit, hero); + TBonusListPtr heroBonuses = hero->getAllBonuses(selector, limit, hero, cachingStr); TBonusListPtr bonusesFromPickedUpArtifact; - std::shared_ptr cp = cww->artSets.size() ? cww->artSets.front()->commonInfo : nullptr; + std::shared_ptr cp = cww->getCommonPart(); if(cp && cp->src.art && cp->src.valid() && cp->src.AOH && cp->src.AOH->getHero() == hero) - { bonusesFromPickedUpArtifact = cp->src.art->getAllBonuses(selector, limit, hero); - } else bonusesFromPickedUpArtifact = TBonusListPtr(new BonusList()); @@ -66,8 +64,8 @@ int64_t CHeroWithMaybePickedArtifact::getTreeVersion() const return hero->getTreeVersion(); //this assumes that hero and artifact belongs to main bonus tree } -CHeroWithMaybePickedArtifact::CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero) - : hero(Hero), cww(Cww) +CHeroWithMaybePickedArtifact::CHeroWithMaybePickedArtifact(CWindowWithArtifacts * Cww, const CGHeroInstance * Hero) + : hero(Hero), cww(Cww) { } @@ -75,114 +73,128 @@ void CHeroSwitcher::clickLeft(tribool down, bool previousState) { if(!down) { + //TODO: do not recreate window + #if 0 + owner->update(hero, true); + #else const CGHeroInstance * buf = hero; GH.popIntTotally(parent); GH.pushInt(new CHeroWindow(buf)); + #endif // 0 } } -CHeroSwitcher::CHeroSwitcher(Point _pos, const CGHeroInstance * _hero): - hero(_hero) +CHeroSwitcher::CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInstance * hero_) + : CIntObject(LCLICK), + owner(owner_), + hero(hero_) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - pos += _pos; - addUsedEvents(LCLICK); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + pos += pos_; - image = new CAnimImage("PortraitsSmall", hero->portrait); + image = std::make_shared("PortraitsSmall", hero->portrait); pos.w = image->pos.w; pos.h = image->pos.h; } -CHeroWindow::CHeroWindow(const CGHeroInstance *hero): - CWindowObject(PLAYER_COLORED, "HeroScr4"), +CHeroWindow::CHeroWindow(const CGHeroInstance * hero) + : CWindowObject(PLAYER_COLORED, "HeroScr4"), heroWArt(this, hero) { auto & heroscrn = CGI->generaltexth->heroscrn; - OBJ_CONSTRUCTION_CAPTURING_ALL; - garr = nullptr; - tacticsButton = nullptr; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); curHero = hero; - listSelection = nullptr; - new CAnimImage("CREST58", LOCPLINT->playerID.getNum(), 0, 606, 8); + banner = std::make_shared("CREST58", LOCPLINT->playerID.getNum(), 0, 606, 8); + name = std::make_shared(190, 38, EFonts::FONT_BIG, EAlignment::CENTER, Colors::YELLOW); + title = std::make_shared(190, 65, EFonts::FONT_MEDIUM, EAlignment::CENTER, Colors::WHITE); - //artifs = new CArtifactsOfHero(pos.topLeft(), true); - ourBar = new CGStatusBar(7, 559, "ADROLLVR.bmp", 660); // new CStatusBar(pos.x+72, pos.y+567, "ADROLLVR.bmp", 660); + statusBar = std::make_shared(7, 559, "ADROLLVR.bmp", 660); - quitButton = new CButton(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [&](){ close(); }, SDLK_RETURN); + quitButton = std::make_shared(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [=](){ close(); }, SDLK_RETURN); quitButton->assignedKeys.insert(SDLK_ESCAPE); - dismissButton = new CButton(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [&](){ dismissCurrent(); }, SDLK_d); - questlogButton = new CButton(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, SDLK_q); - formations = new CToggleGroup(0); - formations->addToggle(0, new CToggleButton(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, SDLK_t)); - formations->addToggle(1, new CToggleButton(Point(481, 519), "hsbtns7.def", std::make_pair(heroscrn[24], heroscrn[30]), 0, SDLK_l)); + dismissLabel = std::make_shared(CGI->generaltexth->jktexts[8], Rect(370, 430, 65, 35), 0, FONT_SMALL, TOPLEFT, Colors::WHITE); + dismissButton = std::make_shared(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [=](){ dismissCurrent(); }, SDLK_d); - if (hero->commander) + questlogLabel = std::make_shared(CGI->generaltexth->jktexts[9], Rect(510, 430, 65, 35), 0, FONT_SMALL, TOPLEFT, Colors::WHITE); + questlogButton = std::make_shared(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, SDLK_q); + + formations = std::make_shared(0); + formations->addToggle(0, std::make_shared(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, SDLK_t)); + formations->addToggle(1, std::make_shared(Point(481, 519), "hsbtns7.def", std::make_pair(heroscrn[24], heroscrn[30]), 0, SDLK_l)); + + if(hero->commander) { auto texts = CGI->generaltexth->localizedTexts["heroWindow"]["openCommander"]; - commanderButton = new CButton (Point(317, 18), "buttons/commander", CButton::tooltip(texts), [&](){ commanderWindow(); }, SDLK_c); + commanderButton = std::make_shared(Point(317, 18), "buttons/commander", CButton::tooltip(texts), [&](){ commanderWindow(); }, SDLK_c); } //right list of heroes for(int i=0; i < std::min(LOCPLINT->cb->howManyHeroes(false), 8); i++) - heroList.push_back(new CHeroSwitcher(Point(612, 87 + i * 54), LOCPLINT->cb->getHeroBySerial(i, false))); + heroList.push_back(std::make_shared(this, Point(612, 87 + i * 54), LOCPLINT->cb->getHeroBySerial(i, false))); //areas - portraitArea = new LRClickableAreaWText(Rect(18, 18, 58, 64)); - portraitImage = new CAnimImage("PortraitsLarge", 0, 0, 19, 19); + portraitArea = std::make_shared(Rect(18, 18, 58, 64)); + portraitImage = std::make_shared("PortraitsLarge", 0, 0, 19, 19); - for(int v=0; v(Rect(30 + 70 * v, 109, 42, 64), CComponent::primskill); area->text = CGI->generaltexth->arraytxt[2+v]; area->type = v; area->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % CGI->generaltexth->primarySkillNames[v]); primSkillAreas.push_back(area); + + auto value = std::make_shared(53 + 70 * v, 166, FONT_SMALL, CENTER); + primSkillValues.push_back(value); } - specImage = new CAnimImage("UN44", 0, 0, 18, 180); + auto primSkills = std::make_shared("PSKIL42"); + primSkills->preload(); + primSkillImages.push_back(std::make_shared(primSkills, 0, 0, 32, 111)); + primSkillImages.push_back(std::make_shared(primSkills, 1, 0, 102, 111)); + primSkillImages.push_back(std::make_shared(primSkills, 2, 0, 172, 111)); + primSkillImages.push_back(std::make_shared(primSkills, 3, 0, 162, 230)); + primSkillImages.push_back(std::make_shared(primSkills, 4, 0, 20, 230)); + primSkillImages.push_back(std::make_shared(primSkills, 5, 0, 242, 111)); - specArea = new LRClickableAreaWText(Rect(18, 180, 136, 42), CGI->generaltexth->heroscrn[27]); - expArea = new LRClickableAreaWText(Rect(18, 228, 136, 42), CGI->generaltexth->heroscrn[9]); - morale = new MoraleLuckBox(true, Rect(175,179,53,45)); - luck = new MoraleLuckBox(false, Rect(233,179,53,45)); - spellPointsArea = new LRClickableAreaWText(Rect(162,228, 136, 42), CGI->generaltexth->heroscrn[22]); + specImage = std::make_shared("UN44", 0, 0, 18, 180); + specArea = std::make_shared(Rect(18, 180, 136, 42), CGI->generaltexth->heroscrn[27]); + specName = std::make_shared(69, 205); + + expArea = std::make_shared(Rect(18, 228, 136, 42), CGI->generaltexth->heroscrn[9]); + morale = std::make_shared(true, Rect(175, 179, 53, 45)); + luck = std::make_shared(false, Rect(233, 179, 53, 45)); + spellPointsArea = std::make_shared(Rect(162,228, 136, 42), CGI->generaltexth->heroscrn[22]); + + expValue = std::make_shared(68, 252); + manaValue = std::make_shared(211, 252); auto secSkills = std::make_shared("SECSKILL"); for(int i = 0; i < std::min(hero->secSkills.size(), 8u); ++i) { Rect r = Rect(i%2 == 0 ? 18 : 162, 276 + 48 * (i/2), 136, 42); - secSkillAreas.push_back(new LRClickableAreaWTextComp(r, CComponent::secskill)); - secSkillImages.push_back(new CAnimImage(secSkills, 0, 0, r.x, r.y)); + secSkillAreas.push_back(std::make_shared(r, CComponent::secskill)); + secSkillImages.push_back(std::make_shared(secSkills, 0, 0, r.x, r.y)); + + int x = (i % 2) ? 212 : 68; + int y = 280 + 48 * (i/2); + + secSkillValues.push_back(std::make_shared(x, y, FONT_SMALL, TOPLEFT)); + secSkillNames.push_back(std::make_shared(x, y+20, FONT_SMALL, TOPLEFT)); } - //dismiss / quest log - new CTextBox(CGI->generaltexth->jktexts[8], Rect(370, 430, 65, 35), 0, FONT_SMALL, TOPLEFT, Colors::WHITE); - new CTextBox(CGI->generaltexth->jktexts[9], Rect(510, 430, 65, 35), 0, FONT_SMALL, TOPLEFT, Colors::WHITE); - - //////////////////////////////////////////////////////////////////////////??????????????? - - //primary skills & exp and mana - auto primSkills = std::make_shared("PSKIL42"); - primSkills->preload(); - new CAnimImage(primSkills, 0, 0, 32, 111); - new CAnimImage(primSkills, 1, 0, 102, 111); - new CAnimImage(primSkills, 2, 0, 172, 111); - new CAnimImage(primSkills, 3, 0, 162, 230); - new CAnimImage(primSkills, 4, 0, 20, 230); - new CAnimImage(primSkills, 5, 0, 242, 111); - // various texts - new CLabel( 52, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[1]); - new CLabel(123, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[2]); - new CLabel(193, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[3]); - new CLabel(262, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[4]); + labels.push_back(std::make_shared(52, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[1])); + labels.push_back(std::make_shared(123, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[2])); + labels.push_back(std::make_shared(193, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[3])); + labels.push_back(std::make_shared(262, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[4])); - new CLabel( 69, 183, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[5]); - new CLabel( 69, 232, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[6]); - new CLabel(213, 232, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[7]); + labels.push_back(std::make_shared(69, 183, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[5])); + labels.push_back(std::make_shared(69, 232, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[6])); + labels.push_back(std::make_shared(213, 232, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[7])); update(hero); } @@ -199,11 +211,14 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded) assert(hero == curHero); + name->setText(curHero->name); + title->setText((boost::format(CGI->generaltexth->allTexts[342]) % curHero->level % curHero->type->heroClass->name).str()); + specArea->text = curHero->type->specDescr; specImage->setFrame(curHero->type->imageIndex); + specName->setText(curHero->type->specName); - delete tacticsButton; - tacticsButton = new CToggleButton(Point(539, 483), "hsbtns8.def", std::make_pair(heroscrn[26], heroscrn[31]), 0, SDLK_b); + tacticsButton = std::make_shared(Point(539, 483), "hsbtns8.def", std::make_pair(heroscrn[26], heroscrn[31]), 0, SDLK_b); tacticsButton->addHoverText(CButton::HIGHLIGHTED, CGI->generaltexth->heroscrn[25]); dismissButton->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->name % curHero->type->heroClass->name)); @@ -212,49 +227,62 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded) portraitImage->setFrame(curHero->portrait); { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); if(!garr) { std::string helpBox = heroscrn[32]; boost::algorithm::replace_first(helpBox, "%s", CGI->generaltexth->allTexts[43]); - garr = new CGarrisonInt(15, 485, 8, Point(), background->bg, Point(15,485), curHero); - auto split = new CButton(Point(539, 519), "hsbtns9.def", CButton::tooltip(CGI->generaltexth->allTexts[256], helpBox), [&](){ garr->splitClick(); }); - + garr = std::make_shared(15, 485, 8, Point(), curHero); + auto split = std::make_shared(Point(539, 519), "hsbtns9.def", CButton::tooltip(CGI->generaltexth->allTexts[256], helpBox), [&](){ garr->splitClick(); }); garr->addSplitBtn(split); } - if(!artSets.size()) + if(!arts) { - auto arts = new CArtifactsOfHero(Point(-65, -8), true); + arts = std::make_shared(Point(-65, -8), true); arts->setHero(curHero); - artSets.push_back(arts); + addSet(arts); } int serial = LOCPLINT->cb->getHeroSerial(curHero, false); - vstd::clear_pointer(listSelection); - if (serial >= 0) - listSelection = new CPicture("HPSYYY", 612, 33 + serial * 54); + listSelection.reset(); + if(serial >= 0) + listSelection = std::make_shared("HPSYYY", 612, 33 + serial * 54); } //primary skills support for(size_t g=0; gbonusValue = heroWArt.getPrimSkillLevel(static_cast(g)); + primSkillValues[g]->setText(boost::lexical_cast(primSkillAreas[g]->bonusValue)); } //secondary skills support for(size_t g=0; g< secSkillAreas.size(); ++g) { - int skill = curHero->secSkills[g].first, - level = curHero->getSecSkillLevel(SecondarySkill(curHero->secSkills[g].first)); + int skill = curHero->secSkills[g].first; + int level = curHero->getSecSkillLevel(SecondarySkill(curHero->secSkills[g].first)); + std::string skillName = CGI->skillh->skillName(skill); + std::string skillValue = CGI->generaltexth->levels[level-1]; + secSkillAreas[g]->type = skill; secSkillAreas[g]->bonusValue = level; secSkillAreas[g]->text = CGI->skillh->skillInfo(skill, level); - secSkillAreas[g]->hoverText = boost::str(boost::format(heroscrn[21]) % CGI->generaltexth->levels[level-1] % CGI->skillh->skillName(skill)); + secSkillAreas[g]->hoverText = boost::str(boost::format(heroscrn[21]) % skillValue % skillName); secSkillImages[g]->setFrame(skill*3 + level + 2); + secSkillNames[g]->setText(skillName); + secSkillValues[g]->setText(skillValue); } + std::ostringstream expstr; + expstr << curHero->exp; + expValue->setText(expstr.str()); + + std::ostringstream manastr; + manastr << curHero->mana << '/' << heroWArt.manaLimit(); + manaValue->setText(manastr.str()); + //printing experience - original format does not support ui64 expArea->text = CGI->generaltexth->allTexts[2]; boost::replace_first(expArea->text, "%d", boost::lexical_cast(curHero->level)); @@ -269,14 +297,16 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded) //if we have exchange window with this curHero open bool noDismiss=false; - for(IShowActivatable *isa : GH.listInt) + for(IShowActivatable * isa : GH.listInt) { if(CExchangeWindow * cew = dynamic_cast(isa)) - for(int g=0; g < ARRAY_COUNT(cew->heroInst); ++g) + { + for(int g=0; g < cew->heroInst.size(); ++g) if(cew->heroInst[g] == curHero) noDismiss = true; + } - if (dynamic_cast(isa)) + if(dynamic_cast(isa)) noDismiss = true; } //if player only have one hero and no towns @@ -289,17 +319,19 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded) dismissButton->block(!!curHero->visitedTown || noDismiss); if(curHero->getSecSkillLevel(SecondarySkill::TACTICS) == 0) + { tacticsButton->block(true); + } else { tacticsButton->block(false); - tacticsButton->addCallback( [&](bool on) {curHero->tacticFormationEnabled = on;}); - + tacticsButton->addCallback([&](bool on){curHero->tacticFormationEnabled = on;}); } + formations->resetCallback(); //setting formations formations->setSelected(curHero->formation); - formations->addCallback([&] (int value) { LOCPLINT->cb->setFormation(curHero, value); }); + formations->addCallback([=](int value){ LOCPLINT->cb->setFormation(curHero, value);}); morale->set(&heroWArt); luck->set(&heroWArt); @@ -312,26 +344,25 @@ void CHeroWindow::dismissCurrent() { CFunctionList ony = [=](){ close(); }; ony += [=](){ LOCPLINT->cb->dismissHero(curHero); }; - LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, 0, false); + LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, nullptr); } void CHeroWindow::commanderWindow() { - //TODO: allow equipping commander artifacts by drag / drop //bool artSelected = false; - const std::shared_ptr commonInfo = artSets.front()->commonInfo; + const std::shared_ptr commonInfo = getCommonPart(); - if (const CArtifactInstance *art = commonInfo->src.art) + if(const CArtifactInstance *art = commonInfo->src.art) { const CGHeroInstance *srcHero = commonInfo->src.AOH->getHero(); //artSelected = true; ArtifactPosition freeSlot = art->firstAvailableSlot (curHero->commander); - if (freeSlot < ArtifactPosition::COMMANDER_AFTER_LAST) //we don't want to put it in commander's backpack! + if(freeSlot < ArtifactPosition::COMMANDER_AFTER_LAST) //we don't want to put it in commander's backpack! { - ArtifactLocation src (srcHero, commonInfo->src.slotID); - ArtifactLocation dst (curHero->commander.get(), freeSlot); + ArtifactLocation src(srcHero, commonInfo->src.slotID); + ArtifactLocation dst(curHero->commander.get(), freeSlot); - if (art->canBePutAt(dst, true)) + if(art->canBePutAt(dst, true)) { //equip clicked stack if(dst.getArt()) { @@ -342,51 +373,13 @@ void CHeroWindow::commanderWindow() } } else + { GH.pushInt(new CStackWindow(curHero->commander, false)); - + } } void CHeroWindow::updateGarrisons() { - CWindowWithGarrison::updateGarrisons(); + garr->recreateSlots(); morale->set(&heroWArt); } - -void CHeroWindow::showAll(SDL_Surface * to) -{ - CIntObject::showAll(to); - - //printing hero's name - printAtMiddleLoc(curHero->name, 190, 38, FONT_BIG, Colors::YELLOW, to); - - //printing hero's level - std::string secondLine= CGI->generaltexth->allTexts[342]; - boost::algorithm::replace_first(secondLine,"%d",boost::lexical_cast(curHero->level)); - boost::algorithm::replace_first(secondLine,"%s",curHero->type->heroClass->name); - printAtMiddleLoc(secondLine, 190, 65, FONT_MEDIUM, Colors::WHITE, to); - - //printing primary skills' amounts - for(int m=0; m<4; ++m) - { - std::ostringstream primarySkill; - primarySkill << primSkillAreas[m]->bonusValue; - printAtMiddleLoc(primarySkill.str(), 53 + 70 * m, 166, FONT_SMALL, Colors::WHITE, to); - } - - //secondary skills - for(size_t v=0; vsecSkills.size()); ++v) - { - printAtLoc(CGI->generaltexth->levels[curHero->secSkills[v].second-1], (v%2) ? 212 : 68, 280 + 48 * (v/2), FONT_SMALL, Colors::WHITE, to); - printAtLoc(CGI->skillh->skillName(curHero->secSkills[v].first), (v%2) ? 212 : 68, 300 + 48 * (v/2), FONT_SMALL, Colors::WHITE, to); - } - - //printing special ability - printAtLoc(curHero->type->specName, 69, 205, FONT_SMALL, Colors::WHITE, to); - std::ostringstream expstr; - expstr << curHero->exp; - printAtLoc(expstr.str(), 68, 252, FONT_SMALL, Colors::WHITE, to); - - std::ostringstream manastr; - manastr << curHero->mana << '/' << heroWArt.manaLimit(); - printAtLoc(manastr.str(), 211, 252, FONT_SMALL, Colors::WHITE, to); -} diff --git a/client/windows/CHeroWindow.h b/client/windows/CHeroWindow.h index b39e20db7..fa03dc2e7 100644 --- a/client/windows/CHeroWindow.h +++ b/client/windows/CHeroWindow.h @@ -26,71 +26,95 @@ class MoraleLuckBox; class CToggleButton; class CToggleGroup; class CGStatusBar; +class CTextBox; /// Button which switches hero selection class CHeroSwitcher : public CIntObject { const CGHeroInstance * hero; - CAnimImage *image; + std::shared_ptr image; + CHeroWindow * owner; public: - virtual void clickLeft(tribool down, bool previousState) override; + void clickLeft(tribool down, bool previousState) override; - CHeroSwitcher(Point pos, const CGHeroInstance * hero); + CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInstance * hero_); }; //helper class for calculating values of hero bonuses without bonuses from picked up artifact class CHeroWithMaybePickedArtifact : public virtual IBonusBearer { public: - const CGHeroInstance *hero; - CWindowWithArtifacts *cww; + const CGHeroInstance * hero; + CWindowWithArtifacts * cww; - CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero); - const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const override; + CHeroWithMaybePickedArtifact(CWindowWithArtifacts * Cww, const CGHeroInstance * Hero); + const TBonusListPtr getAllBonuses(const CSelector & selector, const CSelector & limit, const CBonusSystemNode * root = nullptr, const std::string & cachingStr = "") const override; int64_t getTreeVersion() const override; }; -class CHeroWindow: public CWindowObject, public CWindowWithGarrison, public CWindowWithArtifacts +class CHeroWindow : public CWindowObject, public CGarrisonHolder, public CWindowWithArtifacts { - CGStatusBar * ourBar; //heroWindow's statusBar + std::shared_ptr name; + std::shared_ptr title; - //buttons - //CButton * gar4button; //splitting - std::vector heroList; //list of heroes - CPicture * listSelection; //selection border + std::shared_ptr banner; + std::shared_ptr statusBar; - //clickable areas - LRClickableAreaWText * portraitArea; - CAnimImage * portraitImage; + std::vector> heroList; + std::shared_ptr listSelection; + + std::shared_ptr portraitArea; + std::shared_ptr portraitImage; + + std::vector> primSkillAreas; + std::vector> primSkillImages; + std::vector> primSkillValues; + + std::shared_ptr expValue; + std::shared_ptr expArea; + + std::shared_ptr manaValue; + std::shared_ptr spellPointsArea; + + std::shared_ptr specArea; + std::shared_ptr specImage; + std::shared_ptr specName; + std::shared_ptr morale; + std::shared_ptr luck; + std::vector> secSkillAreas; + std::vector> secSkillImages; + std::vector> secSkillNames; + std::vector> secSkillValues; - std::vector primSkillAreas; - LRClickableAreaWText * expArea; - LRClickableAreaWText * spellPointsArea; - LRClickableAreaWText * specArea;//specialty - CAnimImage *specImage; - MoraleLuckBox * morale, * luck; - std::vector secSkillAreas; - std::vector secSkillImages; CHeroWithMaybePickedArtifact heroWArt; - CButton * quitButton, * dismissButton, * questlogButton, * commanderButton; //general + std::shared_ptr quitButton; + std::shared_ptr dismissLabel; + std::shared_ptr dismissButton; + std::shared_ptr questlogLabel; + std::shared_ptr questlogButton; + std::shared_ptr commanderButton; - CToggleButton *tacticsButton; //garrison / formation handling; - CToggleGroup *formations; + std::shared_ptr tacticsButton; + std::shared_ptr formations; + + std::shared_ptr garr; + std::shared_ptr arts; + + std::vector> labels; public: const CGHeroInstance * curHero; - CHeroWindow(const CGHeroInstance *hero); + CHeroWindow(const CGHeroInstance * hero); void update(const CGHeroInstance * hero, bool redrawNeeded = false); //sets main displayed hero - void showAll(SDL_Surface * to) override; void dismissCurrent(); //dissmissed currently displayed hero (curHero) void commanderWindow(); void switchHero(); //changes displayed hero - virtual void updateGarrisons() override; //updates the morale widget and calls the parent + void updateGarrisons() override; //friends friend void CHeroArtPlace::clickLeft(tribool down, bool previousState); diff --git a/client/windows/CKingdomInterface.cpp b/client/windows/CKingdomInterface.cpp index a8b351ca5..32a71fd8b 100644 --- a/client/windows/CKingdomInterface.cpp +++ b/client/windows/CKingdomInterface.cpp @@ -34,7 +34,7 @@ #include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/MiscObjects.h" -InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, IInfoBoxData *Data): +InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr Data): size(Size), infoPos(Pos), data(Data), @@ -45,52 +45,51 @@ InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, IInfoBoxData *Data) addUsedEvents(LCLICK | RCLICK); EFonts font = (size < SIZE_MEDIUM)? FONT_SMALL: FONT_MEDIUM; - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); pos+=position; - image = new CAnimImage(data->getImageName(size), data->getImageIndex()); + image = std::make_shared(data->getImageName(size), data->getImageIndex()); pos = image->pos; - if (infoPos == POS_CORNER) - value = new CLabel(pos.w, pos.h, font, BOTTOMRIGHT, Colors::WHITE, data->getValueText()); - - if (infoPos == POS_INSIDE) - value = new CLabel(pos.w/2, pos.h-6, font, CENTER, Colors::WHITE, data->getValueText()); - - if (infoPos == POS_UP_DOWN || infoPos == POS_DOWN) - value = new CLabel(pos.w/2, pos.h+8, font, CENTER, Colors::WHITE, data->getValueText()); - - if (infoPos == POS_UP_DOWN) - name = new CLabel(pos.w/2, -12, font, CENTER, Colors::WHITE, data->getNameText()); - - if (infoPos == POS_RIGHT) + switch(infoPos) { - name = new CLabel(pos.w+6, 6, font, TOPLEFT, Colors::WHITE, data->getNameText()); - value = new CLabel(pos.w+6, pos.h-16, font, TOPLEFT, Colors::WHITE, data->getValueText()); + case POS_CORNER: + value = std::make_shared(pos.w, pos.h, font, BOTTOMRIGHT, Colors::WHITE, data->getValueText()); + break; + case POS_INSIDE: + value = std::make_shared(pos.w/2, pos.h-6, font, CENTER, Colors::WHITE, data->getValueText()); + break; + case POS_UP_DOWN: + name = std::make_shared(pos.w/2, -12, font, CENTER, Colors::WHITE, data->getNameText()); + FALLTHROUGH; + case POS_DOWN: + value = std::make_shared(pos.w/2, pos.h+8, font, CENTER, Colors::WHITE, data->getValueText()); + break; + case POS_RIGHT: + name = std::make_shared(pos.w+6, 6, font, TOPLEFT, Colors::WHITE, data->getNameText()); + value = std::make_shared(pos.w+6, pos.h-16, font, TOPLEFT, Colors::WHITE, data->getValueText()); + break; } - pos = image->pos; - if (name) + + if(name) pos = pos | name->pos; - if (value) + if(value) pos = pos | value->pos; - hover = new CHoverableArea(); + hover = std::make_shared(); hover->hoverText = data->getHoverText(); hover->pos = pos; } -InfoBox::~InfoBox() -{ - delete data; -} +InfoBox::~InfoBox() = default; void InfoBox::clickRight(tribool down, bool previousState) { if (down) { - CComponent *comp = nullptr; + std::shared_ptr comp; std::string text; - data->prepareMessage(text, &comp); + data->prepareMessage(text, comp); if (comp) CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp)); else if (!text.empty()) @@ -102,16 +101,12 @@ void InfoBox::clickLeft(tribool down, bool previousState) { if((!down) && previousState) { - CComponent *comp = nullptr; + std::shared_ptr comp; std::string text; - data->prepareMessage(text, &comp); + data->prepareMessage(text, comp); - std::vector compVector; - if (comp) - { - compVector.push_back(comp); - LOCPLINT->showInfoDialog(text, compVector); - } + if(comp) + LOCPLINT->showInfoDialog(text, CInfoWindow::TCompsInfo(1, comp)); } } @@ -123,13 +118,13 @@ void InfoBox::update() } */ -IInfoBoxData::IInfoBoxData(InfoType Type): - type(Type) +IInfoBoxData::IInfoBoxData(InfoType Type) + : type(Type) { } -InfoBoxAbstractHeroData::InfoBoxAbstractHeroData(InfoType Type): - IInfoBoxData(Type) +InfoBoxAbstractHeroData::InfoBoxAbstractHeroData(InfoType Type) + : IInfoBoxData(Type) { } @@ -255,40 +250,37 @@ size_t InfoBoxAbstractHeroData::getImageIndex() } } -bool InfoBoxAbstractHeroData::prepareMessage(std::string &text, CComponent **comp) +void InfoBoxAbstractHeroData::prepareMessage(std::string & text, std::shared_ptr & comp) { + comp.reset(); switch (type) { case HERO_SPECIAL: text = CGI->heroh->heroes[getSubID()]->specDescr; - *comp = nullptr; - return true; + break; case HERO_PRIMARY_SKILL: text = CGI->generaltexth->arraytxt[2+getSubID()]; - *comp =new CComponent(CComponent::primskill, getSubID(), getValue()); - return true; + comp = std::make_shared(CComponent::primskill, getSubID(), getValue()); + break; case HERO_MANA: text = CGI->generaltexth->allTexts[149]; - *comp = nullptr; - return true; + break; case HERO_EXPERIENCE: text = CGI->generaltexth->allTexts[241]; - *comp = nullptr; - return true; + break; case HERO_SECONDARY_SKILL: { si64 value = getValue(); int subID = getSubID(); - if (!value) - return false; - - text = CGI->skillh->skillInfo(subID, value); - *comp = new CComponent(CComponent::secskill, subID, value); - return true; + if(value) + { + text = CGI->skillh->skillInfo(subID, value); + comp = std::make_shared(CComponent::secskill, subID, value); + } + break; } default: - assert(0); - return false; + break; } } @@ -388,8 +380,9 @@ std::string InfoBoxHeroData::getValueText() return InfoBoxAbstractHeroData::getValueText(); } -bool InfoBoxHeroData::prepareMessage(std::string &text, CComponent**comp) +void InfoBoxHeroData::prepareMessage(std::string & text, std::shared_ptr & comp) { + comp.reset(); switch(type) { case HERO_MANA: @@ -397,19 +390,16 @@ bool InfoBoxHeroData::prepareMessage(std::string &text, CComponent**comp) boost::replace_first(text, "%s", boost::lexical_cast(hero->name)); boost::replace_first(text, "%d", boost::lexical_cast(hero->mana)); boost::replace_first(text, "%d", boost::lexical_cast(hero->manaLimit())); - *comp = nullptr; - return true; - + break; case HERO_EXPERIENCE: text = CGI->generaltexth->allTexts[2]; boost::replace_first(text, "%d", boost::lexical_cast(hero->level)); boost::replace_first(text, "%d", boost::lexical_cast(CGI->heroh->reqExp(hero->level+1))); boost::replace_first(text, "%d", boost::lexical_cast(hero->exp)); - *comp = nullptr; - return true; - + break; default: - return InfoBoxAbstractHeroData::prepareMessage(text, comp); + InfoBoxAbstractHeroData::prepareMessage(text, comp); + break; } } @@ -465,26 +455,25 @@ std::string InfoBoxCustom::getValueText() return valueText; } -bool InfoBoxCustom::prepareMessage(std::string &text, CComponent **comp) +void InfoBoxCustom::prepareMessage(std::string & text, std::shared_ptr & comp) { - return false; } -CKingdomInterface::CKingdomInterface(): - CWindowObject(PLAYER_COLORED | BORDERED, conf.go()->ac.overviewBg) +CKingdomInterface::CKingdomInterface() + : CWindowObject(PLAYER_COLORED | BORDERED, conf.go()->ac.overviewBg) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); ui32 footerPos = conf.go()->ac.overviewSize * 116; - tabArea = new CTabbedInt(std::bind(&CKingdomInterface::createMainTab, this, _1), CTabbedInt::DestroyFunc(), Point(4,4)); + tabArea = std::make_shared(std::bind(&CKingdomInterface::createMainTab, this, _1), Point(4,4)); std::vector ownedObjects = LOCPLINT->cb->getMyObjects(); generateObjectsList(ownedObjects); generateMinesList(ownedObjects); generateButtons(); - statusbar = new CGStatusBar(new CPicture("KSTATBAR", 10,pos.h - 45)); - resdatabar= new CResDataBar("KRESBAR", 3, 111+footerPos, 32, 2, 76, 76); + statusbar = std::make_shared(std::make_shared("KSTATBAR", 10,pos.h - 45)); + resdatabar = std::make_shared("KRESBAR", 3, 111+footerPos, 32, 2, 76, 76); } void CKingdomInterface::generateObjectsList(const std::vector &ownedObjects) @@ -508,10 +497,10 @@ void CKingdomInterface::generateObjectsList(const std::vectorID == Obj::CREATURE_GENERATOR1 ) + if(object->ID == Obj::CREATURE_GENERATOR1) { - OwnedObjectInfo &info = visibleObjects[object->subID]; - if (info.count++ == 0) + OwnedObjectInfo & info = visibleObjects[object->subID]; + if(info.count++ == 0) { info.hoverText = object->getObjectName(); info.imageID = object->subID; @@ -519,10 +508,10 @@ void CKingdomInterface::generateObjectsList(const std::vectorID, object->subID)); - if (iter != idToImage.end()) + if(iter != idToImage.end()) { - OwnedObjectInfo &info = visibleObjects[iter->second]; - if (info.count++ == 0) + OwnedObjectInfo & info = visibleObjects[iter->second]; + if(info.count++ == 0) { info.hoverText = object->getObjectName(); info.imageID = iter->second; @@ -535,34 +524,37 @@ void CKingdomInterface::generateObjectsList(const std::vector(std::bind(&CKingdomInterface::createOwnedObject, this, _1), + Point(740,44), Point(0,57), dwellSize, visibleObjects.size()); } -CIntObject* CKingdomInterface::createOwnedObject(size_t index) +std::shared_ptr CKingdomInterface::createOwnedObject(size_t index) { - if (index < objects.size()) + if(index < objects.size()) { - OwnedObjectInfo &obj = objects[index]; + OwnedObjectInfo & obj = objects[index]; std::string value = boost::lexical_cast(obj.count); - return new InfoBox(Point(), InfoBox::POS_CORNER, InfoBox::SIZE_SMALL, - new InfoBoxCustom(value,"", "FLAGPORT", obj.imageID, obj.hoverText)); + auto data = std::make_shared(value, "", "FLAGPORT", obj.imageID, obj.hoverText); + return std::make_shared(Point(), InfoBox::POS_CORNER, InfoBox::SIZE_SMALL, data); } - return nullptr; + return std::shared_ptr(); } -CIntObject * CKingdomInterface::createMainTab(size_t index) +std::shared_ptr CKingdomInterface::createMainTab(size_t index) { size_t size = conf.go()->ac.overviewSize; - switch (index) + switch(index) { - case 0: return new CKingdHeroList(size); - case 1: return new CKingdTownList(size); - default:return nullptr; + case 0: + return std::make_shared(size); + case 1: + return std::make_shared(size); + default: + return std::shared_ptr(); } } -void CKingdomInterface::generateMinesList(const std::vector &ownedObjects) +void CKingdomInterface::generateMinesList(const std::vector & ownedObjects) { ui32 footerPos = conf.go()->ac.overviewSize * 116; std::vector minesCount(GameConstants::RESOURCE_QUANTITY, 0); @@ -573,7 +565,7 @@ void CKingdomInterface::generateMinesList(const std::vectorID == Obj::MINE || object->ID == Obj::ABANDONED_MINE) { - const CGMine *mine = dynamic_cast(object); + const CGMine * mine = dynamic_cast(object); assert(mine); minesCount[mine->producedResource]++; @@ -596,18 +588,17 @@ void CKingdomInterface::generateMinesList(const std::vectordailyIncome()[Res::GOLD]; } - for (int i=0; i<7; i++) + for(int i=0; i<7; i++) { std::string value = boost::lexical_cast(minesCount[i]); - minesBox[i] = new InfoBox(Point(20+i*80, 31+footerPos), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, - new InfoBoxCustom(value, "", "OVMINES", i, CGI->generaltexth->mines[i].first)); - + auto data = std::make_shared(value, "", "OVMINES", i, CGI->generaltexth->mines[i].first); + minesBox[i] = std::make_shared(Point(20+i*80, 31+footerPos), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, data); minesBox[i]->removeUsedEvents(LCLICK|RCLICK); //fixes #890 - mines boxes ignore clicks } - incomeArea = new CHoverableArea(); + incomeArea = std::make_shared(); incomeArea->pos = Rect(pos.x+580, pos.y+31+footerPos, 136, 68); incomeArea->hoverText = CGI->generaltexth->allTexts[255]; - incomeAmount = new CLabel(628, footerPos + 70, FONT_SMALL, TOPLEFT, Colors::WHITE, boost::lexical_cast(totalIncome)); + incomeAmount = std::make_shared(628, footerPos + 70, FONT_SMALL, TOPLEFT, Colors::WHITE, boost::lexical_cast(totalIncome)); } void CKingdomInterface::generateButtons() @@ -615,28 +606,28 @@ void CKingdomInterface::generateButtons() ui32 footerPos = conf.go()->ac.overviewSize * 116; //Main control buttons - btnHeroes = new CButton (Point(748, 28+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->overview[11], CGI->generaltexth->overview[6]), - std::bind(&CKingdomInterface::activateTab, this, 0), SDLK_h); + btnHeroes = std::make_shared(Point(748, 28+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->overview[11], CGI->generaltexth->overview[6]), + std::bind(&CKingdomInterface::activateTab, this, 0), SDLK_h); btnHeroes->block(true); - btnTowns = new CButton (Point(748, 64+footerPos), "OVBUTN6.DEF", CButton::tooltip(CGI->generaltexth->overview[12], CGI->generaltexth->overview[7]), - std::bind(&CKingdomInterface::activateTab, this, 1), SDLK_t); + btnTowns = std::make_shared(Point(748, 64+footerPos), "OVBUTN6.DEF", CButton::tooltip(CGI->generaltexth->overview[12], CGI->generaltexth->overview[7]), + std::bind(&CKingdomInterface::activateTab, this, 1), SDLK_t); - btnExit = new CButton (Point(748,99+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[600]), - std::bind(&CKingdomInterface::close, this), SDLK_RETURN); + btnExit = std::make_shared(Point(748,99+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[600]), + std::bind(&CKingdomInterface::close, this), SDLK_RETURN); btnExit->assignedKeys.insert(SDLK_ESCAPE); btnExit->setImageOrder(3, 4, 5, 6); //Object list control buttons - dwellTop = new CButton (Point(733, 4), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPos(0);}); + dwellTop = std::make_shared(Point(733, 4), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPos(0);}); - dwellBottom = new CButton (Point(733, footerPos+2), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPos(-1); }); + dwellBottom = std::make_shared(Point(733, footerPos+2), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPos(-1); }); dwellBottom->setImageOrder(2, 3, 4, 5); - dwellUp = new CButton (Point(733, 24), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPrev(); }); + dwellUp = std::make_shared(Point(733, 24), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPrev(); }); dwellUp->setImageOrder(4, 5, 6, 7); - dwellDown = new CButton (Point(733, footerPos-18), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToNext(); }); + dwellDown = std::make_shared(Point(733, footerPos-18), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToNext(); }); dwellDown->setImageOrder(6, 7, 8, 9); } @@ -649,160 +640,148 @@ void CKingdomInterface::activateTab(size_t which) void CKingdomInterface::townChanged(const CGTownInstance *town) { - if (CKingdTownList * townList = dynamic_cast(tabArea->getItem())) + if(auto townList = std::dynamic_pointer_cast(tabArea->getItem())) townList->townChanged(town); } void CKingdomInterface::updateGarrisons() { - if (CGarrisonHolder * garrison = dynamic_cast(tabArea->getItem())) + if(auto garrison = std::dynamic_pointer_cast(tabArea->getItem())) garrison->updateGarrisons(); } void CKingdomInterface::artifactAssembled(const ArtifactLocation& artLoc) { - if (CArtifactHolder * arts = dynamic_cast(tabArea->getItem())) + if(auto arts = std::dynamic_pointer_cast(tabArea->getItem())) arts->artifactAssembled(artLoc); } void CKingdomInterface::artifactDisassembled(const ArtifactLocation& artLoc) { - if (CArtifactHolder * arts = dynamic_cast(tabArea->getItem())) + if(auto arts = std::dynamic_pointer_cast(tabArea->getItem())) arts->artifactDisassembled(artLoc); } void CKingdomInterface::artifactMoved(const ArtifactLocation& artLoc, const ArtifactLocation& destLoc) { - if (CArtifactHolder * arts = dynamic_cast(tabArea->getItem())) + if(auto arts = std::dynamic_pointer_cast(tabArea->getItem())) arts->artifactMoved(artLoc, destLoc); } void CKingdomInterface::artifactRemoved(const ArtifactLocation& artLoc) { - if (CArtifactHolder * arts = dynamic_cast(tabArea->getItem())) + if(auto arts = std::dynamic_pointer_cast(tabArea->getItem())) arts->artifactRemoved(artLoc); } CKingdHeroList::CKingdHeroList(size_t maxSize) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - title = new CPicture("OVTITLE",16,0); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + title = std::make_shared("OVTITLE",16,0); title->colorize(LOCPLINT->playerID); - heroLabel = new CLabel(150, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[0]); - skillsLabel = new CLabel(500, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[1]); + heroLabel = std::make_shared(150, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[0]); + skillsLabel = std::make_shared(500, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[1]); ui32 townCount = LOCPLINT->cb->howManyHeroes(false); ui32 size = conf.go()->ac.overviewSize*116 + 19; - heroes = new CListBox(std::bind(&CKingdHeroList::createHeroItem, this, _1), std::bind(&CKingdHeroList::destroyHeroItem, this, _1), - Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size) ); + heroes = std::make_shared(std::bind(&CKingdHeroList::createHeroItem, this, _1), + Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size)); } void CKingdHeroList::updateGarrisons() { - std::list list = heroes->getItems(); - for(CIntObject* object : list) + for(std::shared_ptr object : heroes->getItems()) { - if (CGarrisonHolder * garrison = dynamic_cast(object) ) + if(CGarrisonHolder * garrison = dynamic_cast(object.get())) garrison->updateGarrisons(); } } -CIntObject* CKingdHeroList::createHeroItem(size_t index) +std::shared_ptr CKingdHeroList::createHeroItem(size_t index) { ui32 picCount = conf.go()->ac.overviewPics; size_t heroesCount = LOCPLINT->cb->howManyHeroes(false); - if (index < heroesCount) + if(index < heroesCount) { - auto hero = new CHeroItem(LOCPLINT->cb->getHeroBySerial(index, false)); - artSets.push_back(hero->heroArts); + auto hero = std::make_shared(LOCPLINT->cb->getHeroBySerial(index, false)); + addSet(hero->heroArts); return hero; } else { - return new CAnimImage("OVSLOT", (index-2) % picCount ); + return std::make_shared("OVSLOT", (index-2) % picCount ); } } -void CKingdHeroList::destroyHeroItem(CIntObject *object) -{ - if (CHeroItem * hero = dynamic_cast(object)) - { - artSets.erase(std::find(artSets.begin(), artSets.end(), hero->heroArts)); - } - delete object; -} - CKingdTownList::CKingdTownList(size_t maxSize) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - title = new CPicture("OVTITLE",16,0); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + title = std::make_shared("OVTITLE", 16, 0); title->colorize(LOCPLINT->playerID); - townLabel = new CLabel(146,10,FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[3]); - garrHeroLabel = new CLabel(375,10,FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[4]); - visitHeroLabel = new CLabel(608,10,FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[5]); + townLabel = std::make_shared(146, 10,FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[3]); + garrHeroLabel = std::make_shared(375, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[4]); + visitHeroLabel = std::make_shared(608, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[5]); ui32 townCount = LOCPLINT->cb->howManyTowns(); ui32 size = conf.go()->ac.overviewSize*116 + 19; - towns = new CListBox(std::bind(&CKingdTownList::createTownItem, this, _1), CListBox::DestroyFunc(), - Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size) ); + towns = std::make_shared(std::bind(&CKingdTownList::createTownItem, this, _1), + Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size)); } -void CKingdTownList::townChanged(const CGTownInstance *town) +void CKingdTownList::townChanged(const CGTownInstance * town) { - std::list list = towns->getItems(); - for(CIntObject* object : list) + for(std::shared_ptr object : towns->getItems()) { - CTownItem * townItem = dynamic_cast(object); - if ( townItem && townItem->town == town) + CTownItem * townItem = dynamic_cast(object.get()); + if(townItem && townItem->town == town) townItem->update(); } } void CKingdTownList::updateGarrisons() { - std::list list = towns->getItems(); - for(CIntObject* object : list) + for(std::shared_ptr object : towns->getItems()) { - if (CGarrisonHolder * garrison = dynamic_cast(object) ) + if(CGarrisonHolder * garrison = dynamic_cast(object.get())) garrison->updateGarrisons(); } } -CIntObject* CKingdTownList::createTownItem(size_t index) +std::shared_ptr CKingdTownList::createTownItem(size_t index) { ui32 picCount = conf.go()->ac.overviewPics; size_t townsCount = LOCPLINT->cb->howManyTowns(); - if (index < townsCount) - return new CTownItem(LOCPLINT->cb->getTownBySerial(index)); + if(index < townsCount) + return std::make_shared(LOCPLINT->cb->getTownBySerial(index)); else - return new CAnimImage("OVSLOT", (index-2) % picCount ); + return std::make_shared("OVSLOT", (index-2) % picCount ); } -CTownItem::CTownItem(const CGTownInstance* Town): - town(Town) +CTownItem::CTownItem(const CGTownInstance * Town) + : town(Town) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - background = new CAnimImage("OVSLOT", 6); - name = new CLabel(74, 8, FONT_SMALL, TOPLEFT, Colors::WHITE, town->name); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background = std::make_shared("OVSLOT", 6); + name = std::make_shared(74, 8, FONT_SMALL, TOPLEFT, Colors::WHITE, town->name); - income = new CLabel( 190, 60, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast(town->dailyIncome()[Res::GOLD])); - hall = new CTownInfo( 69, 31, town, true); - fort = new CTownInfo(111, 31, town, false); + income = std::make_shared( 190, 60, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast(town->dailyIncome()[Res::GOLD])); + hall = std::make_shared( 69, 31, town, true); + fort = std::make_shared(111, 31, town, false); - garr = new CGarrisonInt(313, 3, 4, Point(232,0), nullptr, Point(313,2), town->getUpperArmy(), town->visitingHero, true, true, true); - heroes = new HeroSlots(town, Point(244,6), Point(475,6), garr, false); + garr = std::make_shared(313, 3, 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, true); + heroes = std::make_shared(town, Point(244,6), Point(475,6), garr, false); size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN]; - picture = new CAnimImage("ITPT", iconIndex, 0, 5, 6); - new LRClickableAreaOpenTown(Rect(5, 6, 58, 64), town); + picture = std::make_shared("ITPT", iconIndex, 0, 5, 6); + openTown = std::make_shared(Rect(5, 6, 58, 64), town); - for (size_t i=0; icreatures.size(); i++) + for(size_t i=0; icreatures.size(); i++) { - growth.push_back(new CCreaInfo(Point(401+37*i, 78), town, i, true, true)); - available.push_back(new CCreaInfo(Point(48+37*i, 78), town, i, true, false)); + growth.push_back(std::make_shared(Point(401+37*i, 78), town, i, true, true)); + available.push_back(std::make_shared(Point(48+37*i, 78), town, i, true, false)); } } @@ -832,62 +811,62 @@ void CTownItem::update() class ArtSlotsTab : public CIntObject { public: - CAnimImage * background; - std::vector arts; + std::shared_ptr background; + std::vector> arts; ArtSlotsTab() { - OBJ_CONSTRUCTION_CAPTURING_ALL; - background = new CAnimImage("OVSLOT", 4); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background = std::make_shared("OVSLOT", 4); pos = background->pos; - for (size_t i=0; i<9; i++) - arts.push_back(new CHeroArtPlace(Point(270+i*48, 65))); + for(size_t i=0; i<9; i++) + arts.push_back(std::make_shared(Point(270+i*48, 65))); } }; class BackpackTab : public CIntObject { public: - CAnimImage * background; - std::vector arts; - CButton *btnLeft; - CButton *btnRight; + std::shared_ptr background; + std::vector> arts; + std::shared_ptr btnLeft; + std::shared_ptr btnRight; BackpackTab() { - OBJ_CONSTRUCTION_CAPTURING_ALL; - background = new CAnimImage("OVSLOT", 5); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + background = std::make_shared("OVSLOT", 5); pos = background->pos; - btnLeft = new CButton(Point(269, 66), "HSBTNS3", CButton::tooltip(), 0); - btnRight = new CButton(Point(675, 66), "HSBTNS5", CButton::tooltip(), 0); - for (size_t i=0; i<8; i++) - arts.push_back(new CHeroArtPlace(Point(295+i*48, 65))); + btnLeft = std::make_shared(Point(269, 66), "HSBTNS3", CButton::tooltip(), 0); + btnRight = std::make_shared(Point(675, 66), "HSBTNS5", CButton::tooltip(), 0); + for(size_t i=0; i<8; i++) + arts.push_back(std::make_shared(Point(295+i*48, 65))); } }; -CHeroItem::CHeroItem(const CGHeroInstance* Hero): - hero(Hero) +CHeroItem::CHeroItem(const CGHeroInstance * Hero) + : hero(Hero) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); artTabs.resize(3); - auto arts1 = new ArtSlotsTab(); - auto arts2 = new ArtSlotsTab(); - auto backpack = new BackpackTab(); + auto arts1 = std::make_shared(); + auto arts2 = std::make_shared(); + auto backpack = std::make_shared(); artTabs[0] = arts1; artTabs[1] = arts2; artTabs[2] = backpack; - arts1->recActions = DISPOSE | SHARE_POS; - arts2->recActions = DISPOSE | SHARE_POS; - backpack->recActions = DISPOSE | SHARE_POS; + arts1->recActions = SHARE_POS; + arts2->recActions = SHARE_POS; + backpack->recActions = SHARE_POS; - name = new CLabel(75, 7, FONT_SMALL, TOPLEFT, Colors::WHITE, hero->name); + name = std::make_shared(75, 7, FONT_SMALL, TOPLEFT, Colors::WHITE, hero->name); //layout is not trivial: MACH4 - catapult - excluded, MISC[x] rearranged assert(arts1->arts.size() == 9); assert(arts2->arts.size() == 9); - std::map arts = + CArtifactsOfHero::ArtPlaceMap arts = { {ArtifactPosition::HEAD, arts1->arts[0]}, {ArtifactPosition::SHOULDERS,arts1->arts[1]}, @@ -911,20 +890,20 @@ CHeroItem::CHeroItem(const CGHeroInstance* Hero): }; - heroArts = new CArtifactsOfHero(arts, backpack->arts, backpack->btnLeft, backpack->btnRight, true); + heroArts = std::make_shared(arts, backpack->arts, backpack->btnLeft, backpack->btnRight, true); heroArts->setHero(hero); - artsTabs = new CTabbedInt(std::bind(&CHeroItem::onTabSelected, this, _1), std::bind(&CHeroItem::onTabDeselected, this, _1)); + artsTabs = std::make_shared(std::bind(&CHeroItem::onTabSelected, this, _1)); - artButtons = new CToggleGroup(0); - for (size_t it = 0; it<3; it++) + artButtons = std::make_shared(0); + for(size_t it = 0; it<3; it++) { int stringID[3] = {259, 261, 262}; std::string hover = CGI->generaltexth->overview[13+it]; std::string overlay = CGI->generaltexth->overview[8+it]; - auto button = new CToggleButton(Point(364+it*112, 46), "OVBUTN3", CButton::tooltip(hover, overlay), 0); + auto button = std::make_shared(Point(364+it*112, 46), "OVBUTN3", CButton::tooltip(hover, overlay), 0); button->addTextOverlay(CGI->generaltexth->allTexts[stringID[it]], FONT_SMALL, Colors::YELLOW); artButtons->addToggle(it, button); } @@ -932,53 +911,58 @@ CHeroItem::CHeroItem(const CGHeroInstance* Hero): artButtons->addCallback(std::bind(&CHeroItem::onArtChange, this, _1)); artButtons->setSelected(0); - garr = new CGarrisonInt(6, 78, 4, Point(), nullptr, Point(), hero, nullptr, true, true); + garr = std::make_shared(6, 78, 4, Point(), hero, nullptr, true, true); - portrait = new CAnimImage("PortraitsLarge", hero->portrait, 0, 5, 6); - heroArea = new CHeroArea(5, 6, hero); + portrait = std::make_shared("PortraitsLarge", hero->portrait, 0, 5, 6); + heroArea = std::make_shared(5, 6, hero); - name = new CLabel(73, 7, FONT_SMALL, TOPLEFT, Colors::WHITE, hero->name); - artsText = new CLabel(320, 55, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->overview[2]); + name = std::make_shared(73, 7, FONT_SMALL, TOPLEFT, Colors::WHITE, hero->name); + artsText = std::make_shared(320, 55, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->overview[2]); - for (size_t i=0; i(IInfoBoxData::HERO_PRIMARY_SKILL, hero, i); + heroInfo.push_back(std::make_shared(Point(78+i*36, 26), InfoBox::POS_DOWN, InfoBox::SIZE_SMALL, data)); + } - for (size_t i=0; i(IInfoBoxData::HERO_SECONDARY_SKILL, hero, i); + heroInfo.push_back(std::make_shared(Point(410+i*36, 5), InfoBox::POS_NONE, InfoBox::SIZE_SMALL, data)); + } - heroInfo.push_back(new InfoBox(Point(375, 5), InfoBox::POS_NONE, InfoBox::SIZE_SMALL, - new InfoBoxHeroData(IInfoBoxData::HERO_SPECIAL, hero))); + { + auto data = std::make_shared(IInfoBoxData::HERO_SPECIAL, hero); + heroInfo.push_back(std::make_shared(Point(375, 5), InfoBox::POS_NONE, InfoBox::SIZE_SMALL, data)); - heroInfo.push_back(new InfoBox(Point(330, 5), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, - new InfoBoxHeroData(IInfoBoxData::HERO_EXPERIENCE, hero))); + data = std::make_shared(IInfoBoxData::HERO_EXPERIENCE, hero); + heroInfo.push_back(std::make_shared(Point(330, 5), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, data)); - heroInfo.push_back(new InfoBox(Point(280, 5), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, - new InfoBoxHeroData(IInfoBoxData::HERO_MANA, hero))); + data = std::make_shared(IInfoBoxData::HERO_MANA, hero); + heroInfo.push_back(std::make_shared(Point(280, 5), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, data)); + } - morale = new MoraleLuckBox(true, Rect(225, 53, 30, 22), true); - luck = new MoraleLuckBox(false, Rect(225, 28, 30, 22), true); + morale = std::make_shared(true, Rect(225, 53, 30, 22), true); + luck = std::make_shared(false, Rect(225, 28, 30, 22), true); morale->set(hero); luck->set(hero); } -CIntObject * CHeroItem::onTabSelected(size_t index) + +void CHeroItem::updateGarrisons() { - return artTabs[index]; + garr->recreateSlots(); } -void CHeroItem::onTabDeselected(CIntObject *object) +std::shared_ptr CHeroItem::onTabSelected(size_t index) { - addChild(object, false); - object->deactivate(); - object->recActions = DISPOSE | SHARE_POS; + return artTabs.at(index); } void CHeroItem::onArtChange(int tabIndex) { //redraw item after background change - if (active) + if(active) redraw(); } diff --git a/client/windows/CKingdomInterface.h b/client/windows/CKingdomInterface.h index 147300256..9109eba3b 100644 --- a/client/windows/CKingdomInterface.h +++ b/client/windows/CKingdomInterface.h @@ -61,16 +61,16 @@ public: private: InfoSize size; - InfoPos infoPos; - IInfoBoxData *data; + InfoPos infoPos; + std::shared_ptr data; - CLabel * value; - CLabel * name; - CAnimImage * image; - CHoverableArea *hover; + std::shared_ptr value; + std::shared_ptr name; + std::shared_ptr image; + std::shared_ptr hover; public: - InfoBox(Point position, InfoPos Pos, InfoSize Size, IInfoBoxData *Data); + InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr Data); ~InfoBox(); void clickRight(tribool down, bool previousState) override; @@ -106,7 +106,7 @@ public: virtual size_t getImageIndex()=0; //TODO: replace with something better - virtual bool prepareMessage(std::string &text, CComponent **comp)=0; + virtual void prepareMessage(std::string & text, std::shared_ptr & comp)=0; virtual ~IInfoBoxData(){}; }; @@ -126,7 +126,7 @@ public: std::string getHoverText() override; size_t getImageIndex() override; - bool prepareMessage(std::string &text, CComponent **comp) override; + void prepareMessage(std::string & text, std::shared_ptr & comp) override; }; class InfoBoxHeroData : public InfoBoxAbstractHeroData @@ -144,7 +144,7 @@ public: std::string getHoverText() override; std::string getValueText() override; - bool prepareMessage(std::string &text, CComponent **comp) override; + void prepareMessage(std::string & text, std::shared_ptr & comp) override; }; class InfoBoxCustomHeroData : public InfoBoxAbstractHeroData @@ -176,7 +176,7 @@ public: std::string getHoverText() override; size_t getImageIndex() override; - bool prepareMessage(std::string &text, CComponent **comp) override; + void prepareMessage(std::string & text, std::shared_ptr & comp) override; }; //TODO!!! @@ -197,8 +197,6 @@ public: size_t getImageIndex() override; }; -//////////////////////////////////////////////////////////////////////////////// - /// Class which holds all parts of kingdom overview window class CKingdomInterface : public CWindowObject, public CGarrisonHolder, public CArtifactHolder { @@ -215,25 +213,27 @@ private: }; std::vector objects; - CListBox * dwellingsList; - CTabbedInt * tabArea; + std::shared_ptr dwellingsList; + std::shared_ptr tabArea; //Main buttons - CButton *btnTowns; - CButton *btnHeroes; - CButton *btnExit; + std::shared_ptr btnTowns; + std::shared_ptr btnHeroes; + std::shared_ptr btnExit; //Buttons for scrolling dwellings list - CButton *dwellUp, *dwellDown; - CButton *dwellTop, *dwellBottom; + std::shared_ptr dwellUp; + std::shared_ptr dwellDown; + std::shared_ptr dwellTop; + std::shared_ptr dwellBottom; - InfoBox * minesBox[7]; + std::array, 7> minesBox; - CHoverableArea * incomeArea; - CLabel * incomeAmount; + std::shared_ptr incomeArea; + std::shared_ptr incomeAmount; - CGStatusBar * statusbar; - CResDataBar *resdatabar; + std::shared_ptr statusbar; + std::shared_ptr resdatabar; void activateTab(size_t which); @@ -242,8 +242,8 @@ private: void generateObjectsList(const std::vector &ownedObjects); void generateMinesList(const std::vector &ownedObjects); - CIntObject* createOwnedObject(size_t index); - CIntObject* createMainTab(size_t index); + std::shared_ptr createOwnedObject(size_t index); + std::shared_ptr createMainTab(size_t index); public: CKingdomInterface(); @@ -259,67 +259,73 @@ public: /// List item with town class CTownItem : public CIntObject, public CGarrisonHolder { - CAnimImage *background; - CAnimImage *picture; - CLabel *name; - CLabel *income; - CGarrisonInt *garr; + std::shared_ptr background; + std::shared_ptr picture; + std::shared_ptr name; + std::shared_ptr income; + std::shared_ptr garr; - HeroSlots *heroes; - CTownInfo *hall, *fort; - std::vector available; - std::vector growth; + std::shared_ptr heroes; + std::shared_ptr hall; + std::shared_ptr fort; + + std::vector> available; + std::vector> growth; + + std::shared_ptr openTown; public: const CGTownInstance * town; - CTownItem(const CGTownInstance* town); + CTownItem(const CGTownInstance * Town); void updateGarrisons() override; void update(); }; /// List item with hero -class CHeroItem : public CIntObject, public CWindowWithGarrison +class CHeroItem : public CIntObject, public CGarrisonHolder { const CGHeroInstance * hero; - std::vector artTabs; + std::vector> artTabs; - CAnimImage *portrait; - CLabel *name; - CHeroArea *heroArea; + std::shared_ptr portrait; + std::shared_ptr name; + std::shared_ptr heroArea; - CLabel *artsText; - CTabbedInt *artsTabs; + std::shared_ptr artsText; + std::shared_ptr artsTabs; - CToggleGroup *artButtons; - std::vector heroInfo; - MoraleLuckBox * morale, * luck; + std::shared_ptr artButtons; + std::vector> heroInfo; + std::shared_ptr morale; + std::shared_ptr luck; + + std::shared_ptr garr; void onArtChange(int tabIndex); - CIntObject * onTabSelected(size_t index); - void onTabDeselected(CIntObject *object); + std::shared_ptr onTabSelected(size_t index); public: - CArtifactsOfHero *heroArts; + std::shared_ptr heroArts; - CHeroItem(const CGHeroInstance* hero); + void updateGarrisons() override; + + CHeroItem(const CGHeroInstance * hero); }; /// Tab with all hero-specific data class CKingdHeroList : public CIntObject, public CGarrisonHolder, public CWindowWithArtifacts { private: - std::vector heroItems; - CListBox * heroes; - CPicture * title; - CLabel * heroLabel; - CLabel * skillsLabel; + std::shared_ptr heroes; + std::shared_ptr title; + std::shared_ptr heroLabel; + std::shared_ptr skillsLabel; - CIntObject* createHeroItem(size_t index); - void destroyHeroItem(CIntObject *item); + std::shared_ptr createHeroItem(size_t index); public: CKingdHeroList(size_t maxSize); @@ -330,17 +336,16 @@ public: class CKingdTownList : public CIntObject, public CGarrisonHolder { private: - std::vector townItems; - CListBox * towns; - CPicture * title; - CLabel * townLabel; - CLabel * garrHeroLabel; - CLabel * visitHeroLabel; + std::shared_ptr towns; + std::shared_ptr title; + std::shared_ptr townLabel; + std::shared_ptr garrHeroLabel; + std::shared_ptr visitHeroLabel; - CIntObject* createTownItem(size_t index); + std::shared_ptr createTownItem(size_t index); public: CKingdTownList(size_t maxSize); - void townChanged(const CGTownInstance *town); + void townChanged(const CGTownInstance * town); void updateGarrisons() override; }; diff --git a/client/windows/CQuestLog.cpp b/client/windows/CQuestLog.cpp index 9bcef154d..3218a2b05 100644 --- a/client/windows/CQuestLog.cpp +++ b/client/windows/CQuestLog.cpp @@ -62,15 +62,15 @@ void CQuestIcon::showAll(SDL_Surface * to) CAnimImage::showAll(to); } -CQuestMinimap::CQuestMinimap (const Rect & position) : -CMinimap (position), - currentQuest (nullptr) +CQuestMinimap::CQuestMinimap(const Rect & position) + : CMinimap(position), + currentQuest(nullptr) { } void CQuestMinimap::addQuestMarks (const QuestInfo * q) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); icons.clear(); int3 tile; @@ -96,13 +96,13 @@ void CQuestMinimap::addQuestMarks (const QuestInfo * q) void CQuestMinimap::update() { CMinimap::update(); - if (currentQuest) - addQuestMarks (currentQuest); + if(currentQuest) + addQuestMarks(currentQuest); } void CQuestMinimap::iconClicked() { - if (currentQuest->obj) + if(currentQuest->obj) adventureInt->centerOn (currentQuest->obj->pos); //moveAdvMapSelection(); } @@ -110,44 +110,38 @@ void CQuestMinimap::iconClicked() void CQuestMinimap::showAll(SDL_Surface * to) { CIntObject::showAll(to); // blitting IntObject directly to hide radar - for (auto pic : icons) - pic->showAll(to); +// for (auto pic : icons) +// pic->showAll(to); } -CQuestLog::CQuestLog (const std::vector & Quests) : - CWindowObject(PLAYER_COLORED | BORDERED, "questDialog"), +CQuestLog::CQuestLog (const std::vector & Quests) + : CWindowObject(PLAYER_COLORED | BORDERED, "questDialog"), questIndex(0), currentQuest(nullptr), - componentsBox(nullptr), hideComplete(false), - quests(Quests), - slider(nullptr) + quests(Quests) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - init(); -} + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); -void CQuestLog::init() -{ const JsonNode & texts = CGI->generaltexth->localizedTexts["questLog"]; - minimap = new CQuestMinimap (Rect (12, 12, 169, 169)); + minimap = std::make_shared(Rect(12, 12, 169, 169)); // TextBox have it's own 4 pixel padding from top at least for English. To achieve 10px from both left and top only add 6px margin - description = new CTextBox ("", Rect(205, 18, 385, DESCRIPTION_HEIGHT_MAX), CSlider::BROWN, FONT_MEDIUM, TOPLEFT, Colors::WHITE); - ok = new CButton(Point(539, 398), "IOKAY.DEF", CGI->generaltexth->zelp[445], std::bind(&CQuestLog::close,this), SDLK_RETURN); + description = std::make_shared("", Rect(205, 18, 385, DESCRIPTION_HEIGHT_MAX), CSlider::BROWN, FONT_MEDIUM, TOPLEFT, Colors::WHITE); + ok = std::make_shared(Point(539, 398), "IOKAY.DEF", CGI->generaltexth->zelp[445], std::bind(&CQuestLog::close, this), SDLK_RETURN); // Both button and lable are shifted to -2px by x and y to not make them actually look like they're on same line with quests list and ok button - hideCompleteButton = new CToggleButton(Point(10, 396), "sysopchk.def", CButton::tooltip(texts["hideComplete"]), std::bind(&CQuestLog::toggleComplete, this, _1)); - hideCompleteLabel = new CLabel(46, 398, FONT_MEDIUM, TOPLEFT, Colors::WHITE, texts["hideComplete"]["label"].String()); - slider = new CSlider(Point(166, 195), 191, std::bind(&CQuestLog::sliderMoved, this, _1), QUEST_COUNT, 0, false, CSlider::BROWN); + hideCompleteButton = std::make_shared(Point(10, 396), "sysopchk.def", CButton::tooltip(texts["hideComplete"]), std::bind(&CQuestLog::toggleComplete, this, _1)); + hideCompleteLabel = std::make_shared(46, 398, FONT_MEDIUM, TOPLEFT, Colors::WHITE, texts["hideComplete"]["label"].String()); + slider = std::make_shared(Point(166, 195), 191, std::bind(&CQuestLog::sliderMoved, this, _1), QUEST_COUNT, 0, false, CSlider::BROWN); recreateLabelList(); - recreateQuestList (0); + recreateQuestList(0); } void CQuestLog::recreateLabelList() { - if (labels.size()) - labels.clear(); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + labels.clear(); bool completeMissing = true; int currentLabel = 0; @@ -209,8 +203,8 @@ void CQuestLog::recreateLabelList() void CQuestLog::showAll(SDL_Surface * to) { - CWindowObject::showAll (to); - if (labels.size() && labels[questIndex]->active) + CWindowObject::showAll(to); + if(labels.size() && labels[questIndex]->active) { Rect rect = Rect::around(labels[questIndex]->pos); rect.x -= 2; // Adjustment needed as we want selection box on top of border in graphics @@ -232,7 +226,7 @@ void CQuestLog::recreateQuestList (int newpos) minimap->update(); } -void CQuestLog::selectQuest (int which, int labelId) +void CQuestLog::selectQuest(int which, int labelId) { questIndex = labelId; currentQuest = &quests[which]; @@ -241,14 +235,15 @@ void CQuestLog::selectQuest (int which, int labelId) MetaString text; std::vector components; currentQuest->quest->getVisitText (text, components, currentQuest->quest->isCustomFirst, true); - if (description->slider) + if(description->slider) description->slider->moveToMin(); // scroll text to start position - description->setText (text.toString()); //TODO: use special log entry text + description->setText(text.toString()); //TODO: use special log entry text + + componentsBox.reset(); - vstd::clear_pointer(componentsBox); int componentsSize = components.size(); int descriptionHeight = DESCRIPTION_HEIGHT_MAX; - if (componentsSize) + if(componentsSize) { descriptionHeight -= 15; CComponent::ESize imageSize = CComponent::large; @@ -290,12 +285,16 @@ void CQuestLog::selectQuest (int which, int labelId) break; } - OBJ_CONSTRUCTION_CAPTURING_ALL; - std::vector comps; - for (auto & component : components) - comps.push_back(new CComponent(component, imageSize)); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); - componentsBox = new CComponentBox(comps, Rect(202, 20+descriptionHeight+15, 391, DESCRIPTION_HEIGHT_MAX-(20+descriptionHeight))); + std::vector> comps; + for(auto & component : components) + { + auto c = std::make_shared(component, imageSize); + comps.push_back(c); + } + + componentsBox = std::make_shared(comps, Rect(202, 20+descriptionHeight+15, 391, DESCRIPTION_HEIGHT_MAX-(20+descriptionHeight))); } description->resize(Point(385, descriptionHeight)); @@ -303,15 +302,14 @@ void CQuestLog::selectQuest (int which, int labelId) redraw(); } -void CQuestLog::sliderMoved (int newpos) +void CQuestLog::sliderMoved(int newpos) { - recreateQuestList (newpos); //move components + recreateQuestList(newpos); //move components redraw(); } void CQuestLog::toggleComplete(bool on) { - OBJ_CONSTRUCTION_CAPTURING_ALL; hideComplete = on; recreateLabelList(); recreateQuestList(0); diff --git a/client/windows/CQuestLog.h b/client/windows/CQuestLog.h index 45e72b499..47a2dfa59 100644 --- a/client/windows/CQuestLog.h +++ b/client/windows/CQuestLog.h @@ -38,7 +38,7 @@ class CQuestLabel : public LRClickableAreaWText, public CMultiLineLabel public: std::function callback; - CQuestLabel (Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = "") + CQuestLabel(Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = "") : CMultiLineLabel (position, FONT_SMALL, TOPLEFT, Colors::WHITE, Text){}; void clickLeft(tribool down, bool previousState) override; void showAll(SDL_Surface * to) override; @@ -49,7 +49,7 @@ class CQuestIcon : public CAnimImage public: std::function callback; //TODO: merge with other similar classes? - CQuestIcon (const std::string &defname, int index, int x=0, int y=0); + CQuestIcon(const std::string &defname, int index, int x=0, int y=0); void clickLeft(tribool down, bool previousState) override; void showAll(SDL_Surface * to) override; @@ -57,17 +57,16 @@ public: class CQuestMinimap : public CMinimap { - std::vector > icons; + std::vector> icons; void clickLeft(tribool down, bool previousState) override{}; //minimap ignores clicking on its surface void iconClicked(); void mouseMoved (const SDL_MouseMotionEvent & sEvent) override{}; public: - const QuestInfo * currentQuest; - CQuestMinimap (const Rect & position); + CQuestMinimap(const Rect & position); //should be called to invalidate whole map - different player or level void update(); void addQuestMarks (const QuestInfo * q); @@ -79,22 +78,20 @@ class CQuestLog : public CWindowObject { int questIndex; const QuestInfo * currentQuest; - CComponentBox * componentsBox; + std::shared_ptr componentsBox; bool hideComplete; - CToggleButton * hideCompleteButton; - CLabel * hideCompleteLabel; + std::shared_ptr hideCompleteButton; + std::shared_ptr hideCompleteLabel; const std::vector quests; - std::vector > labels; - CTextBox * description; - CQuestMinimap * minimap; - CSlider * slider; //scrolls quests - CButton *ok; + std::vector> labels; + std::shared_ptr description; + std::shared_ptr minimap; + std::shared_ptr slider; //scrolls quests + std::shared_ptr ok; - void init (); public: - - CQuestLog (const std::vector & Quests); + CQuestLog(const std::vector & Quests); ~CQuestLog(){}; diff --git a/client/windows/CSpellWindow.cpp b/client/windows/CSpellWindow.cpp index e3fb85f6d..623dee304 100644 --- a/client/windows/CSpellWindow.cpp +++ b/client/windows/CSpellWindow.cpp @@ -102,7 +102,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m myHero(_myHero), myInt(_myInt) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); //initializing castable spells mySpells.reserve(CGI->spellh->objects.size()); for(const CSpell * spell : CGI->spellh->objects) @@ -168,13 +168,13 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m //numbers of spell pages computed - leftCorner = new CPicture("SpelTrnL.bmp", 97, 77); - rightCorner = new CPicture("SpelTrnR.bmp", 487, 72); + leftCorner = std::make_shared("SpelTrnL.bmp", 97, 77); + rightCorner = std::make_shared("SpelTrnR.bmp", 487, 72); - spells = std::make_shared("Spells"); + spellIcons = std::make_shared("Spells"); - spellTab = new CAnimImage("SpelTab", selectedTab, 0, 524, 88); - schools = new CAnimImage("Schools",0,0,117,74); + schoolTab = std::make_shared("SpelTab", selectedTab, 0, 524, 88); + schoolPicture = std::make_shared("Schools", 0, 0, 117, 74); schoolBorders[0] = std::make_shared("SplevA.def"); schoolBorders[1] = std::make_shared("SplevF.def"); @@ -182,34 +182,34 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m schoolBorders[3] = std::make_shared("SplevE.def"); for(auto item : schoolBorders) - item->load(); - mana = new CLabel(435, 426, FONT_SMALL, CENTER, Colors::YELLOW, boost::lexical_cast(myHero->mana)); - statusBar = new CGStatusBar(7, 569, "Spelroll.bmp"); + item->preload(); + mana = std::make_shared(435, 426, FONT_SMALL, CENTER, Colors::YELLOW, boost::lexical_cast(myHero->mana)); + statusBar = std::make_shared(7, 569, "Spelroll.bmp"); SDL_Rect temp_rect = genRect(45, 35, 479 + pos.x, 405 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fexitb, this), 460, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::fexitb, this), 460, this)); temp_rect = genRect(45, 35, 221 + pos.x, 405 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fbattleSpellsb, this), 453, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::fbattleSpellsb, this), 453, this)); temp_rect = genRect(45, 35, 355 + pos.x, 405 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fadvSpellsb, this), 452, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::fadvSpellsb, this), 452, this)); temp_rect = genRect(45, 35, 418 + pos.x, 405 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fmanaPtsb, this), 459, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::fmanaPtsb, this), 459, this)); temp_rect = genRect(36, 56, 549 + pos.x, 94 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 0), 454, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 0), 454, this)); temp_rect = genRect(36, 56, 549 + pos.x, 151 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 3), 457, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 3), 457, this)); temp_rect = genRect(36, 56, 549 + pos.x, 210 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 1), 455, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 1), 455, this)); temp_rect = genRect(36, 56, 549 + pos.x, 270 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 2), 456, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 2), 456, this)); temp_rect = genRect(36, 56, 549 + pos.x, 330 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 4), 458, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 4), 458, this)); temp_rect = genRect(leftCorner->bg->h, leftCorner->bg->w, 97 + pos.x, 77 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fLcornerb, this), 450, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::fLcornerb, this), 450, this)); temp_rect = genRect(rightCorner->bg->h, rightCorner->bg->w, 487 + pos.x, 72 + pos.y); - new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fRcornerb, this), 451, this); + interactiveAreas.push_back(std::make_shared(temp_rect, std::bind(&CSpellWindow::fRcornerb, this), 451, this)); //areas for spells int xpos = 117 + pos.x, ypos = 90 + pos.y; @@ -217,7 +217,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m for(int v=0; v<12; ++v) { temp_rect = genRect(65, 78, xpos, ypos); - spellAreas[v] = new SpellArea(temp_rect, this); + spellAreas[v] = std::make_shared(temp_rect, this); if(v == 5) //to right page { @@ -237,7 +237,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m } selectedTab = battleSpellsOnly ? myInt->spellbookSettings.spellbookLastTabBattle : myInt->spellbookSettings.spellbookLastTabAdvmap; - spellTab->setFrame(selectedTab, 0); + schoolTab->setFrame(selectedTab, 0); int cp = battleSpellsOnly ? myInt->spellbookSettings.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap; // spellbook last page battle index is not reset after battle, so this needs to stay here vstd::abetween(cp, 0, std::max(0, pagesWithinCurrentTab() - 1)); @@ -248,9 +248,6 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m CSpellWindow::~CSpellWindow() { - for(auto item : schoolBorders) - item->unload(); - spells->unload(); } void CSpellWindow::fexitb() @@ -263,7 +260,7 @@ void CSpellWindow::fexitb() void CSpellWindow::fadvSpellsb() { - if (battleSpellsOnly == true) + if(battleSpellsOnly == true) { turnPageRight(); battleSpellsOnly = false; @@ -274,7 +271,7 @@ void CSpellWindow::fadvSpellsb() void CSpellWindow::fbattleSpellsb() { - if (battleSpellsOnly == false) + if(battleSpellsOnly == false) { turnPageLeft(); battleSpellsOnly = true; @@ -289,14 +286,14 @@ void CSpellWindow::fmanaPtsb() void CSpellWindow::selectSchool(int school) { - if (selectedTab != school) + if(selectedTab != school) { - if (selectedTab < school) + if(selectedTab < school) turnPageLeft(); else turnPageRight(); selectedTab = school; - spellTab->setFrame(selectedTab, 0); + schoolTab->setFrame(selectedTab, 0); setCurrentPage(0); } computeSpellsPerArea(); @@ -405,9 +402,9 @@ void CSpellWindow::computeSpellsPerArea() void CSpellWindow::setCurrentPage(int value) { currentPage = value; - schools->visible = selectedTab!=4 && currentPage == 0; + schoolPicture->visible = selectedTab!=4 && currentPage == 0; if(selectedTab != 4) - schools->setFrame(selectedTab, 0); + schoolPicture->setFrame(selectedTab, 0); leftCorner->visible = currentPage != 0; rightCorner->visible = (currentPage+1) < pagesWithinCurrentTab(); @@ -416,13 +413,13 @@ void CSpellWindow::setCurrentPage(int value) void CSpellWindow::turnPageLeft() { - if (settings["video"]["spellbookAnimation"].Bool()) + if(settings["video"]["spellbookAnimation"].Bool()) CCS->videoh->openAndPlayVideo("PGTRNLFT.SMK", pos.x+13, pos.y+15, screen); } void CSpellWindow::turnPageRight() { - if (settings["video"]["spellbookAnimation"].Bool()) + if(settings["video"]["spellbookAnimation"].Bool()) CCS->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15, screen); } @@ -503,27 +500,23 @@ CSpellWindow::SpellArea::SpellArea(SDL_Rect pos, CSpellWindow * owner) this->owner = owner; addUsedEvents(LCLICK | RCLICK | HOVER); - spellCost = whichSchool = schoolLevel = -1; + schoolLevel = -1; mySpell = nullptr; - schoolBorder = nullptr; - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - image = new CAnimImage(owner->spells, 0, 0); + image = std::make_shared(owner->spellIcons, 0, 0); image->visible = false; - name = new CLabel(39, 70, FONT_TINY, CENTER); - level = new CLabel(39, 82, FONT_TINY, CENTER); - cost = new CLabel(39, 94, FONT_TINY, CENTER); + name = std::make_shared(39, 70, FONT_TINY, CENTER); + level = std::make_shared(39, 82, FONT_TINY, CENTER); + cost = std::make_shared(39, 94, FONT_TINY, CENTER); for(auto l : {name, level, cost}) l->autoRedraw = false; } -CSpellWindow::SpellArea::~SpellArea() -{ - -} +CSpellWindow::SpellArea::~SpellArea() = default; void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState) { @@ -551,7 +544,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState) //battle spell on adv map or adventure map spell during combat => display infowindow, not cast if((combatSpell ^ inCombat) || inCastle) { - std::vector hlp(1, new CComponent(CComponent::spell, mySpell->id, 0)); + std::vector> hlp(1, std::make_shared(CComponent::spell, mySpell->id, 0)); owner->myInt->showInfoDialog(mySpell->getLevelInfo(schoolLevel).description, hlp); } else if(combatSpell) @@ -607,8 +600,7 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState) boost::algorithm::replace_first(dmgInfo, "%d", boost::lexical_cast(causedDmg)); } - CRClickPopup::createAndPush(mySpell->getLevelInfo(schoolLevel).description + dmgInfo, - new CComponent(CComponent::spell, mySpell->id)); + CRClickPopup::createAndPush(mySpell->getLevelInfo(schoolLevel).description + dmgInfo, std::make_shared(CComponent::spell, mySpell->id)); } } @@ -623,20 +615,9 @@ void CSpellWindow::SpellArea::hover(bool on) } } -void CSpellWindow::SpellArea::showAll(SDL_Surface * to) -{ - if(mySpell) - { - //printing border (indicates level of magic school) - if(schoolBorder) - schoolBorder->draw(to, pos.x, pos.y); - CIntObject::showAll(to); - } -} - void CSpellWindow::SpellArea::setSpell(const CSpell * spell) { - schoolBorder = nullptr; + schoolBorder.reset(); image->visible = false; name->setText(""); level->setText(""); @@ -644,12 +625,17 @@ void CSpellWindow::SpellArea::setSpell(const CSpell * spell) mySpell = spell; if(mySpell) { + int whichSchool = 0; //0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, schoolLevel = owner->myHero->getSpellSchoolLevel(mySpell, &whichSchool); - spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero); + auto spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero); image->setFrame(mySpell->id); image->visible = true; - schoolBorder = owner->schoolBorders[owner->selectedTab >= 4 ? whichSchool : owner->selectedTab]->getImage(schoolLevel,0); + + { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + schoolBorder = std::make_shared(owner->schoolBorders[owner->selectedTab >= 4 ? whichSchool : owner->selectedTab], schoolLevel); + } SDL_Color firstLineColor, secondLineColor; if(spellCost > owner->myHero->mana) //hero cannot cast this spell diff --git a/client/windows/CSpellWindow.h b/client/windows/CSpellWindow.h index 273e0ea63..e77a60267 100644 --- a/client/windows/CSpellWindow.h +++ b/client/windows/CSpellWindow.h @@ -30,12 +30,12 @@ class CSpellWindow : public CWindowObject { const CSpell * mySpell; int schoolLevel; //range: 0 none, 3 - expert - int whichSchool; //0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, - int spellCost; CSpellWindow * owner; - CAnimImage * image; - IImage * schoolBorder; - CLabel * name, * level, * cost; + std::shared_ptr image; + std::shared_ptr schoolBorder; + std::shared_ptr name; + std::shared_ptr level; + std::shared_ptr cost; public: SpellArea(SDL_Rect pos, CSpellWindow * owner); ~SpellArea(); @@ -44,7 +44,6 @@ class CSpellWindow : public CWindowObject void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; void hover(bool on) override; - void showAll(SDL_Surface * to) override; }; class InteractiveArea : public CIntObject @@ -62,17 +61,20 @@ class CSpellWindow : public CWindowObject InteractiveArea(const SDL_Rect & myRect, std::function funcL, int helpTextId, CSpellWindow * _owner); }; - CPicture * leftCorner, * rightCorner; + std::shared_ptr spellIcons; + std::array, 4> schoolBorders; //[0]: air, [1]: fire, [2]: water, [3]: earth - std::shared_ptr spells; //pictures of spells + std::shared_ptr leftCorner; + std::shared_ptr rightCorner; - CAnimImage * spellTab; //school select - CAnimImage * schools; //schools' pictures - std::array< std::shared_ptr, 4> schoolBorders; //schools' 'borders': [0]: air, [1]: fire, [2]: water, [3]: earth + std::shared_ptr schoolTab; + std::shared_ptr schoolPicture; - SpellArea * spellAreas[12]; - CLabel * mana; - CGStatusBar * statusBar; + std::array, 12> spellAreas; + std::shared_ptr mana; + std::shared_ptr statusBar; + + std::vector> interactiveAreas; int sitesPerTabAdv[5]; int sitesPerTabBattle[5]; diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index 3b03998bc..35db8683f 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -31,34 +31,35 @@ #include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/CGMarket.h" -CTradeWindow::CTradeableItem::CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial): - CIntObject(LCLICK | HOVER | RCLICK, pos), +CTradeWindow::CTradeableItem::CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial) + : CIntObject(LCLICK | HOVER | RCLICK, pos), type(EType(-1)),// set to invalid, will be corrected in setType id(ID), serial(Serial), left(Left) { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); downSelection = false; hlp = nullptr; - image = nullptr; setType(Type); } void CTradeWindow::CTradeableItem::setType(EType newType) { - if (type != newType) + if(type != newType) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); type = newType; - delete image; - if (getIndex() < 0) + if(getIndex() < 0) { - image = new CAnimImage(getFilename(), 0); + image = std::make_shared(getFilename(), 0); image->disable(); } else - image = new CAnimImage(getFilename(), getIndex()); + { + image = std::make_shared(getFilename(), getIndex()); + } } } @@ -177,11 +178,11 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState) CAltarWindow *aw = static_cast(mw); if(const CArtifactInstance *movedArt = aw->arts->commonInfo->src.art) { - aw->moveFromSlotToAltar(aw->arts->commonInfo->src.slotID, this, movedArt); + aw->moveFromSlotToAltar(aw->arts->commonInfo->src.slotID, this->shared_from_this(), movedArt); } else if(const CArtifactInstance *art = getArtInstance()) { - aw->arts->commonInfo->src.AOH = aw->arts; + aw->arts->commonInfo->src.AOH = aw->arts.get(); aw->arts->commonInfo->src.art = art; aw->arts->commonInfo->src.slotID = aw->hero->getArtPos(art); aw->arts->markPossibleSlots(art); @@ -200,15 +201,15 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState) } if(left) { - if(mw->hLeft != this) - mw->hLeft = this; + if(mw->hLeft != this->shared_from_this()) + mw->hLeft = this->shared_from_this(); else return; } else { - if(mw->hRight != this) - mw->hRight = this; + if(mw->hRight != this->shared_from_this()) + mw->hRight = this->shared_from_this(); else return; } @@ -301,7 +302,7 @@ const CArtifactInstance * CTradeWindow::CTradeableItem::getArtInstance() const { case ARTIFACT_PLACEHOLDER: case ARTIFACT_INSTANCE: - return (const CArtifactInstance *)hlp; + return hlp; default: return nullptr; } @@ -321,15 +322,10 @@ CTradeWindow::CTradeWindow(std::string bgName, const IMarket *Market, const CGHe CWindowObject(PLAYER_COLORED, bgName), market(Market), hero(Hero), - arts(nullptr), - hLeft(nullptr), - hRight(nullptr), - ok(nullptr), - max(nullptr), - deal(nullptr), - slider(nullptr), readyToTrade(false) { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + type |= BLOCK_ADV_HOTKEYS; mode = Mode; initTypes(); @@ -372,6 +368,8 @@ void CTradeWindow::initTypes() void CTradeWindow::initItems(bool Left) { + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + if(Left && (itemsType[1] == ARTIFACT_TYPE || itemsType[1] == ARTIFACT_INSTANCE)) { int xOffset = 0, yOffset = 0; @@ -380,9 +378,9 @@ void CTradeWindow::initItems(bool Left) xOffset = -361; yOffset = +46; - auto hlp = new CTradeableItem(Point(137, 469), itemsType[Left], -1, 1, 0); - hlp->recActions &= ~(UPDATE | SHOWALL); - items[Left].push_back(hlp); + auto item = std::make_shared(Point(137, 469), itemsType[Left], -1, 1, 0); + item->recActions &= ~(UPDATE | SHOWALL); + items[Left].push_back(item); } else //ARTIFACT_EXP { @@ -390,47 +388,44 @@ void CTradeWindow::initItems(bool Left) yOffset = -12; } - BLOCK_CAPTURING; - arts = new CArtifactsOfHero(Point(pos.x+xOffset, pos.y+yOffset)); - arts->commonInfo = std::make_shared(); - arts->commonInfo->participants.insert(arts); - arts->recActions = 255; + arts = std::make_shared(Point(xOffset, yOffset), true); + arts->recActions = 255-DISPOSE; arts->setHero(hero); arts->allowedAssembling = false; - addChild(arts); - artSets.push_back(arts); + addSet(arts); if(mode == EMarketMode::ARTIFACT_RESOURCE) arts->highlightModeCallback = std::bind(&CTradeWindow::artifactSelected, this, _1); - return; } - - std::vector *ids = getItemsIds(Left); - std::vector pos; - int amount = -1; - - getPositionsFor(pos, Left, itemsType[Left]); - - if(Left || !ids) - amount = 7; else - amount = ids->size(); - - if(ids) - vstd::amin(amount, ids->size()); - - for(int j=0; jsize()>j) ? (*ids)[j] : j; - if(id < 0 && mode != EMarketMode::ARTIFACT_EXP) //when sacrificing artifacts we need to prepare empty slots - continue; + std::vector *ids = getItemsIds(Left); + std::vector pos; + int amount = -1; - auto hlp = new CTradeableItem(pos[j].topLeft(), itemsType[Left], id, Left, j); - hlp->pos = pos[j] + this->pos.topLeft(); - items[Left].push_back(hlp); + getPositionsFor(pos, Left, itemsType[Left]); + + if(Left || !ids) + amount = 7; + else + amount = ids->size(); + + if(ids) + vstd::amin(amount, ids->size()); + + for(int j=0; jsize()>j) ? (*ids)[j] : j; + if(id < 0 && mode != EMarketMode::ARTIFACT_EXP) //when sacrificing artifacts we need to prepare empty slots + continue; + + auto item = std::make_shared(pos[j].topLeft(), itemsType[Left], id, Left, j); + item->pos = pos[j] + this->pos.topLeft(); + items[Left].push_back(item); + } + vstd::clear_pointer(ids); + initSubs(Left); } - vstd::clear_pointer(ids); - initSubs(Left); } std::vector *CTradeWindow::getItemsIds(bool Left) @@ -523,17 +518,17 @@ void CTradeWindow::getPositionsFor(std::vector &poss, bool Left, EType typ void CTradeWindow::initSubs(bool Left) { - for(CTradeableItem *t : items[Left]) + for(auto item : items[Left]) { if(Left) { switch(itemsType[1]) { case CREATURE: - t->subtitle = boost::lexical_cast(hero->getStackCount(SlotID(t->serial))); + item->subtitle = boost::lexical_cast(hero->getStackCount(SlotID(item->serial))); break; case RESOURCE: - t->subtitle = boost::lexical_cast(LOCPLINT->cb->getResourceAmount(static_cast(t->serial))); + item->subtitle = boost::lexical_cast(LOCPLINT->cb->getResourceAmount(static_cast(item->serial))); break; } } @@ -541,25 +536,25 @@ void CTradeWindow::initSubs(bool Left) { if(itemsType[0] == PLAYER) { - t->subtitle = CGI->generaltexth->capColors[t->id]; + item->subtitle = CGI->generaltexth->capColors[item->id]; } else if(hLeft)//artifact, creature { int h1, h2; //hlp variables for getting offer - market->getOffer(hLeft->id, t->id, h1, h2, mode); - if(t->id != hLeft->id || mode != EMarketMode::RESOURCE_RESOURCE) //don't allow exchanging same resources + market->getOffer(hLeft->id, item->id, h1, h2, mode); + if(item->id != hLeft->id || mode != EMarketMode::RESOURCE_RESOURCE) //don't allow exchanging same resources { std::ostringstream oss; oss << h2; if(h1!=1) oss << "/" << h1; - t->subtitle = oss.str(); + item->subtitle = oss.str(); } else - t->subtitle = CGI->generaltexth->allTexts[164]; // n/a + item->subtitle = CGI->generaltexth->allTexts[164]; // n/a } else - t->subtitle = ""; + item->subtitle = ""; } } } @@ -569,9 +564,9 @@ void CTradeWindow::showAll(SDL_Surface * to) CWindowObject::showAll(to); if(hRight) - CSDL_Ext::drawBorder(to,hRight->pos.x-1,hRight->pos.y-1,hRight->pos.w+2,hRight->pos.h+2,int3(255,231,148)); + CSDL_Ext::drawBorder(to, hRight->pos.x-1, hRight->pos.y-1, hRight->pos.w+2, hRight->pos.h+2, int3(255,231,148)); if(hLeft && hLeft->type != ARTIFACT_INSTANCE) - CSDL_Ext::drawBorder(to,hLeft->pos.x-1,hLeft->pos.y-1,hLeft->pos.w+2,hLeft->pos.h+2,int3(255,231,148)); + CSDL_Ext::drawBorder(to, hLeft->pos.x-1, hLeft->pos.y-1, hLeft->pos.w+2, hLeft->pos.h+2, int3(255,231,148)); if(readyToTrade) { @@ -582,29 +577,28 @@ void CTradeWindow::showAll(SDL_Surface * to) } } -void CTradeWindow::removeItems(const std::set &toRemove) +void CTradeWindow::removeItems(const std::set> & toRemove) { - for(CTradeableItem *t : toRemove) - removeItem(t); + for(auto item : toRemove) + removeItem(item); } -void CTradeWindow::removeItem(CTradeableItem * t) +void CTradeWindow::removeItem(std::shared_ptr item) { - items[t->left] -= t; - delete t; + items[item->left] -= item; - if(hRight == t) + if(hRight == item) { - hRight = nullptr; + hRight.reset(); selectionChanged(false); } } -void CTradeWindow::getEmptySlots(std::set &toRemove) +void CTradeWindow::getEmptySlots(std::set> & toRemove) { - for(CTradeableItem *t : items[1]) - if(!hero->getStackCount(SlotID(t->serial))) - toRemove.insert(t); + for(auto item : items[1]) + if(!hero->getStackCount(SlotID(item->serial))) + toRemove.insert(item); } void CTradeWindow::setMode(EMarketMode::EMarketMode Mode) @@ -660,35 +654,36 @@ std::string CMarketplaceWindow::getBackgroundForMode(EMarketMode::EMarketMode mo return ""; } -CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstance *Hero, EMarketMode::EMarketMode Mode) +CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode::EMarketMode Mode) : CTradeWindow(getBackgroundForMode(Mode), Market, Hero, Mode) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); madeTransaction = false; bool sliderNeeded = true; - new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + statusBar = std::make_shared(std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); std::string title; - if (market->o->ID == Obj::TOWN) + if(market->o->ID == Obj::TOWN) { switch (mode) { - break; case EMarketMode::CREATURE_RESOURCE: + case EMarketMode::CREATURE_RESOURCE: title = CGI->townh->factions[ETownType::STRONGHOLD]->town->buildings[BuildingID::FREELANCERS_GUILD]->Name(); - - break; case EMarketMode::RESOURCE_ARTIFACT: + break; + case EMarketMode::RESOURCE_ARTIFACT: title = CGI->townh->factions[market->o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->Name(); sliderNeeded = false; - - break; case EMarketMode::ARTIFACT_RESOURCE: + break; + case EMarketMode::ARTIFACT_RESOURCE: title = CGI->townh->factions[market->o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->Name(); sliderNeeded = false; - - break; default: + break; + default: title = CGI->generaltexth->allTexts[158]; + break; } } else @@ -707,55 +702,51 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan break; default: title = market->o->getObjectName(); + break; } } - new CLabel(300, 27, FONT_BIG, CENTER, Colors::YELLOW, title); + titleLabel = std::make_shared(300, 27, FONT_BIG, CENTER, Colors::YELLOW, title); initItems(false); initItems(true); - ok = new CButton(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[600], [&](){ close(); }, SDLK_RETURN); + ok = std::make_shared(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[600], [&](){ close(); }, SDLK_RETURN); ok->assignedKeys.insert(SDLK_ESCAPE); - deal = new CButton(Point(307, 520), "TPMRKB.DEF", CGI->generaltexth->zelp[595], [&](){ makeDeal(); } ); + deal = std::make_shared(Point(307, 520), "TPMRKB.DEF", CGI->generaltexth->zelp[595], [&](){ makeDeal(); } ); deal->block(true); if(sliderNeeded) { - slider = new CSlider(Point(231, 490),137, std::bind(&CMarketplaceWindow::sliderMoved,this,_1),0,0); - max = new CButton(Point(229, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[596], [&](){ setMax(); }); + slider = std::make_shared(Point(231, 490),137, std::bind(&CMarketplaceWindow::sliderMoved,this,_1),0,0); + max = std::make_shared(Point(229, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[596], [&](){ setMax(); }); max->block(true); } else { - slider = nullptr; - max = nullptr; deal->moveBy(Point(-30, 0)); } - Rect traderTextRect; - //left side switch(Mode) { case EMarketMode::RESOURCE_RESOURCE: case EMarketMode::RESOURCE_PLAYER: case EMarketMode::RESOURCE_ARTIFACT: - new CLabel(154, 148, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[270]); + labels.push_back(std::make_shared(154, 148, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[270])); break; - case EMarketMode::CREATURE_RESOURCE: //%s's Creatures - new CLabel(152, 102, FONT_SMALL, CENTER, Colors::WHITE, - boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->name)); + labels.push_back(std::make_shared(152, 102, FONT_SMALL, CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->name))); break; case EMarketMode::ARTIFACT_RESOURCE: //%s's Artifacts - new CLabel(152, 56, FONT_SMALL, CENTER, Colors::WHITE, - boost::str(boost::format(CGI->generaltexth->allTexts[271]) % hero->name)); + labels.push_back(std::make_shared(152, 56, FONT_SMALL, CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->allTexts[271]) % hero->name))); break; } + Rect traderTextRect; + //right side switch(Mode) { @@ -763,45 +754,33 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan case EMarketMode::CREATURE_RESOURCE: case EMarketMode::RESOURCE_ARTIFACT: case EMarketMode::ARTIFACT_RESOURCE: - new CLabel(445, 148, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[168]); + labels.push_back(std::make_shared(445, 148, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[168])); traderTextRect = Rect(316, 48, 260, 75); break; case EMarketMode::RESOURCE_PLAYER: - new CLabel(445, 55, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[169]); + labels.push_back(std::make_shared(445, 55, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[169])); traderTextRect = Rect(28, 48, 260, 75); break; } - traderText = new CTextBox("", traderTextRect, 0, FONT_SMALL, CENTER); + traderText = std::make_shared("", traderTextRect, 0, FONT_SMALL, CENTER); int specialOffset = mode == EMarketMode::ARTIFACT_RESOURCE ? 35 : 0; //in selling artifacts mode we need to move res-res and art-res buttons down if(printButtonFor(EMarketMode::RESOURCE_PLAYER)) - new CButton(Point(18, 520),"TPMRKBU1.DEF", CGI->generaltexth->zelp[612], [&](){ setMode(EMarketMode::RESOURCE_PLAYER);}); + buttons.push_back(std::make_shared(Point(18, 520),"TPMRKBU1.DEF", CGI->generaltexth->zelp[612], [&](){ setMode(EMarketMode::RESOURCE_PLAYER);})); if(printButtonFor(EMarketMode::RESOURCE_RESOURCE)) - new CButton(Point(516, 450 + specialOffset),"TPMRKBU5.DEF", CGI->generaltexth->zelp[605], [&](){ setMode(EMarketMode::RESOURCE_RESOURCE);}); + buttons.push_back(std::make_shared(Point(516, 450 + specialOffset),"TPMRKBU5.DEF", CGI->generaltexth->zelp[605], [&](){ setMode(EMarketMode::RESOURCE_RESOURCE);})); if(printButtonFor(EMarketMode::CREATURE_RESOURCE)) - new CButton(Point(516, 485),"TPMRKBU4.DEF", CGI->generaltexth->zelp[599], [&](){ setMode(EMarketMode::CREATURE_RESOURCE);}); + buttons.push_back(std::make_shared(Point(516, 485),"TPMRKBU4.DEF", CGI->generaltexth->zelp[599], [&](){ setMode(EMarketMode::CREATURE_RESOURCE);})); if(printButtonFor(EMarketMode::RESOURCE_ARTIFACT)) - new CButton(Point(18, 450 + specialOffset),"TPMRKBU2.DEF", CGI->generaltexth->zelp[598], [&](){ setMode(EMarketMode::RESOURCE_ARTIFACT);}); + buttons.push_back(std::make_shared(Point(18, 450 + specialOffset),"TPMRKBU2.DEF", CGI->generaltexth->zelp[598], [&](){ setMode(EMarketMode::RESOURCE_ARTIFACT);})); if(printButtonFor(EMarketMode::ARTIFACT_RESOURCE)) - new CButton(Point(18, 485),"TPMRKBU3.DEF", CGI->generaltexth->zelp[613], [&](){ setMode(EMarketMode::ARTIFACT_RESOURCE);}); + buttons.push_back(std::make_shared(Point(18, 485),"TPMRKBU3.DEF", CGI->generaltexth->zelp[613], [&](){ setMode(EMarketMode::ARTIFACT_RESOURCE);})); updateTraderText(); } -CMarketplaceWindow::~CMarketplaceWindow() -{ - hLeft = hRight = nullptr; - for(auto & elem : items[1]) - delete elem; - for(auto & elem : items[0]) - delete elem; - - items[1].clear(); - items[0].clear(); -} - - +CMarketplaceWindow::~CMarketplaceWindow() = default; void CMarketplaceWindow::setMax() { @@ -918,10 +897,8 @@ void CMarketplaceWindow::garrisonChanged() if(mode != EMarketMode::CREATURE_RESOURCE) return; - std::set toRemove; + std::set> toRemove; getEmptySlots(toRemove); - - removeItems(toRemove); initSubs(true); } @@ -933,10 +910,10 @@ void CMarketplaceWindow::artifactsChanged(bool Left) return; std::vector available = market->availableItemsIds(mode); - std::set toRemove; - for(CTradeableItem *t : items[0]) - if(!vstd::contains(available, t->id)) - toRemove.insert(t); + std::set> toRemove; + for(auto item : items[0]) + if(!vstd::contains(available, item->id)) + toRemove.insert(item); removeItems(toRemove); redraw(); @@ -1113,93 +1090,88 @@ void CMarketplaceWindow::updateTraderText() } CAltarWindow::CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode::EMarketMode Mode) - :CTradeWindow((Mode == EMarketMode::CREATURE_EXP ? "ALTARMON.bmp" : "ALTRART2.bmp"), Market, Hero, Mode) + : CTradeWindow((Mode == EMarketMode::CREATURE_EXP ? "ALTARMON.bmp" : "ALTRART2.bmp"), Market, Hero, Mode) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + if(Mode == EMarketMode::CREATURE_EXP) { //%s's Creatures - new CLabel(155, 30, FONT_SMALL, CENTER, Colors::YELLOW, - boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->name)); + labels.push_back(std::make_shared(155, 30, FONT_SMALL, CENTER, Colors::YELLOW, + boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->name))); //Altar of Sacrifice - new CLabel(450, 30, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[479]); + labels.push_back(std::make_shared(450, 30, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[479])); //To sacrifice creatures, move them from your army on to the Altar and click Sacrifice new CTextBox(CGI->generaltexth->allTexts[480], Rect(320, 56, 256, 40), 0, FONT_SMALL, CENTER, Colors::YELLOW); - slider = new CSlider(Point(231,481),137,std::bind(&CAltarWindow::sliderMoved,this,_1),0,0); - max = new CButton(Point(147, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[578], std::bind(&CSlider::moveToMax, slider)); + slider = std::make_shared(Point(231,481),137,std::bind(&CAltarWindow::sliderMoved,this,_1),0,0); + max = std::make_shared(Point(147, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[578], std::bind(&CSlider::moveToMax, slider)); sacrificedUnits.resize(GameConstants::ARMY_SIZE, 0); - sacrificeAll = new CButton(Point(393, 520), "ALTARMY.DEF", CGI->generaltexth->zelp[579], std::bind(&CAltarWindow::SacrificeAll,this)); - sacrificeBackpack = nullptr; + sacrificeAll = std::make_shared(Point(393, 520), "ALTARMY.DEF", CGI->generaltexth->zelp[579], std::bind(&CAltarWindow::SacrificeAll,this)); initItems(true); mimicCres(); - artIcon = nullptr; } else { //Sacrifice artifacts for experience - new CLabel(450, 34, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477]); + labels.push_back(std::make_shared(450, 34, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477])); //%s's Creatures - new CLabel(302, 423, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[478]); + labels.push_back(std::make_shared(302, 423, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[478])); - sacrificeAll = new CButton(Point(393, 520), "ALTFILL.DEF", CGI->generaltexth->zelp[571], std::bind(&CAltarWindow::SacrificeAll,this)); + sacrificeAll = std::make_shared(Point(393, 520), "ALTFILL.DEF", CGI->generaltexth->zelp[571], std::bind(&CAltarWindow::SacrificeAll,this)); sacrificeAll->block(hero->artifactsInBackpack.empty() && hero->artifactsWorn.empty()); - sacrificeBackpack = new CButton(Point(147, 520), "ALTEMBK.DEF", CGI->generaltexth->zelp[570], std::bind(&CAltarWindow::SacrificeBackpack,this)); + sacrificeBackpack = std::make_shared(Point(147, 520), "ALTEMBK.DEF", CGI->generaltexth->zelp[570], std::bind(&CAltarWindow::SacrificeBackpack,this)); sacrificeBackpack->block(hero->artifactsInBackpack.empty()); - slider = nullptr; - max = nullptr; - initItems(true); initItems(false); - artIcon = new CAnimImage("ARTIFACT", 0, 0, 281, 442); + artIcon = std::make_shared("ARTIFACT", 0, 0, 281, 442); artIcon->disable(); } //Experience needed to reach next level - new CTextBox(CGI->generaltexth->allTexts[475], Rect(15, 415, 125, 50), 0, FONT_SMALL, CENTER, Colors::YELLOW); + texts.push_back(std::make_shared(CGI->generaltexth->allTexts[475], Rect(15, 415, 125, 50), 0, FONT_SMALL, CENTER, Colors::YELLOW)); //Total experience on the Altar - new CTextBox(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, CENTER, Colors::YELLOW); + texts.push_back(std::make_shared(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, CENTER, Colors::YELLOW)); - new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + statusBar = std::make_shared(std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); - ok = new CButton(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[568], [&](){ close();}, SDLK_RETURN); + ok = std::make_shared(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[568], [&](){ close();}, SDLK_RETURN); ok->assignedKeys.insert(SDLK_ESCAPE); - deal = new CButton(Point(269, 520), "ALTSACR.DEF", CGI->generaltexth->zelp[585], std::bind(&CAltarWindow::makeDeal,this)); + deal = std::make_shared(Point(269, 520), "ALTSACR.DEF", CGI->generaltexth->zelp[585], std::bind(&CAltarWindow::makeDeal,this)); if(Mode == EMarketMode::CREATURE_EXP) { - CButton *changeMode = new CButton(Point(516, 421), "ALTART.DEF", CGI->generaltexth->zelp[580], std::bind(&CTradeWindow::setMode,this, EMarketMode::ARTIFACT_EXP)); - if (Hero->getAlignment() == ::EAlignment::EVIL) + auto changeMode = std::make_shared(Point(516, 421), "ALTART.DEF", CGI->generaltexth->zelp[580], std::bind(&CTradeWindow::setMode,this, EMarketMode::ARTIFACT_EXP)); + if(Hero->getAlignment() == ::EAlignment::EVIL) changeMode->block(true); + buttons.push_back(changeMode); } - if(Mode == EMarketMode::ARTIFACT_EXP) + else if(Mode == EMarketMode::ARTIFACT_EXP) { - CButton *changeMode = new CButton(Point(516, 421), "ALTSACC.DEF", CGI->generaltexth->zelp[572], std::bind(&CTradeWindow::setMode,this, EMarketMode::CREATURE_EXP)); - if (Hero->getAlignment() == ::EAlignment::GOOD) + auto changeMode = std::make_shared(Point(516, 421), "ALTSACC.DEF", CGI->generaltexth->zelp[572], std::bind(&CTradeWindow::setMode,this, EMarketMode::CREATURE_EXP)); + if(Hero->getAlignment() == ::EAlignment::GOOD) changeMode->block(true); + buttons.push_back(changeMode); } expPerUnit.resize(GameConstants::ARMY_SIZE, 0); getExpValues(); - expToLevel = new CLabel(73, 475, FONT_SMALL, CENTER); - expOnAltar = new CLabel(73, 543, FONT_SMALL, CENTER); + expToLevel = std::make_shared(73, 475, FONT_SMALL, CENTER); + expOnAltar = std::make_shared(73, 543, FONT_SMALL, CENTER); setExpToLevel(); calcTotalExp(); blockTrade(); } -CAltarWindow::~CAltarWindow() -{ - -} +CAltarWindow::~CAltarWindow() = default; void CAltarWindow::getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const { @@ -1248,10 +1220,10 @@ void CAltarWindow::makeDeal() for(int& val : sacrificedUnits) val = 0; - for(CTradeableItem *t : items[0]) + for(auto item : items[0]) { - t->setType(CREATURE_PLACEHOLDER); - t->subtitle = ""; + item->setType(CREATURE_PLACEHOLDER); + item->subtitle = ""; } } else @@ -1265,10 +1237,10 @@ void CAltarWindow::makeDeal() LOCPLINT->cb->trade(market->o, mode, positions, {}, {}, hero); arts->artifactsOnAltar.clear(); - for(CTradeableItem *t : items[0]) + for(auto item : items[0]) { - t->setID(-1); - t->subtitle = ""; + item->setID(-1); + item->subtitle = ""; } arts->commonInfo->reset(); @@ -1284,15 +1256,15 @@ void CAltarWindow::SacrificeAll() if(mode == EMarketMode::CREATURE_EXP) { bool movedAnything = false; - for(CTradeableItem *t : items[1]) - sacrificedUnits[t->serial] = hero->getStackCount(SlotID(t->serial)); + for(auto item : items[1]) + sacrificedUnits[item->serial] = hero->getStackCount(SlotID(item->serial)); sacrificedUnits[items[1].front()->serial]--; - for(CTradeableItem *t : items[0]) + for(auto item : items[0]) { - updateRight(t); - if(t->type == CREATURE) + updateRight(item); + if(item->type == CREATURE) movedAnything = true; } @@ -1350,13 +1322,14 @@ void CAltarWindow::selectOppositeItem(bool side) void CAltarWindow::mimicCres() { + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); std::vector positions; getPositionsFor(positions, false, CREATURE); - for(CTradeableItem *t : items[1]) + for(auto item : items[1]) { - auto hlp = new CTradeableItem(positions[t->serial].topLeft(), CREATURE_PLACEHOLDER, t->id, false, t->serial); - hlp->pos = positions[t->serial] + this->pos.topLeft(); + auto hlp = std::make_shared(positions[item->serial].topLeft(), CREATURE_PLACEHOLDER, item->id, false, item->serial); + hlp->pos = positions[item->serial] + this->pos.topLeft(); items[0].push_back(hlp); } } @@ -1389,7 +1362,7 @@ void CAltarWindow::garrisonChanged() if(mode != EMarketMode::CREATURE_EXP) return; - std::set empty; + std::set> empty; getEmptySlots(empty); removeItems(empty); @@ -1401,9 +1374,11 @@ void CAltarWindow::garrisonChanged() void CAltarWindow::getExpValues() { int dump; - for(CTradeableItem *t : items[1]) - if(t->id >= 0) - market->getOffer(t->id, 0, dump, expPerUnit[t->serial], EMarketMode::CREATURE_EXP); + for(auto item : items[1]) + { + if(item->id >= 0) + market->getOffer(item->id, 0, dump, expPerUnit[item->serial], EMarketMode::CREATURE_EXP); + } } void CAltarWindow::calcTotalExp() @@ -1446,7 +1421,7 @@ void CAltarWindow::blockTrade() deal->block(true); } -void CAltarWindow::updateRight(CTradeableItem *toUpdate) +void CAltarWindow::updateRight(std::shared_ptr toUpdate) { int val = sacrificedUnits[toUpdate->serial]; toUpdate->setType(val ? CREATURE : CREATURE_PLACEHOLDER); @@ -1500,7 +1475,7 @@ void CAltarWindow::showAll(SDL_Surface * to) } } -bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, const CArtifactInstance *art) +bool CAltarWindow::putOnAltar(std::shared_ptr altarSlot, const CArtifactInstance *art) { if(!art->artType->isTradable()) //special art { @@ -1531,13 +1506,13 @@ bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, const CArtifactInstance return true; } -void CAltarWindow::moveFromSlotToAltar(ArtifactPosition slotID, CTradeableItem* altarSlot, const CArtifactInstance *art) +void CAltarWindow::moveFromSlotToAltar(ArtifactPosition slotID, std::shared_ptr altarSlot, const CArtifactInstance *art) { auto freeBackpackSlot = ArtifactPosition(hero->artifactsInBackpack.size() + GameConstants::BACKPACK_START); if(arts->commonInfo->src.art) { arts->commonInfo->dst.slotID = freeBackpackSlot; - arts->commonInfo->dst.AOH = arts; + arts->commonInfo->dst.AOH = arts.get(); } if(putOnAltar(altarSlot, art)) diff --git a/client/windows/CTradeWindow.h b/client/windows/CTradeWindow.h index 6bbb7c910..fd7049d69 100644 --- a/client/windows/CTradeWindow.h +++ b/client/windows/CTradeWindow.h @@ -16,6 +16,7 @@ class IMarket; class CSlider; class CTextBox; +class CGStatusBar; class CTradeWindow : public CWindowObject, public CWindowWithArtifacts //base for markets and altar of sacrifice { @@ -24,14 +25,14 @@ public: { RESOURCE, PLAYER, ARTIFACT_TYPE, CREATURE, CREATURE_PLACEHOLDER, ARTIFACT_PLACEHOLDER, ARTIFACT_INSTANCE }; - class CTradeableItem : public CIntObject - { - CAnimImage * image; + class CTradeableItem : public CIntObject, public std::enable_shared_from_this + { + std::shared_ptr image; std::string getFilename(); int getIndex(); public: - const CArtifactInstance *hlp; //holds ptr to artifact instance id type artifact + const CArtifactInstance * hlp; //holds ptr to artifact instance id type artifact EType type; int id; const int serial; @@ -41,37 +42,43 @@ public: void setType(EType newType); void setID(int newID); - const CArtifactInstance *getArtInstance() const; - void setArtInstance(const CArtifactInstance *art); + const CArtifactInstance * getArtInstance() const; + void setArtInstance(const CArtifactInstance * art); CFunctionList callback; bool downSelection; - void showAllAt(const Point &dstPos, const std::string &customSub, SDL_Surface * to); + void showAllAt(const Point & dstPos, const std::string & customSub, SDL_Surface * to); void clickRight(tribool down, bool previousState) override; - void hover (bool on) override; + void hover(bool on) override; void showAll(SDL_Surface * to) override; void clickLeft(tribool down, bool previousState) override; std::string getName(int number = -1) const; CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial); }; - const IMarket *market; - const CGHeroInstance *hero; + const IMarket * market; + const CGHeroInstance * hero; - CArtifactsOfHero *arts; + std::shared_ptr arts; //all indexes: 1 = left, 0 = right - std::vector items[2]; - CTradeableItem *hLeft, *hRight; //highlighted items (nullptr if no highlight) + std::array>, 2> items; + + //highlighted items (nullptr if no highlight) + std::shared_ptr hLeft; + std::shared_ptr hRight; EType itemsType[2]; - EMarketMode::EMarketMode mode;//0 - res<->res; 1 - res<->plauer; 2 - buy artifact; 3 - sell artifact - CButton *ok, *max, *deal; - CSlider *slider; //for choosing amount to be exchanged + EMarketMode::EMarketMode mode; + std::shared_ptr ok; + std::shared_ptr max; + std::shared_ptr deal; + + std::shared_ptr slider; //for choosing amount to be exchanged bool readyToTrade; - CTradeWindow(std::string bgName, const IMarket *Market, const CGHeroInstance *Hero, EMarketMode::EMarketMode Mode); //c + CTradeWindow(std::string bgName, const IMarket * Market, const CGHeroInstance * Hero, EMarketMode::EMarketMode Mode); //c void showAll(SDL_Surface * to) override; @@ -80,9 +87,9 @@ public: void initItems(bool Left); std::vector *getItemsIds(bool Left); //nullptr if default void getPositionsFor(std::vector &poss, bool Left, EType type) const; - void removeItems(const std::set &toRemove); - void removeItem(CTradeableItem * t); - void getEmptySlots(std::set &toRemove); + void removeItems(const std::set> & toRemove); + void removeItem(std::shared_ptr item); + void getEmptySlots(std::set> & toRemove); void setMode(EMarketMode::EMarketMode Mode); //mode setter void artifactSelected(CHeroArtPlace *slot); //used when selling artifacts -> called when user clicked on artifact slot @@ -93,29 +100,35 @@ public: virtual std::string selectionSubtitle(bool Left) const = 0; virtual void garrisonChanged() = 0; virtual void artifactsChanged(bool left) = 0; +protected: + std::shared_ptr statusBar; + std::vector> labels; + std::vector> buttons; + std::vector> texts; }; class CMarketplaceWindow : public CTradeWindow { + std::shared_ptr titleLabel; + bool printButtonFor(EMarketMode::EMarketMode M) const; std::string getBackgroundForMode(EMarketMode::EMarketMode mode); public: int r1, r2; //suggested amounts of traded resources bool madeTransaction; //if player made at least one transaction - CTextBox *traderText; + std::shared_ptr traderText; void setMax(); void sliderMoved(int to); void makeDeal(); void selectionChanged(bool side) override; //true == left - CMarketplaceWindow(const IMarket *Market, const CGHeroInstance *Hero = nullptr, EMarketMode::EMarketMode Mode = EMarketMode::RESOURCE_RESOURCE); + CMarketplaceWindow(const IMarket * Market, const CGHeroInstance * Hero = nullptr, EMarketMode::EMarketMode Mode = EMarketMode::RESOURCE_RESOURCE); ~CMarketplaceWindow(); Point selectionOffset(bool Left) const override; std::string selectionSubtitle(bool Left) const override; - void garrisonChanged() override; //removes creatures with count 0 from the list (apparently whole stack has been sold) void artifactsChanged(bool left) override; void resourceChanged(); @@ -126,19 +139,20 @@ public: class CAltarWindow : public CTradeWindow { - CAnimImage * artIcon; + std::shared_ptr artIcon; public: - CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero, EMarketMode::EMarketMode Mode); + std::vector sacrificedUnits; //[slot_nr] -> how many creatures from that slot will be sacrificed + std::vector expPerUnit; - void getExpValues(); + std::shared_ptr sacrificeAll; + std::shared_ptr sacrificeBackpack; + std::shared_ptr expToLevel; + std::shared_ptr expOnAltar; + + CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode::EMarketMode Mode); ~CAltarWindow(); - std::vector sacrificedUnits, //[slot_nr] -> how many creatures from that slot will be sacrificed - expPerUnit; - - CButton *sacrificeAll, *sacrificeBackpack; - CLabel *expToLevel, *expOnAltar; - + void getExpValues(); void selectionChanged(bool side) override; //true == left void selectOppositeItem(bool side); @@ -146,7 +160,7 @@ public: void SacrificeBackpack(); void putOnAltar(int backpackIndex); - bool putOnAltar(CTradeableItem* altarSlot, const CArtifactInstance *art); + bool putOnAltar(std::shared_ptr altarSlot, const CArtifactInstance * art); void makeDeal(); void showAll(SDL_Surface * to) override; @@ -161,9 +175,9 @@ public: void artifactsChanged(bool left) override; void calcTotalExp(); void setExpToLevel(); - void updateRight(CTradeableItem *toUpdate); + void updateRight(std::shared_ptr toUpdate); void artifactPicked(); int firstFreeSlot(); - void moveFromSlotToAltar(ArtifactPosition slotID, CTradeableItem* altarSlot, const CArtifactInstance *art); + void moveFromSlotToAltar(ArtifactPosition slotID, std::shared_ptr, const CArtifactInstance * art); }; diff --git a/client/windows/CWindowObject.cpp b/client/windows/CWindowObject.cpp index a8c2d8cdb..6b1e95845 100644 --- a/client/windows/CWindowObject.cpp +++ b/client/windows/CWindowObject.cpp @@ -34,13 +34,15 @@ #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt): - CIntObject(getUsedEvents(options_), Point()), - shadow(nullptr), - options(options_), - background(createBg(imageName, options & PLAYER_COLORED)) + CIntObject(getUsedEvents(options_), Point()), + shadow(nullptr), + options(options_), + background(createBg(imageName, options & PLAYER_COLORED)) { assert(parent == nullptr); //Safe to remove, but windows should not have parent + defActions = 255-DISPOSE; + if (options & RCLICK_POPUP) CCS->curh->hide(); @@ -54,51 +56,48 @@ CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt } CWindowObject::CWindowObject(int options_, std::string imageName): - CIntObject(getUsedEvents(options_), Point()), - shadow(nullptr), - options(options_), - background(createBg(imageName, options & PLAYER_COLORED)) + CIntObject(getUsedEvents(options_), Point()), + options(options_), + background(createBg(imageName, options_ & PLAYER_COLORED)) { assert(parent == nullptr); //Safe to remove, but windows should not have parent - if (options & RCLICK_POPUP) + defActions = 255-DISPOSE; + + if(options & RCLICK_POPUP) CCS->curh->hide(); - if (background) + if(background) pos = background->center(); else center(Point(screen->w/2, screen->h/2)); - if (!(options & SHADOW_DISABLED)) + if(!(options & SHADOW_DISABLED)) setShadow(true); } -CWindowObject::~CWindowObject() -{ - setShadow(false); -} +CWindowObject::~CWindowObject() = default; -CPicture * CWindowObject::createBg(std::string imageName, bool playerColored) +std::shared_ptr CWindowObject::createBg(std::string imageName, bool playerColored) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); - if (imageName.empty()) + if(imageName.empty()) return nullptr; - auto image = new CPicture(imageName); - if (playerColored) + auto image = std::make_shared(imageName); + if(playerColored) image->colorize(LOCPLINT->playerID); return image; } void CWindowObject::setBackground(std::string filename) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); - delete background; background = createBg(filename, options & PLAYER_COLORED); - if (background) + if(background) pos = background->center(Point(pos.w/2 + pos.x, pos.h/2 + pos.y)); updateShadow(); @@ -123,16 +122,16 @@ void CWindowObject::setShadow(bool on) //size of shadow static const int size = 8; - if (on == bool(shadow)) + if(on == bool(shadow)) return; - vstd::clear_pointer(shadow); + shadow.reset(); //object too small to cast shadow - if (pos.h <= size || pos.w <= size) + if(pos.h <= size || pos.w <= size) return; - if (on) + if(on) { //helper to set last row @@ -164,7 +163,7 @@ void CWindowObject::setShadow(bool on) static SDL_Surface * shadowRightTempl = nullptr; //one-time initialization - if (!shadowCornerTempl) + if(!shadowCornerTempl) { //create "template" surfaces shadowCornerTempl = CSDL_Ext::createSurfaceWithBpp<4>(size, size); @@ -185,8 +184,6 @@ void CWindowObject::setShadow(bool on) blitAlphaRow(shadowCornerTempl, size-1); } - OBJ_CONSTRUCTION_CAPTURING_ALL; - //FIXME: do something with this points Point shadowStart; if (options & BORDERED) @@ -215,10 +212,18 @@ void CWindowObject::setShadow(bool on) blitAlphaRow(shadowRight, 0); //generate "shadow" object with these 3 pieces in it - shadow = new CIntObject(); - shadow->addChild(new CPicture(shadowCorner, shadowPos.x, shadowPos.y)); - shadow->addChild(new CPicture(shadowRight, shadowPos.x, shadowStart.y)); - shadow->addChild(new CPicture(shadowBottom, shadowStart.x, shadowPos.y)); + { + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); + shadow = std::make_shared(); + } + + { + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255); + + shadow->addChild(new CPicture(shadowCorner, shadowPos.x, shadowPos.y)); + shadow->addChild(new CPicture(shadowRight, shadowPos.x, shadowStart.y)); + shadow->addChild(new CPicture(shadowBottom, shadowStart.x, shadowPos.y)); + } } } diff --git a/client/windows/CWindowObject.h b/client/windows/CWindowObject.h index 423a8cff3..44b5ca3b9 100644 --- a/client/windows/CWindowObject.h +++ b/client/windows/CWindowObject.h @@ -14,26 +14,24 @@ /// Basic class for windows class CWindowObject : public CIntObject { - CPicture * createBg(std::string imageName, bool playerColored); + std::shared_ptr createBg(std::string imageName, bool playerColored); int getUsedEvents(int options); - CIntObject *shadow; + std::shared_ptr shadow; void setShadow(bool on); int options; protected: - CPicture * background; + std::shared_ptr background; //Simple function with call to GH.popInt void close(); //Used only if RCLICK_POPUP was set void clickRight(tribool down, bool previousState) override; //To display border - void showAll(SDL_Surface *to) override; - //change or set background image - void setBackground(std::string filename); void updateShadow(); + void setBackground(std::string filename); public: enum EOptions { @@ -51,4 +49,6 @@ public: CWindowObject(int options, std::string imageName, Point centerAt); CWindowObject(int options, std::string imageName = ""); ~CWindowObject(); + + void showAll(SDL_Surface * to) override; }; diff --git a/client/windows/CreaturePurchaseCard.cpp b/client/windows/CreaturePurchaseCard.cpp index de34ff538..98083799a 100644 --- a/client/windows/CreaturePurchaseCard.cpp +++ b/client/windows/CreaturePurchaseCard.cpp @@ -75,7 +75,6 @@ void CreaturePurchaseCard::initCostBox() cost->createItems(creatureOnTheCard->cost); } - void CreaturePurchaseCard::sliderMoved(int to) { updateAmountInfo(to); diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 579d4c4d7..67ddf3592 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -67,18 +67,18 @@ using namespace CSDL_Ext; std::list CFocusable::focusables; CFocusable * CFocusable::inputWithFocus; -CRecruitmentWindow::CCreatureCard::CCreatureCard(CRecruitmentWindow *window, const CCreature *crea, int totalAmount): - CIntObject(LCLICK | RCLICK), +CRecruitmentWindow::CCreatureCard::CCreatureCard(CRecruitmentWindow * window, const CCreature * crea, int totalAmount) + : CIntObject(LCLICK | RCLICK), parent(window), selected(false), creature(crea), amount(totalAmount) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - pic = new CCreaturePic(1,1, creature, true, true); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + animation = std::make_shared(1, 1, creature, true, true); // 1 + 1 px for borders - pos.w = pic->pos.w + 2; - pos.h = pic->pos.h + 2; + pos.w = animation->pos.w + 2; + pos.h = animation->pos.h + 2; } void CRecruitmentWindow::CCreatureCard::select(bool on) @@ -89,40 +89,39 @@ void CRecruitmentWindow::CCreatureCard::select(bool on) void CRecruitmentWindow::CCreatureCard::clickLeft(tribool down, bool previousState) { - if (down) - parent->select(this); + if(down) + parent->select(this->shared_from_this()); } void CRecruitmentWindow::CCreatureCard::clickRight(tribool down, bool previousState) { - if (down) + if(down) GH.pushInt(new CStackWindow(creature, true)); } void CRecruitmentWindow::CCreatureCard::showAll(SDL_Surface * to) { CIntObject::showAll(to); - if (selected) + if(selected) drawBorder(to, pos, int3(248, 0, 0)); else drawBorder(to, pos, int3(232, 212, 120)); } - -void CRecruitmentWindow::select(CCreatureCard *card) +void CRecruitmentWindow::select(std::shared_ptr card) { - if (card == selected) + if(card == selected) return; - if (selected) + if(selected) selected->select(false); selected = card; - if (selected) + if(selected) selected->select(true); - if (card) + if(card) { si32 maxAmount = card->creature->maxAmount(LOCPLINT->cb->getResourceAmount()); @@ -194,7 +193,7 @@ void CRecruitmentWindow::showAll(SDL_Surface * to) drawBorder(to, pos.x + 289, pos.y + 312, 66, 34, int3(173,142,66)); } -CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, const CArmedInstance *Dst, const std::function &Recruit, int y_offset): +CRecruitmentWindow::CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function & Recruit, int y_offset): CWindowObject(PLAYER_COLORED, "TPRCRT"), onRecruit(Recruit), level(Level), @@ -204,43 +203,40 @@ CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, co { moveBy(Point(0, y_offset)); - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - slider = new CSlider(Point(176,279),135,std::bind(&CRecruitmentWindow::sliderMoved,this, _1),0,0,0,true); + statusBar = std::make_shared(std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); - maxButton = new CButton(Point(134, 313), "IRCBTNS.DEF", CGI->generaltexth->zelp[553], std::bind(&CSlider::moveToMax,slider), SDLK_m); - buyButton = new CButton(Point(212, 313), "IBY6432.DEF", CGI->generaltexth->zelp[554], std::bind(&CRecruitmentWindow::buy,this), SDLK_RETURN); - cancelButton = new CButton(Point(290, 313), "ICN6432.DEF", CGI->generaltexth->zelp[555], std::bind(&CRecruitmentWindow::close,this), SDLK_ESCAPE); + slider = std::make_shared(Point(176,279),135,std::bind(&CRecruitmentWindow::sliderMoved,this, _1),0,0,0,true); - title = new CLabel(243, 32, FONT_BIG, CENTER, Colors::YELLOW); - availableValue = new CLabel(205, 253, FONT_SMALL, CENTER, Colors::WHITE); - toRecruitValue = new CLabel(279, 253, FONT_SMALL, CENTER, Colors::WHITE); + maxButton = std::make_shared(Point(134, 313), "IRCBTNS.DEF", CGI->generaltexth->zelp[553], std::bind(&CSlider::moveToMax, slider), SDLK_m); + buyButton = std::make_shared(Point(212, 313), "IBY6432.DEF", CGI->generaltexth->zelp[554], std::bind(&CRecruitmentWindow::buy, this), SDLK_RETURN); + cancelButton = std::make_shared(Point(290, 313), "ICN6432.DEF", CGI->generaltexth->zelp[555], std::bind(&CRecruitmentWindow::close, this), SDLK_ESCAPE); - costPerTroopValue = new CreatureCostBox(Rect(65, 222, 97, 74), CGI->generaltexth->allTexts[346]); - totalCostValue = new CreatureCostBox(Rect(323, 222, 97, 74), CGI->generaltexth->allTexts[466]); + title = std::make_shared(243, 32, FONT_BIG, CENTER, Colors::YELLOW); + availableValue = std::make_shared(205, 253, FONT_SMALL, CENTER, Colors::WHITE); + toRecruitValue = std::make_shared(279, 253, FONT_SMALL, CENTER, Colors::WHITE); - new CLabel(205, 233, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[465]); //available t - new CLabel(279, 233, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[16]); //recruit t + costPerTroopValue = std::make_shared(Rect(65, 222, 97, 74), CGI->generaltexth->allTexts[346]); + totalCostValue = std::make_shared(Rect(323, 222, 97, 74), CGI->generaltexth->allTexts[466]); + + availableTitle = std::make_shared(205, 233, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[465]); + toRecruitTitle = std::make_shared(279, 233, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[16]); availableCreaturesChanged(); } void CRecruitmentWindow::availableCreaturesChanged() { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); size_t selectedIndex = 0; - if (!cards.empty() && selected) // find position of selected item + if(!cards.empty() && selected) // find position of selected item selectedIndex = std::find(cards.begin(), cards.end(), selected) - cards.begin(); - //deselect card select(nullptr); - //delete old cards - for(auto & card : cards) - delete card; cards.clear(); for(int i=0; icreatures.size(); i++) @@ -253,11 +249,9 @@ void CRecruitmentWindow::availableCreaturesChanged() //create new cards for(auto & creature : boost::adaptors::reverse(dwelling->creatures[i].second)) - cards.push_back(new CCreatureCard(this, CGI->creh->creatures[creature], amount)); + cards.push_back(std::make_shared(this, CGI->creh->creatures[creature], amount)); } - assert(!cards.empty()); - const int creatureWidth = 102; //normal distance between cards - 18px @@ -294,7 +288,7 @@ void CRecruitmentWindow::availableCreaturesChanged() void CRecruitmentWindow::sliderMoved(int to) { - if (!selected) + if(!selected) return; buyButton->block(!to); @@ -304,29 +298,27 @@ void CRecruitmentWindow::sliderMoved(int to) totalCostValue->set(selected->creature->cost * to); } -CSplitWindow::CSplitWindow(const CCreature * creature, std::function callback_, - int leftMin_, int rightMin_, int leftAmount_, int rightAmount_): - CWindowObject(PLAYER_COLORED, "GPUCRDIV"), +CSplitWindow::CSplitWindow(const CCreature * creature, std::function callback_, int leftMin_, int rightMin_, int leftAmount_, int rightAmount_) + : CWindowObject(PLAYER_COLORED, "GPUCRDIV"), callback(callback_), leftAmount(leftAmount_), rightAmount(rightAmount_), leftMin(leftMin_), - rightMin(rightMin_), - slider(nullptr) + rightMin(rightMin_) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); int total = leftAmount + rightAmount; int leftMax = total - rightMin; int rightMax = total - leftMin; - ok = new CButton(Point(20, 263), "IOK6432", CButton::tooltip(), std::bind(&CSplitWindow::apply, this), SDLK_RETURN); - cancel = new CButton(Point(214, 263), "ICN6432", CButton::tooltip(), std::bind(&CSplitWindow::close, this), SDLK_ESCAPE); + ok = std::make_shared(Point(20, 263), "IOK6432", CButton::tooltip(), std::bind(&CSplitWindow::apply, this), SDLK_RETURN); + cancel = std::make_shared(Point(214, 263), "ICN6432", CButton::tooltip(), std::bind(&CSplitWindow::close, this), SDLK_ESCAPE); - int sliderPositions = total - leftMin - rightMin; + int sliderPosition = total - leftMin - rightMin; - leftInput = new CTextInput(Rect(20, 218, 100, 36), FONT_BIG, std::bind(&CSplitWindow::setAmountText, this, _1, true)); - rightInput = new CTextInput(Rect(176, 218, 100, 36), FONT_BIG, std::bind(&CSplitWindow::setAmountText, this, _1, false)); + leftInput = std::make_shared(Rect(20, 218, 100, 36), FONT_BIG, std::bind(&CSplitWindow::setAmountText, this, _1, true)); + rightInput = std::make_shared(Rect(176, 218, 100, 36), FONT_BIG, std::bind(&CSplitWindow::setAmountText, this, _1, false)); //add filters to allow only number input leftInput->filters += std::bind(&CTextInput::numberFilter, _1, _2, leftMin, leftMax); @@ -335,20 +327,20 @@ CSplitWindow::CSplitWindow(const CCreature * creature, std::functionsetText(boost::lexical_cast(leftAmount), false); rightInput->setText(boost::lexical_cast(rightAmount), false); - animLeft = new CCreaturePic(20, 54, creature, true, false); - animRight = new CCreaturePic(177, 54,creature, true, false); + animLeft = std::make_shared(20, 54, creature, true, false); + animRight = std::make_shared(177, 54,creature, true, false); - slider = new CSlider(Point(21, 194), 257, std::bind(&CSplitWindow::sliderMoved, this, _1), 0, sliderPositions, rightAmount - rightMin, true); + slider = std::make_shared(Point(21, 194), 257, std::bind(&CSplitWindow::sliderMoved, this, _1), 0, sliderPosition, rightAmount - rightMin, true); - std::string title = CGI->generaltexth->allTexts[256]; - boost::algorithm::replace_first(title,"%s", creature->namePl); - new CLabel(150, 34, FONT_BIG, CENTER, Colors::YELLOW, title); + std::string titleStr = CGI->generaltexth->allTexts[256]; + boost::algorithm::replace_first(titleStr,"%s", creature->namePl); + title = std::make_shared(150, 34, FONT_BIG, CENTER, Colors::YELLOW, titleStr); } void CSplitWindow::setAmountText(std::string text, bool left) { int amount = 0; - if (text.length()) + if(text.length()) { try { @@ -360,7 +352,7 @@ void CSplitWindow::setAmountText(std::string text, bool left) } int total = leftAmount + rightAmount; - if (amount > total) + if(amount > total) amount = total; } @@ -389,48 +381,42 @@ void CSplitWindow::sliderMoved(int to) setAmount(rightMin + to, false); } -CLevelWindow::CLevelWindow(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector &skills, std::function callback): - CWindowObject(PLAYER_COLORED, "LVLUPBKG"), +CLevelWindow::CLevelWindow(const CGHeroInstance * hero, PrimarySkill::PrimarySkill pskill, std::vector & skills, std::function callback) + : CWindowObject(PLAYER_COLORED, "LVLUPBKG"), cb(callback) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); LOCPLINT->showingDialog->setn(true); - new CAnimImage("PortraitsLarge", hero->portrait, 0, 170, 66); - new CButton(Point(297, 413), "IOKAY", CButton::tooltip(), std::bind(&CLevelWindow::close, this), SDLK_RETURN); - - //%s has gained a level. - new CLabel(192, 33, FONT_MEDIUM, CENTER, Colors::WHITE, - boost::str(boost::format(CGI->generaltexth->allTexts[444]) % hero->name)); - - //%s is now a level %d %s. - new CLabel(192, 162, FONT_MEDIUM, CENTER, Colors::WHITE, - boost::str(boost::format(CGI->generaltexth->allTexts[445]) % hero->name % hero->level % hero->type->heroClass->name)); - - new CAnimImage("PSKIL42", pskill, 0, 174, 190); - - new CLabel(192, 253, FONT_MEDIUM, CENTER, Colors::WHITE, - CGI->generaltexth->primarySkillNames[pskill] + " +1"); - - if (!skills.empty()) + if(!skills.empty()) { - std::vector comps; - + std::vector> comps; for(auto & skill : skills) { - comps.push_back(new CSelectableComponent( - CComponent::secskill, - skill, - hero->getSecSkillLevel( SecondarySkill(skill) )+1, - CComponent::medium)); + auto comp = std::make_shared(CComponent::secskill, skill, hero->getSecSkillLevel(SecondarySkill(skill))+1, CComponent::medium); + comps.push_back(comp); } - box = new CComponentBox(comps, Rect(75, 300, pos.w - 150, 100)); + + box = std::make_shared(comps, Rect(75, 300, pos.w - 150, 100)); } - else - box = nullptr; + + portrait = std::make_shared("PortraitsLarge", hero->portrait, 0, 170, 66); + ok = std::make_shared(Point(297, 413), "IOKAY", CButton::tooltip(), std::bind(&CLevelWindow::close, this), SDLK_RETURN); + + //%s has gained a level. + mainTitle = std::make_shared(192, 33, FONT_MEDIUM, CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->allTexts[444]) % hero->name)); + + //%s is now a level %d %s. + levelTitle = std::make_shared(192, 162, FONT_MEDIUM, CENTER, Colors::WHITE, + boost::str(boost::format(CGI->generaltexth->allTexts[445]) % hero->name % hero->level % hero->type->heroClass->name)); + + skillIcon = std::make_shared("PSKIL42", pskill, 0, 174, 190); + + skillValue = std::make_shared(192, 253, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->primarySkillNames[pskill] + " +1"); } + CLevelWindow::~CLevelWindow() { //FIXME: call callback if there was nothing to select? @@ -452,17 +438,17 @@ static void setBoolSetting(std::string group, std::string field, bool value) fullscreen->Bool() = value; } -CSystemOptionsWindow::CSystemOptionsWindow(): - CWindowObject(PLAYER_COLORED, "SysOpBck"), +CSystemOptionsWindow::CSystemOptionsWindow() + : CWindowObject(PLAYER_COLORED, "SysOpBck"), onFullscreenChanged(settings.listen["video"]["fullscreen"]) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - title = new CLabel(242, 32, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[568]); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + title = std::make_shared(242, 32, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[568]); const JsonNode & texts = CGI->generaltexth->localizedTexts["systemOptions"]; //left window section - leftGroup = new CLabelGroup(FONT_MEDIUM, CENTER, Colors::YELLOW); + leftGroup = std::make_shared(FONT_MEDIUM, CENTER, Colors::YELLOW); leftGroup->add(122, 64, CGI->generaltexth->allTexts[569]); leftGroup->add(122, 130, CGI->generaltexth->allTexts[570]); leftGroup->add(122, 196, CGI->generaltexth->allTexts[571]); @@ -471,7 +457,7 @@ CSystemOptionsWindow::CSystemOptionsWindow(): leftGroup->add(122, 412, CGI->generaltexth->allTexts[395]); //right section - rightGroup = new CLabelGroup(FONT_MEDIUM, TOPLEFT, Colors::WHITE); + rightGroup = std::make_shared(FONT_MEDIUM, TOPLEFT, Colors::WHITE); rightGroup->add(282, 57, CGI->generaltexth->allTexts[572]); rightGroup->add(282, 89, CGI->generaltexth->allTexts[573]); rightGroup->add(282, 121, CGI->generaltexth->allTexts[574]); @@ -480,13 +466,13 @@ CSystemOptionsWindow::CSystemOptionsWindow(): rightGroup->add(282, 217, texts["fullscreenButton"]["label"].String()); //setting up buttons - load = new CButton (Point(246, 298), "SOLOAD.DEF", CGI->generaltexth->zelp[321], [&](){ bloadf(); }, SDLK_l); + load = std::make_shared(Point(246, 298), "SOLOAD.DEF", CGI->generaltexth->zelp[321], [&](){ bloadf(); }, SDLK_l); load->setImageOrder(1, 0, 2, 3); - save = new CButton (Point(357, 298), "SOSAVE.DEF", CGI->generaltexth->zelp[322], [&](){ bsavef(); }, SDLK_s); + save = std::make_shared(Point(357, 298), "SOSAVE.DEF", CGI->generaltexth->zelp[322], [&](){ bsavef(); }, SDLK_s); save->setImageOrder(1, 0, 2, 3); - restart = new CButton (Point(246, 357), "SORSTRT", CGI->generaltexth->zelp[323], [&](){ brestartf(); }, SDLK_r); + restart = std::make_shared(Point(246, 357), "SORSTRT", CGI->generaltexth->zelp[323], [&](){ brestartf(); }, SDLK_r); restart->setImageOrder(1, 0, 2, 3); if(CSH->isGuest()) @@ -496,73 +482,79 @@ CSystemOptionsWindow::CSystemOptionsWindow(): restart->block(true); } - mainMenu = new CButton (Point(357, 357), "SOMAIN.DEF", CGI->generaltexth->zelp[320], [&](){ bmainmenuf(); }, SDLK_m); + mainMenu = std::make_shared(Point(357, 357), "SOMAIN.DEF", CGI->generaltexth->zelp[320], [&](){ bmainmenuf(); }, SDLK_m); mainMenu->setImageOrder(1, 0, 2, 3); - quitGame = new CButton (Point(246, 415), "soquit.def", CGI->generaltexth->zelp[324], [&](){ bquitf(); }, SDLK_q); + quitGame = std::make_shared(Point(246, 415), "soquit.def", CGI->generaltexth->zelp[324], [&](){ bquitf(); }, SDLK_q); quitGame->setImageOrder(1, 0, 2, 3); - backToMap = new CButton ( Point(357, 415), "soretrn.def", CGI->generaltexth->zelp[325], [&](){ breturnf(); }, SDLK_RETURN); + backToMap = std::make_shared( Point(357, 415), "soretrn.def", CGI->generaltexth->zelp[325], [&](){ breturnf(); }, SDLK_RETURN); backToMap->setImageOrder(1, 0, 2, 3); backToMap->assignedKeys.insert(SDLK_ESCAPE); - heroMoveSpeed = new CToggleGroup(0); - heroMoveSpeed->addToggle(1, new CToggleButton(Point( 28, 77), "sysopb1.def", CGI->generaltexth->zelp[349])); - heroMoveSpeed->addToggle(2, new CToggleButton(Point( 76, 77), "sysopb2.def", CGI->generaltexth->zelp[350])); - heroMoveSpeed->addToggle(4, new CToggleButton(Point(124, 77), "sysopb3.def", CGI->generaltexth->zelp[351])); - heroMoveSpeed->addToggle(8, new CToggleButton(Point(172, 77), "sysopb4.def", CGI->generaltexth->zelp[352])); + heroMoveSpeed = std::make_shared(0); + enemyMoveSpeed = std::make_shared(0); + mapScrollSpeed = std::make_shared(0); + + heroMoveSpeed->addToggle(1, std::make_shared(Point( 28, 77), "sysopb1.def", CGI->generaltexth->zelp[349])); + heroMoveSpeed->addToggle(2, std::make_shared(Point( 76, 77), "sysopb2.def", CGI->generaltexth->zelp[350])); + heroMoveSpeed->addToggle(4, std::make_shared(Point(124, 77), "sysopb3.def", CGI->generaltexth->zelp[351])); + heroMoveSpeed->addToggle(8, std::make_shared(Point(172, 77), "sysopb4.def", CGI->generaltexth->zelp[352])); heroMoveSpeed->setSelected(settings["adventure"]["heroSpeed"].Float()); heroMoveSpeed->addCallback(std::bind(&setIntSetting, "adventure", "heroSpeed", _1)); - enemyMoveSpeed = new CToggleGroup(0); - enemyMoveSpeed->addToggle(2, new CToggleButton(Point( 28, 144), "sysopb5.def", CGI->generaltexth->zelp[353])); - enemyMoveSpeed->addToggle(4, new CToggleButton(Point( 76, 144), "sysopb6.def", CGI->generaltexth->zelp[354])); - enemyMoveSpeed->addToggle(8, new CToggleButton(Point(124, 144), "sysopb7.def", CGI->generaltexth->zelp[355])); - enemyMoveSpeed->addToggle(0, new CToggleButton(Point(172, 144), "sysopb8.def", CGI->generaltexth->zelp[356])); + enemyMoveSpeed->addToggle(2, std::make_shared(Point( 28, 144), "sysopb5.def", CGI->generaltexth->zelp[353])); + enemyMoveSpeed->addToggle(4, std::make_shared(Point( 76, 144), "sysopb6.def", CGI->generaltexth->zelp[354])); + enemyMoveSpeed->addToggle(8, std::make_shared(Point(124, 144), "sysopb7.def", CGI->generaltexth->zelp[355])); + enemyMoveSpeed->addToggle(0, std::make_shared(Point(172, 144), "sysopb8.def", CGI->generaltexth->zelp[356])); enemyMoveSpeed->setSelected(settings["adventure"]["enemySpeed"].Float()); enemyMoveSpeed->addCallback(std::bind(&setIntSetting, "adventure", "enemySpeed", _1)); - mapScrollSpeed = new CToggleGroup(0); - mapScrollSpeed->addToggle(1, new CToggleButton(Point( 28, 210), "sysopb9.def", CGI->generaltexth->zelp[357])); - mapScrollSpeed->addToggle(2, new CToggleButton(Point( 92, 210), "sysob10.def", CGI->generaltexth->zelp[358])); - mapScrollSpeed->addToggle(4, new CToggleButton(Point(156, 210), "sysob11.def", CGI->generaltexth->zelp[359])); + mapScrollSpeed->addToggle(1, std::make_shared(Point( 28, 210), "sysopb9.def", CGI->generaltexth->zelp[357])); + mapScrollSpeed->addToggle(2, std::make_shared(Point( 92, 210), "sysob10.def", CGI->generaltexth->zelp[358])); + mapScrollSpeed->addToggle(4, std::make_shared(Point(156, 210), "sysob11.def", CGI->generaltexth->zelp[359])); mapScrollSpeed->setSelected(settings["adventure"]["scrollSpeed"].Float()); mapScrollSpeed->addCallback(std::bind(&setIntSetting, "adventure", "scrollSpeed", _1)); - musicVolume = new CVolumeSlider(Point(29, 359), "syslb.def", CCS->musich->getVolume(), &CGI->generaltexth->zelp[326]); + musicVolume = std::make_shared(Point(29, 359), "syslb.def", CCS->musich->getVolume(), &CGI->generaltexth->zelp[326]); musicVolume->addCallback(std::bind(&setIntSetting, "general", "music", _1)); - effectsVolume = new CVolumeSlider(Point(29, 425), "syslb.def", CCS->soundh->getVolume(), &CGI->generaltexth->zelp[336]); + effectsVolume = std::make_shared(Point(29, 425), "syslb.def", CCS->soundh->getVolume(), &CGI->generaltexth->zelp[336]); effectsVolume->addCallback(std::bind(&setIntSetting, "general", "sound", _1)); - showReminder = new CToggleButton(Point(246, 87), "sysopchk.def", CGI->generaltexth->zelp[361], - [&] (bool value) { setBoolSetting("adventure", "heroReminder", value); }); - - quickCombat = new CToggleButton(Point(246, 87+32), "sysopchk.def", CGI->generaltexth->zelp[362], - [&] (bool value) { setBoolSetting("adventure", "quickCombat", value); }); - - spellbookAnim = new CToggleButton(Point(246, 87+64), "sysopchk.def", CGI->generaltexth->zelp[364], - [&] (bool value) { setBoolSetting("video", "spellbookAnimation", value); }); - - fullscreen = new CToggleButton(Point(246, 215), "sysopchk.def", CButton::tooltip(texts["fullscreenButton"]), - [&] (bool value) { setBoolSetting("video", "fullscreen", value); }); - + showReminder = std::make_shared(Point(246, 87), "sysopchk.def", CGI->generaltexth->zelp[361], [&](bool value) + { + setBoolSetting("adventure", "heroReminder", value); + }); showReminder->setSelected(settings["adventure"]["heroReminder"].Bool()); + + quickCombat = std::make_shared(Point(246, 87+32), "sysopchk.def", CGI->generaltexth->zelp[362], [&](bool value) + { + setBoolSetting("adventure", "quickCombat", value); + }); quickCombat->setSelected(settings["adventure"]["quickCombat"].Bool()); + + spellbookAnim = std::make_shared(Point(246, 87+64), "sysopchk.def", CGI->generaltexth->zelp[364], [&](bool value) + { + setBoolSetting("video", "spellbookAnimation", value); + }); spellbookAnim->setSelected(settings["video"]["spellbookAnimation"].Bool()); + + fullscreen = std::make_shared(Point(246, 215), "sysopchk.def", CButton::tooltip(texts["fullscreenButton"]), [&](bool value) + { + setBoolSetting("video", "fullscreen", value); + }); fullscreen->setSelected(settings["video"]["fullscreen"].Bool()); onFullscreenChanged([&](const JsonNode &newState){ fullscreen->setSelected(newState.Bool());}); - gameResButton = new CButton(Point(28, 275),"buttons/resolution", CButton::tooltip(texts["resolutionButton"]), - std::bind(&CSystemOptionsWindow::selectGameRes, this), SDLK_g); + gameResButton = std::make_shared(Point(28, 275),"buttons/resolution", CButton::tooltip(texts["resolutionButton"]), std::bind(&CSystemOptionsWindow::selectGameRes, this), SDLK_g); std::string resText; resText += boost::lexical_cast(settings["video"]["screenRes"]["width"].Float()); resText += "x"; resText += boost::lexical_cast(settings["video"]["screenRes"]["height"].Float()); - gameResLabel = new CLabel(170, 292, FONT_MEDIUM, CENTER, Colors::YELLOW, resText); - + gameResLabel = std::make_shared(170, 292, FONT_MEDIUM, CENTER, Colors::YELLOW, resText); } void CSystemOptionsWindow::selectGameRes() @@ -638,35 +630,37 @@ void CSystemOptionsWindow::closeAndPushEvent(int eventType, int code) GH.pushSDLEvent(eventType, code); } -CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj): - CWindowObject(PLAYER_COLORED, "TPTAVERN"), +CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj) + : CWindowObject(PLAYER_COLORED, "TPTAVERN"), tavernObj(TavernObj) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + std::vector h = LOCPLINT->cb->getAvailableHeroes(TavernObj); if(h.size() < 2) h.resize(2, nullptr); - h1 = new HeroPortrait(selected,0,72,299,h[0]); - h2 = new HeroPortrait(selected,1,162,299,h[1]); - selected = 0; - if (!h[0]) + if(!h[0]) selected = 1; - if (!h[0] && !h[1]) + if(!h[0] && !h[1]) selected = -1; + oldSelected = -1; - new CLabel(200, 35, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[37]); - new CLabel(320, 328, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast(GameConstants::HERO_GOLD_COST)); + h1 = std::make_shared(selected, 0, 72, 299, h[0]); + h2 = std::make_shared(selected, 1, 162, 299, h[1]); + + title = std::make_shared(200, 35, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[37]); + cost = std::make_shared(320, 328, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast(GameConstants::HERO_GOLD_COST)); auto rumorText = boost::str(boost::format(CGI->generaltexth->allTexts[216]) % LOCPLINT->cb->getTavernRumor(tavernObj)); - new CTextBox(rumorText, Rect(32, 190, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE); + rumor = std::make_shared(rumorText, Rect(32, 190, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE); - new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); - cancel = new CButton(Point(310, 428), "ICANCEL.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[7]), std::bind(&CTavernWindow::close, this), SDLK_ESCAPE); - recruit = new CButton(Point(272, 355), "TPTAV01.DEF", CButton::tooltip(), std::bind(&CTavernWindow::recruitb, this), SDLK_RETURN); - thiefGuild = new CButton(Point(22, 428), "TPTAV02.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[5]), std::bind(&CTavernWindow::thievesguildb, this), SDLK_t); + statusBar = std::make_shared(std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + cancel = std::make_shared(Point(310, 428), "ICANCEL.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[7]), std::bind(&CTavernWindow::close, this), SDLK_ESCAPE); + recruit = std::make_shared(Point(272, 355), "TPTAV01.DEF", CButton::tooltip(), std::bind(&CTavernWindow::recruitb, this), SDLK_RETURN); + thiefGuild = std::make_shared(Point(22, 428), "TPTAV02.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[5]), std::bind(&CTavernWindow::thievesguildb, this), SDLK_t); if(LOCPLINT->cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST) //not enough gold { @@ -695,7 +689,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj): if(selected == -1) recruit->block(true); } - if (LOCPLINT->castleInt) + if(LOCPLINT->castleInt) CCS->videoh->open(LOCPLINT->castleInt->town->town->clientInfo.tavernVideo); else CCS->videoh->open("TAVERN.BIK"); @@ -726,7 +720,7 @@ void CTavernWindow::show(SDL_Surface * to) CCS->videoh->update(pos.x+70, pos.y+56, to, true, false); if(selected >= 0) { - HeroPortrait *sel = selected ? h2 : h1; + auto sel = selected ? h2 : h1; if (selected != oldSelected && !recruit->isBlocked()) { @@ -756,11 +750,11 @@ void CTavernWindow::HeroPortrait::clickRight(tribool down, bool previousState) } } -CTavernWindow::HeroPortrait::HeroPortrait(int &sel, int id, int x, int y, const CGHeroInstance *H) -: h(H), _sel(&sel), _id(id) +CTavernWindow::HeroPortrait::HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H) + : CIntObject(LCLICK | RCLICK | HOVER), + h(H), _sel(&sel), _id(id) { - addUsedEvents(LCLICK | RCLICK | HOVER); - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); h = H; pos.x += x; pos.y += y; @@ -783,11 +777,11 @@ CTavernWindow::HeroPortrait::HeroPortrait(int &sel, int id, int x, int y, const boost::algorithm::replace_first(description, "%s", h->type->heroClass->name); boost::algorithm::replace_first(description, "%d", boost::lexical_cast(artifs)); - new CAnimImage("portraitsLarge", h->portrait); + portrait = std::make_shared("portraitsLarge", h->portrait); } } -void CTavernWindow::HeroPortrait::hover( bool on ) +void CTavernWindow::HeroPortrait::hover(bool on) { //Hoverable::hover(on); if(on) @@ -796,88 +790,72 @@ void CTavernWindow::HeroPortrait::hover( bool on ) GH.statusbar->clear(); } -void CExchangeWindow::questlog(int whichHero) +CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID) + : CWindowObject(PLAYER_COLORED | BORDERED, "TRADE2") { - CCS->curh->dragAndDropCursor(nullptr); - LOCPLINT->showQuestLog(); -} + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); -void CExchangeWindow::prepareBackground() -{ - //printing heroes' names and levels - auto genTitle = [](const CGHeroInstance *h) - { - return boost::str(boost::format(CGI->generaltexth->allTexts[138]) - % h->name % h->level % h->type->heroClass->name); - }; - - new CLabel(147, 25, FONT_SMALL, CENTER, Colors::WHITE, genTitle(heroInst[0])); - new CLabel(653, 25, FONT_SMALL, CENTER, Colors::WHITE, genTitle(heroInst[1])); - - //printing primary skills - for(int g=0; g<4; ++g) - new CAnimImage("PSKIL32", g, 0, 385, 19 + 36*g); - - //heroes related thing - for(int b=0; b(heroWArt.getPrimSkillLevel(static_cast(m)))); - - //printing secondary skills - for(int m=0; msecSkills.size(); ++m) - { - int id = heroInst[b]->secSkills[m].first; - int level = heroInst[b]->secSkills[m].second; - new CAnimImage("SECSK32", id*3 + level + 2 , 0, 32 + 36 * m + 454 * b, 88); - } - - //hero's specialty - new CAnimImage("UN32", heroInst[b]->type->imageIndex, 0, 67 + 490*b, 45); - - //experience - new CAnimImage("PSKIL32", 4, 0, 103 + 490*b, 45); - new CLabel(119 + 490*b, 71, FONT_SMALL, CENTER, Colors::WHITE, makeNumberShort(heroInst[b]->exp)); - - //mana points - new CAnimImage("PSKIL32", 5, 0, 139 + 490*b, 45); - new CLabel(155 + 490*b, 71, FONT_SMALL, CENTER, Colors::WHITE, makeNumberShort(heroInst[b]->mana)); - } - - //printing portraits - new CAnimImage("PortraitsLarge", heroInst[0]->portrait, 0, 257, 13); - new CAnimImage("PortraitsLarge", heroInst[1]->portrait, 0, 485, 13); -} - -CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID): - CWindowObject(PLAYER_COLORED | BORDERED, "TRADE2") -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; heroInst[0] = LOCPLINT->cb->getHero(hero1); heroInst[1] = LOCPLINT->cb->getHero(hero2); - prepareBackground(); + auto genTitle = [](const CGHeroInstance * h) + { + boost::format fmt(CGI->generaltexth->allTexts[138]); + fmt % h->name % h->level % h->type->heroClass->name; + return boost::str(fmt); + }; - artifs[0] = new CArtifactsOfHero(Point(-334, 150)); + titles[0] = std::make_shared(147, 25, FONT_SMALL, CENTER, Colors::WHITE, genTitle(heroInst[0])); + titles[1] = std::make_shared(653, 25, FONT_SMALL, CENTER, Colors::WHITE, genTitle(heroInst[1])); + + auto PSKIL32 = std::make_shared("PSKIL32"); + PSKIL32->preload(); + + auto SECSK32 = std::make_shared("SECSK32"); + + for(int g = 0; g < 4; ++g) + primSkillImages.push_back(std::make_shared(PSKIL32, g, 0, 385, 19 + 36 * g)); + + for(int leftRight : {0, 1}) + { + const CGHeroInstance * hero = heroInst.at(leftRight); + + herosWArt[leftRight] = std::make_shared(this, hero); + + for(int m=0; m(352 + 93 * leftRight, 35 + 36 * m, FONT_SMALL, CENTER, Colors::WHITE)); + + + for(int m=0; m < hero->secSkills.size(); ++m) + secSkillIcons[leftRight].push_back(std::make_shared(SECSK32, 0, 0, 32 + 36 * m + 454 * leftRight, 88)); + + specImages[leftRight] = std::make_shared("UN32", hero->type->imageIndex, 0, 67 + 490 * leftRight, 45); + + expImages[leftRight] = std::make_shared(PSKIL32, 4, 0, 103 + 490 * leftRight, 45); + expValues[leftRight] = std::make_shared(119 + 490 * leftRight, 71, FONT_SMALL, CENTER, Colors::WHITE); + + manaImages[leftRight] = std::make_shared(PSKIL32, 5, 0, 139 + 490 * leftRight, 45); + manaValues[leftRight] = std::make_shared(155 + 490 * leftRight, 71, FONT_SMALL, CENTER, Colors::WHITE); + } + + portraits[0] = std::make_shared("PortraitsLarge", heroInst[0]->portrait, 0, 257, 13); + portraits[1] = std::make_shared("PortraitsLarge", heroInst[1]->portrait, 0, 485, 13); + + artifs[0] = std::make_shared(Point(-334, 150)); artifs[0]->commonInfo = std::make_shared(); - artifs[0]->commonInfo->participants.insert(artifs[0]); + artifs[0]->commonInfo->participants.insert(artifs[0].get()); artifs[0]->setHero(heroInst[0]); - artifs[1] = new CArtifactsOfHero(Point(96, 150)); + artifs[1] = std::make_shared(Point(96, 150)); artifs[1]->commonInfo = artifs[0]->commonInfo; - artifs[1]->commonInfo->participants.insert(artifs[1]); + artifs[1]->commonInfo->participants.insert(artifs[1].get()); artifs[1]->setHero(heroInst[1]); - artSets.push_back(artifs[0]); - artSets.push_back(artifs[1]); + addSet(artifs[0]); + addSet(artifs[1]); - //primary skills for(int g=0; g<4; ++g) { - //primary skill's clickable areas - primSkillAreas.push_back(new LRClickableAreaWTextComp()); + primSkillAreas.push_back(std::make_shared()); primSkillAreas[g]->pos = genRect(32, 140, pos.x + 329, pos.y + 19 + 36 * g); primSkillAreas[g]->text = CGI->generaltexth->arraytxt[2+g]; primSkillAreas[g]->type = g; @@ -888,14 +866,16 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, } //heroes related thing - for(int b=0; bsecSkills.size(); ++g) + for(int g=0; gsecSkills.size(); ++g) { - int skill = heroInst[b]->secSkills[g].first, - level = heroInst[b]->secSkills[g].second; // <1, 3> - secSkillAreas[b].push_back(new LRClickableAreaWTextComp()); + int skill = hero->secSkills[g].first, + level = hero->secSkills[g].second; // <1, 3> + secSkillAreas[b].push_back(std::make_shared()); secSkillAreas[b][g]->pos = genRect(32, 32, pos.x + 32 + g*36 + b*454 , pos.y + 88); secSkillAreas[b][g]->baseType = 1; @@ -908,52 +888,49 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, boost::algorithm::replace_first(secSkillAreas[b][g]->hoverText, "%s", CGI->skillh->skillName(skill)); } - portrait[b] = new CHeroArea(257 + 228*b, 13, heroInst[b]); + heroAreas[b] = std::make_shared(257 + 228*b, 13, hero); - specialty[b] = new LRClickableAreaWText(); - specialty[b]->pos = genRect(32, 32, pos.x + 69 + 490*b, pos.y + 45); - specialty[b]->hoverText = CGI->generaltexth->heroscrn[27]; - specialty[b]->text = heroInst[b]->type->specDescr; + specialtyAreas[b] = std::make_shared(); + specialtyAreas[b]->pos = genRect(32, 32, pos.x + 69 + 490*b, pos.y + 45); + specialtyAreas[b]->hoverText = CGI->generaltexth->heroscrn[27]; + specialtyAreas[b]->text = hero->type->specDescr; - experience[b] = new LRClickableAreaWText(); - experience[b]->pos = genRect(32, 32, pos.x + 105 + 490*b, pos.y + 45); - experience[b]->hoverText = CGI->generaltexth->heroscrn[9]; - experience[b]->text = CGI->generaltexth->allTexts[2].c_str(); - boost::algorithm::replace_first(experience[b]->text, "%d", boost::lexical_cast(heroInst[b]->level)); - boost::algorithm::replace_first(experience[b]->text, "%d", boost::lexical_cast(CGI->heroh->reqExp(heroInst[b]->level+1))); - boost::algorithm::replace_first(experience[b]->text, "%d", boost::lexical_cast(heroInst[b]->exp)); + experienceAreas[b] = std::make_shared(); + experienceAreas[b]->pos = genRect(32, 32, pos.x + 105 + 490*b, pos.y + 45); + experienceAreas[b]->hoverText = CGI->generaltexth->heroscrn[9]; + experienceAreas[b]->text = CGI->generaltexth->allTexts[2]; + boost::algorithm::replace_first(experienceAreas[b]->text, "%d", boost::lexical_cast(hero->level)); + boost::algorithm::replace_first(experienceAreas[b]->text, "%d", boost::lexical_cast(CGI->heroh->reqExp(hero->level+1))); + boost::algorithm::replace_first(experienceAreas[b]->text, "%d", boost::lexical_cast(hero->exp)); - spellPoints[b] = new LRClickableAreaWText(); - spellPoints[b]->pos = genRect(32, 32, pos.x + 141 + 490*b, pos.y + 45); - spellPoints[b]->hoverText = CGI->generaltexth->heroscrn[22]; - spellPoints[b]->text = CGI->generaltexth->allTexts[205]; - boost::algorithm::replace_first(spellPoints[b]->text, "%s", heroInst[b]->name); - boost::algorithm::replace_first(spellPoints[b]->text, "%d", boost::lexical_cast(heroInst[b]->mana)); - boost::algorithm::replace_first(spellPoints[b]->text, "%d", boost::lexical_cast(heroInst[b]->manaLimit())); + spellPointsAreas[b] = std::make_shared(); + spellPointsAreas[b]->pos = genRect(32, 32, pos.x + 141 + 490*b, pos.y + 45); + spellPointsAreas[b]->hoverText = CGI->generaltexth->heroscrn[22]; + spellPointsAreas[b]->text = CGI->generaltexth->allTexts[205]; + boost::algorithm::replace_first(spellPointsAreas[b]->text, "%s", hero->name); + boost::algorithm::replace_first(spellPointsAreas[b]->text, "%d", boost::lexical_cast(hero->mana)); + boost::algorithm::replace_first(spellPointsAreas[b]->text, "%d", boost::lexical_cast(hero->manaLimit())); - //setting morale - morale[b] = new MoraleLuckBox(true, genRect(32, 32, 176 + 490*b, 39), true); - morale[b]->set(heroInst[b]); - //setting luck - luck[b] = new MoraleLuckBox(false, genRect(32, 32, 212 + 490*b, 39), true); - luck[b]->set(heroInst[b]); + morale[b] = std::make_shared(true, genRect(32, 32, 176 + 490 * b, 39), true); + luck[b] = std::make_shared(false, genRect(32, 32, 212 + 490 * b, 39), true); } - //buttons - quit = new CButton(Point(732, 567), "IOKAY.DEF", CGI->generaltexth->zelp[600], std::bind(&CExchangeWindow::close, this), SDLK_RETURN); + quit = std::make_shared(Point(732, 567), "IOKAY.DEF", CGI->generaltexth->zelp[600], std::bind(&CExchangeWindow::close, this), SDLK_RETURN); if(queryID.getNum() > 0) quit->addCallback([=](){ LOCPLINT->cb->selectionMade(0, queryID); }); - questlogButton[0] = new CButton(Point( 10, 44), "hsbtns4.def", CButton::tooltip(CGI->generaltexth->heroscrn[0]), std::bind(&CExchangeWindow::questlog,this, 0)); - questlogButton[1] = new CButton(Point(740, 44), "hsbtns4.def", CButton::tooltip(CGI->generaltexth->heroscrn[0]), std::bind(&CExchangeWindow::questlog,this, 1)); + questlogButton[0] = std::make_shared(Point( 10, 44), "hsbtns4.def", CButton::tooltip(CGI->generaltexth->heroscrn[0]), std::bind(&CExchangeWindow::questlog, this, 0)); + questlogButton[1] = std::make_shared(Point(740, 44), "hsbtns4.def", CButton::tooltip(CGI->generaltexth->heroscrn[0]), std::bind(&CExchangeWindow::questlog, this, 1)); Rect barRect(5, 578, 725, 18); - ourBar = new CGStatusBar(new CPicture(*background, barRect, 5, 578, false)); + statusBar = std::make_shared(std::make_shared(*background, barRect, 5, 578, false)); //garrison interface - garr = new CGarrisonInt(69, 131, 4, Point(418,0), *background, Point(69,131), heroInst[0],heroInst[1], true, true); - garr->addSplitBtn(new CButton( Point( 10, 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), std::bind(&CGarrisonInt::splitClick, garr))); - garr->addSplitBtn(new CButton( Point(740, 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), std::bind(&CGarrisonInt::splitClick, garr))); + garr = std::make_shared(69, 131, 4, Point(418,0), heroInst[0], heroInst[1], true, true); + garr->addSplitBtn(std::make_shared( Point( 10, 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), std::bind(&CGarrisonInt::splitClick, garr))); + garr->addSplitBtn(std::make_shared( Point(740, 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), std::bind(&CGarrisonInt::splitClick, garr))); + + updateWidgets(); } CExchangeWindow::~CExchangeWindow() @@ -962,31 +939,72 @@ CExchangeWindow::~CExchangeWindow() artifs[1]->commonInfo = nullptr; } -CShipyardWindow::CShipyardWindow(const std::vector &cost, int state, int boatType, const std::function &onBuy): - CWindowObject(PLAYER_COLORED, "TPSHIP") +void CExchangeWindow::updateGarrisons() { - OBJ_CONSTRUCTION_CAPTURING_ALL; + garr->recreateSlots(); - bgWater = new CPicture("TPSHIPBK", 100, 69); + updateWidgets(); +} + +void CExchangeWindow::questlog(int whichHero) +{ + CCS->curh->dragAndDropCursor(nullptr); + LOCPLINT->showQuestLog(); +} + +void CExchangeWindow::updateWidgets() +{ + for(size_t leftRight : {0, 1}) + { + const CGHeroInstance * hero = heroInst.at(leftRight); + + for(int m=0; mgetPrimSkillLevel(static_cast(m)); + primSkillValues[leftRight][m]->setText(boost::lexical_cast(value)); + } + + for(int m=0; m < hero->secSkills.size(); ++m) + { + int id = hero->secSkills[m].first; + int level = hero->secSkills[m].second; + + secSkillIcons[leftRight][m]->setFrame(2 + id * 3 + level); + } + + expValues[leftRight]->setText(makeNumberShort(hero->exp)); + manaValues[leftRight]->setText(makeNumberShort(hero->mana)); + + morale[leftRight]->set(hero); + luck[leftRight]->set(hero); + } +} + +CShipyardWindow::CShipyardWindow(const std::vector & cost, int state, int boatType, const std::function & onBuy) + : CWindowObject(PLAYER_COLORED, "TPSHIP") +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + bgWater = std::make_shared("TPSHIPBK", 100, 69); std::string boatFilenames[3] = {"AB01_", "AB02_", "AB03_"}; Point waterCenter = Point(bgWater->pos.x+bgWater->pos.w/2, bgWater->pos.y+bgWater->pos.h/2); - bgShip = new CAnimImage(boatFilenames[boatType], 0, 7, 120, 96, CShowableAnim::USE_RLE); + bgShip = std::make_shared(boatFilenames[boatType], 0, 7, 120, 96, CShowableAnim::USE_RLE); bgShip->center(waterCenter); // Create resource icons and costs. std::string goldValue = boost::lexical_cast(cost[Res::GOLD]); std::string woodValue = boost::lexical_cast(cost[Res::WOOD]); - goldCost = new CLabel(118, 294, FONT_SMALL, CENTER, Colors::WHITE, goldValue); - woodCost = new CLabel(212, 294, FONT_SMALL, CENTER, Colors::WHITE, woodValue); + goldCost = std::make_shared(118, 294, FONT_SMALL, CENTER, Colors::WHITE, goldValue); + woodCost = std::make_shared(212, 294, FONT_SMALL, CENTER, Colors::WHITE, woodValue); - goldPic = new CAnimImage("RESOURCE", Res::GOLD, 0, 100, 244); - woodPic = new CAnimImage("RESOURCE", Res::WOOD, 0, 196, 244); + goldPic = std::make_shared("RESOURCE", Res::GOLD, 0, 100, 244); + woodPic = std::make_shared("RESOURCE", Res::WOOD, 0, 196, 244); - quit = new CButton( Point(224, 312), "ICANCEL", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CShipyardWindow::close, this), SDLK_RETURN); - build = new CButton( Point( 42, 312), "IBUY30", CButton::tooltip(CGI->generaltexth->allTexts[598]), std::bind(&CShipyardWindow::close, this),SDLK_RETURN); + quit = std::make_shared(Point(224, 312), "ICANCEL", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CShipyardWindow::close, this), SDLK_RETURN); + build = std::make_shared(Point(42, 312), "IBUY30", CButton::tooltip(CGI->generaltexth->allTexts[598]), std::bind(&CShipyardWindow::close, this), SDLK_RETURN); build->addCallback(onBuy); for(Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, 1)) @@ -998,27 +1016,28 @@ CShipyardWindow::CShipyardWindow(const std::vector &cost, int state, int b } } - statusBar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + statusBar = std::make_shared(std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); - title = new CLabel(164, 27, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[13]); - costLabel = new CLabel(164, 220, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->jktexts[14]); + title = std::make_shared(164, 27, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[13]); + costLabel = std::make_shared(164, 220, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->jktexts[14]); } -CPuzzleWindow::CPuzzleWindow(const int3 &GrailPos, double discoveredRatio): - CWindowObject(PLAYER_COLORED | BORDERED, "PUZZLE"), +CPuzzleWindow::CPuzzleWindow(const int3 & GrailPos, double discoveredRatio) + : CWindowObject(PLAYER_COLORED | BORDERED, "PUZZLE"), grailPos(GrailPos), currentAlpha(SDL_ALPHA_OPAQUE) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + CCS->soundh->playSound(soundBase::OBELISK); - quitb = new CButton(Point(670, 538), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CPuzzleWindow::close, this), SDLK_RETURN); + quitb = std::make_shared(Point(670, 538), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CPuzzleWindow::close, this), SDLK_RETURN); quitb->assignedKeys.insert(SDLK_ESCAPE); quitb->setBorderColor(Colors::METALLIC_GOLD); - new CPicture("PUZZLOGO", 607, 3); - new CLabel(700, 95, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[463]); - new CResDataBar("ARESBAR.bmp", 3, 575, 32, 2, 85, 85); + logo = std::make_shared("PUZZLOGO", 607, 3); + title = std::make_shared(700, 95, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[463]); + resDataBar = std::make_shared("ARESBAR.bmp", 3, 575, 32, 2, 85, 85); int faction = LOCPLINT->cb->getStartInfo()->playerInfos.find(LOCPLINT->playerID)->second.castle; @@ -1028,7 +1047,7 @@ CPuzzleWindow::CPuzzleWindow(const int3 &GrailPos, double discoveredRatio): { const SPuzzleInfo & info = elem; - auto piece = new CPicture(info.filename, info.x, info.y); + auto piece = std::make_shared(info.filename, info.x, info.y); //piece that will slowly disappear if(info.whenUncovered <= GameConstants::PUZZLE_MAP_PIECES * discoveredRatio) @@ -1038,6 +1057,10 @@ CPuzzleWindow::CPuzzleWindow(const int3 &GrailPos, double discoveredRatio): piece->recActions = piece->recActions & ~SHOWALL; SDL_SetSurfaceBlendMode(piece->bg,SDL_BLENDMODE_BLEND); } + else + { + visiblePieces.push_back(piece); + } } } @@ -1059,11 +1082,8 @@ void CPuzzleWindow::show(SDL_Surface * to) { static int animSpeed = 2; - if (currentAlpha < animSpeed) + if(currentAlpha < animSpeed) { - //animation done - for(auto & piece : piecesToRemove) - delete piece; piecesToRemove.clear(); } else @@ -1078,7 +1098,7 @@ void CPuzzleWindow::show(SDL_Surface * to) void CTransformerWindow::CItem::move() { - if (left) + if(left) moveBy(Point(289, 0)); else moveBy(Point(-289, 0)); @@ -1099,79 +1119,106 @@ void CTransformerWindow::CItem::update() icon->setFrame(parent->army->getCreature(SlotID(id))->idNumber + 2); } -CTransformerWindow::CItem::CItem(CTransformerWindow * parent, int size, int id): - id(id), size(size), parent(parent) +CTransformerWindow::CItem::CItem(CTransformerWindow * parent_, int size_, int id_) + : CIntObject(LCLICK), + id(id_), + size(size_), + parent(parent_) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - addUsedEvents(LCLICK); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); left = true; pos.w = 58; pos.h = 64; pos.x += 45 + (id%3)*83 + id/6*83; pos.y += 109 + (id/3)*98; - icon = new CAnimImage("TWCRPORT", parent->army->getCreature(SlotID(id))->idNumber + 2); - new CLabel(28, 76,FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast(size));//stack size + icon = std::make_shared("TWCRPORT", parent->army->getCreature(SlotID(id))->idNumber + 2); + count = std::make_shared(28, 76,FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast(size)); } void CTransformerWindow::makeDeal() { - for (auto & elem : items) - if (!elem->left) + for(auto & elem : items) + { + if(!elem->left) LOCPLINT->cb->trade(town, EMarketMode::CREATURE_UNDEAD, elem->id, 0, 0, hero); + } } void CTransformerWindow::addAll() { - for (auto & elem : items) - if (elem->left) + for(auto & elem : items) + { + if(elem->left) elem->move(); + } showAll(screen2); } void CTransformerWindow::updateGarrisons() { for(auto & item : items) - { item->update(); - } } -CTransformerWindow::CTransformerWindow(const CGHeroInstance * _hero, const CGTownInstance * _town): - CWindowObject(PLAYER_COLORED, "SKTRNBK"), +CTransformerWindow::CTransformerWindow(const CGHeroInstance * _hero, const CGTownInstance * _town) + : CWindowObject(PLAYER_COLORED, "SKTRNBK"), hero(_hero), town(_town) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - if (hero) + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + if(hero) army = hero; else army = town; - for (int i=0; igetCreature(SlotID(i)) ) - items.push_back(new CItem(this, army->getStackCount(SlotID(i)), i)); + for(int i=0; igetCreature(SlotID(i))) + items.push_back(std::make_shared(this, army->getStackCount(SlotID(i)), i)); + } - all = new CButton(Point(146, 416), "ALTARMY.DEF", CGI->generaltexth->zelp[590], [&](){ addAll(); }, SDLK_a); - convert = new CButton(Point(269, 416), "ALTSACR.DEF", CGI->generaltexth->zelp[591], [&](){ makeDeal(); }, SDLK_RETURN); - cancel = new CButton(Point(392, 416), "ICANCEL.DEF", CGI->generaltexth->zelp[592], [&](){ close(); },SDLK_ESCAPE); - bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + all = std::make_shared(Point(146, 416), "ALTARMY.DEF", CGI->generaltexth->zelp[590], [&](){ addAll(); }, SDLK_a); + convert = std::make_shared(Point(269, 416), "ALTSACR.DEF", CGI->generaltexth->zelp[591], [&](){ makeDeal(); }, SDLK_RETURN); + cancel = std::make_shared(Point(392, 416), "ICANCEL.DEF", CGI->generaltexth->zelp[592], [&](){ close(); },SDLK_ESCAPE); + statusBar = std::make_shared(std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); - new CLabel(153, 29,FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[485]);//holding area - new CLabel(153+295, 29, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[486]);//transformer - new CTextBox(CGI->generaltexth->allTexts[487], Rect(26, 56, 255, 40), 0, FONT_MEDIUM, CENTER, Colors::YELLOW);//move creatures to create skeletons - new CTextBox(CGI->generaltexth->allTexts[488], Rect(320, 56, 255, 40), 0, FONT_MEDIUM, CENTER, Colors::YELLOW);//creatures here will become skeletons + titleLeft = std::make_shared(153, 29,FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[485]);//holding area + titleRight = std::make_shared(153+295, 29, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[486]);//transformer + helpLeft = std::make_shared(CGI->generaltexth->allTexts[487], Rect(26, 56, 255, 40), 0, FONT_MEDIUM, CENTER, Colors::YELLOW);//move creatures to create skeletons + helpRight = std::make_shared(CGI->generaltexth->allTexts[488], Rect(320, 56, 255, 40), 0, FONT_MEDIUM, CENTER, Colors::YELLOW);//creatures here will become skeletons +} +CUniversityWindow::CItem::CItem(CUniversityWindow * _parent, int _ID, int X, int Y) + : CIntObject(LCLICK | RCLICK | HOVER), + ID(_ID), + parent(_parent) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + pos.x += X; + pos.y += Y; + + topBar = std::make_shared(parent->bars, 0, 0, -28, -22); + bottomBar = std::make_shared(parent->bars, 0, 0, -28, 48); + + icon = std::make_shared("SECSKILL", _ID * 3 + 3, 0); + + name = std::make_shared(22, -13, FONT_SMALL, CENTER, Colors::WHITE, CGI->skillh->skillName(ID)); + level = std::make_shared(22, 57, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->levels[0]); + + pos.h = icon->pos.h; + pos.w = icon->pos.w; } void CUniversityWindow::CItem::clickLeft(tribool down, bool previousState) { if(previousState && (!down)) { - if ( state() != 2 ) - return; - auto win = new CUnivConfirmWindow(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000); - GH.pushInt(win); + if(state() == 2) + { + auto win = new CUnivConfirmWindow(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000); + GH.pushInt(win); + } } } @@ -1179,14 +1226,13 @@ void CUniversityWindow::CItem::clickRight(tribool down, bool previousState) { if(down) { - CRClickPopup::createAndPush(CGI->skillh->skillInfo(ID, 1), - new CComponent(CComponent::secskill, ID, 1)); + CRClickPopup::createAndPush(CGI->skillh->skillInfo(ID, 1), std::make_shared(CComponent::secskill, ID, 1)); } } void CUniversityWindow::CItem::hover(bool on) { - if (on) + if(on) GH.statusbar->setText(CGI->skillh->skillName(ID)); else GH.statusbar->clear(); @@ -1194,108 +1240,83 @@ void CUniversityWindow::CItem::hover(bool on) int CUniversityWindow::CItem::state() { - if (parent->hero->getSecSkillLevel(SecondarySkill(ID)))//hero know this skill + if(parent->hero->getSecSkillLevel(SecondarySkill(ID)))//hero know this skill return 1; - if (!parent->hero->canLearnSkill())//can't learn more skills + if(!parent->hero->canLearnSkill())//can't learn more skills return 0; - if (parent->hero->type->heroClass->secSkillProbability[ID]==0)//can't learn this skill (like necromancy for most of non-necros) + if(parent->hero->type->heroClass->secSkillProbability[ID]==0)//can't learn this skill (like necromancy for most of non-necros) return 0; return 2; } void CUniversityWindow::CItem::showAll(SDL_Surface * to) { - CPicture * bar; - switch (state()) - { - case 0: bar = parent->red; - break; - case 1: bar = parent->yellow; - break; - case 2: bar = parent->green; - break; - default:bar = nullptr; - break; - } - assert(bar); + //TODO: update when state actually changes + auto stateIndex = state(); + topBar->setFrame(stateIndex); + bottomBar->setFrame(stateIndex); - blitAtLoc(bar->bg, -28, -22, to); - blitAtLoc(bar->bg, -28, 48, to); - printAtMiddleLoc (CGI->skillh->skillName(ID), 22, -13, FONT_SMALL, Colors::WHITE,to);//Name - printAtMiddleLoc (CGI->generaltexth->levels[0], 22, 57, FONT_SMALL, Colors::WHITE,to);//Level(always basic) - - CAnimImage::showAll(to); + CIntObject::showAll(to); } -CUniversityWindow::CItem::CItem(CUniversityWindow * _parent, int _ID, int X, int Y): - CAnimImage ("SECSKILL", _ID*3+3, 0, X, Y), - ID(_ID), - parent(_parent) -{ - addUsedEvents(LCLICK | RCLICK | HOVER); -} - -CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market): - CWindowObject(PLAYER_COLORED, "UNIVERS1"), +CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market) + : CWindowObject(PLAYER_COLORED, "UNIVERS1"), hero(_hero), market(_market) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - green = new CPicture("UNIVGREN.PCX"); - yellow = new CPicture("UNIVGOLD.PCX");//bars - red = new CPicture("UNIVRED.PCX"); + bars = std::make_shared(); + bars->setCustom("UNIVRED", 0, 0); + bars->setCustom("UNIVGOLD", 1, 0); + bars->setCustom("UNIVGREN", 2, 0); + bars->preload(); - green->recActions = - yellow->recActions = - red->recActions = DISPOSE; - - CIntObject * titlePic = nullptr; - - if (market->o->ID == Obj::TOWN) - titlePic = new CAnimImage(CGI->townh->factions[ETownType::CONFLUX]->town->clientInfo.buildingsIcons, BuildingID::MAGIC_UNIVERSITY); + if(market->o->ID == Obj::TOWN) + titlePic = std::make_shared(CGI->townh->factions[ETownType::CONFLUX]->town->clientInfo.buildingsIcons, BuildingID::MAGIC_UNIVERSITY); else - titlePic = new CPicture("UNIVBLDG"); + titlePic = std::make_shared("UNIVBLDG"); titlePic->center(Point(232 + pos.x, 76 + pos.y)); - //Clerk speech - new CTextBox(CGI->generaltexth->allTexts[603], Rect(24, 129, 413, 70), 0, FONT_SMALL, CENTER, Colors::WHITE); + clerkSpeech = std::make_shared(CGI->generaltexth->allTexts[603], Rect(24, 129, 413, 70), 0, FONT_SMALL, CENTER, Colors::WHITE); + title = std::make_shared(231, 26, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[602]); - //University - new CLabel(231, 26, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[602]); + std::vector goods = market->availableItemsIds(EMarketMode::RESOURCE_SKILL); + assert(goods.size() == 4); - std::vector list = market->availableItemsIds(EMarketMode::RESOURCE_SKILL); + for(int i=0; i(this, goods[i], 54+i*104, 234)); - assert(list.size() == 4); - - for (int i=0; igeneraltexth->zelp[632], [&](){ close(); }, SDLK_RETURN); - - bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + cancel = std::make_shared(Point(200, 313), "IOKAY.DEF", CGI->generaltexth->zelp[632], [&](){ close(); }, SDLK_RETURN); + statusBar = std::make_shared(std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); } -CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bool available ): - CWindowObject(PLAYER_COLORED, "UNIVERS2.PCX"), - parent(PARENT) +void CUniversityWindow::makeDeal(int skill) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + LOCPLINT->cb->trade(market->o, EMarketMode::RESOURCE_SKILL, 6, skill, 1, hero); +} + + +CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * owner_, int SKILL, bool available) + : CWindowObject(PLAYER_COLORED, "UNIVERS2.PCX"), + owner(owner_) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); std::string text = CGI->generaltexth->allTexts[608]; boost::replace_first(text, "%s", CGI->generaltexth->levels[0]); boost::replace_first(text, "%s", CGI->skillh->skillName(SKILL)); boost::replace_first(text, "%d", "2000"); - new CTextBox(text, Rect(24, 129, 413, 70), 0, FONT_SMALL, CENTER, Colors::WHITE);//Clerk speech + clerkSpeech = std::make_shared(text, Rect(24, 129, 413, 70), 0, FONT_SMALL, CENTER, Colors::WHITE); - new CLabel(230, 37, FONT_SMALL, CENTER, Colors::WHITE, CGI->skillh->skillName(SKILL));//Skill name - new CAnimImage("SECSKILL", SKILL*3+3, 0, 211, 51);//skill - new CLabel(230, 107, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->levels[1]);//Skill level + name = std::make_shared(230, 37, FONT_SMALL, CENTER, Colors::WHITE, CGI->skillh->skillName(SKILL)); + icon = std::make_shared("SECSKILL", SKILL*3+3, 0, 211, 51); + level = std::make_shared(230, 107, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->levels[1]); - new CAnimImage("RESOURCE", Res::GOLD, 0, 210, 210);//gold - new CLabel(230, 267, FONT_SMALL, CENTER, Colors::WHITE, "2000");//Cost + costIcon = std::make_shared("RESOURCE", Res::GOLD, 0, 210, 210); + cost = std::make_shared(230, 267, FONT_SMALL, CENTER, Colors::WHITE, "2000"); std::string hoverText = CGI->generaltexth->allTexts[609]; boost::replace_first(hoverText, "%s", CGI->generaltexth->levels[0]+ " " + CGI->skillh->skillName(SKILL)); @@ -1305,57 +1326,98 @@ CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bo boost::replace_first(text, "%s", CGI->skillh->skillName(SKILL)); boost::replace_first(text, "%d", "2000"); - confirm= new CButton(Point(148, 299), "IBY6432.DEF", CButton::tooltip(hoverText, text), [=](){makeDeal(SKILL);}, SDLK_RETURN); + confirm = std::make_shared(Point(148, 299), "IBY6432.DEF", CButton::tooltip(hoverText, text), [=](){makeDeal(SKILL);}, SDLK_RETURN); confirm->block(!available); - cancel = new CButton(Point(252,299), "ICANCEL.DEF", CGI->generaltexth->zelp[631], [&](){ close(); }, SDLK_ESCAPE); - bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + cancel = std::make_shared(Point(252,299), "ICANCEL.DEF", CGI->generaltexth->zelp[631], [&](){ close(); }, SDLK_ESCAPE); + statusBar = std::make_shared(std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); } void CUnivConfirmWindow::makeDeal(int skill) { - LOCPLINT->cb->trade(parent->market->o, EMarketMode::RESOURCE_SKILL, 6, skill, 1, parent->hero); + owner->makeDeal(skill); close(); } -CHillFortWindow::CHillFortWindow(const CGHeroInstance *visitor, const CGObjectInstance *object): - CWindowObject(PLAYER_COLORED, "APHLFTBK"), +CGarrisonWindow::CGarrisonWindow(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits) + : CWindowObject(PLAYER_COLORED, "GARRISON") +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + garr = std::make_shared(92, 127, 4, Point(0,96), up, down, removableUnits); + { + auto split = std::make_shared(Point(88, 314), "IDV6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3], ""), [&](){ garr->splitClick(); } ); + garr->addSplitBtn(split); + } + quit = std::make_shared(Point(399, 314), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[8], ""), [&](){ close(); }, SDLK_RETURN); + + std::string titleText; + if(down->tempOwner == up->tempOwner) + { + titleText = CGI->generaltexth->allTexts[709]; + } + else + { + //assume that this is joining monsters dialog + if(up->Slots().size() > 0) + { + titleText = CGI->generaltexth->allTexts[35]; + boost::algorithm::replace_first(titleText, "%s", up->Slots().begin()->second->type->namePl); + } + else + { + logGlobal->error("Invalid armed instance for garrison window."); + } + } + title = std::make_shared(275, 30, FONT_BIG, CENTER, Colors::YELLOW, titleText); + + banner = std::make_shared("CREST58", up->getOwner().getNum(), 0, 28, 124); + portrait = std::make_shared("PortraitsLarge", down->portrait, 0, 29, 222); +} + +void CGarrisonWindow::updateGarrisons() +{ + garr->recreateSlots(); +} + +CHillFortWindow::CHillFortWindow(const CGHeroInstance * visitor, const CGObjectInstance * object) + : CWindowObject(PLAYER_COLORED, "APHLFTBK"), fort(object), hero(visitor) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - new CLabel(325, 32, FONT_BIG, CENTER, Colors::YELLOW, fort->getObjectName());//Hill Fort + title = std::make_shared(325, 32, FONT_BIG, CENTER, Colors::YELLOW, fort->getObjectName()); - heroPic = new CHeroArea(30, 60, hero); + heroPic = std::make_shared(30, 60, hero); - for (int i=0; i("SMALRES", i, 0, 104 + 76 * i, 237); + totalLabels[i] = std::make_shared(166 + 76 * i, 253, FONT_SMALL, BOTTOMRIGHT); } - for (int i = 0; i < slotsCount; i++) + for(int i = 0; i < slotsCount; i++) { - upgrade[i] = new CButton(Point(107 + i * 76, 171), "", CButton::tooltip(getTextForSlot(SlotID(i))), [=](){ makeDeal(SlotID(i)); }, SDLK_1 + i); - for (auto image : { "APHLF1R.DEF", "APHLF1Y.DEF", "APHLF1G.DEF" }) + upgrade[i] = std::make_shared(Point(107 + i * 76, 171), "", CButton::tooltip(getTextForSlot(SlotID(i))), [=](){ makeDeal(SlotID(i)); }, SDLK_1 + i); + for(auto image : { "APHLF1R.DEF", "APHLF1Y.DEF", "APHLF1G.DEF" }) upgrade[i]->addImage(image); for(int j : {0,1}) { - slotIcons[i][j] = new CAnimImage("SMALRES", 0, 0, 104 + 76 * i, 128 + 20 * j); - slotLabels[i][j] = new CLabel(168 + 76 * i, 144 + 20 * j, FONT_SMALL, BOTTOMRIGHT); + slotIcons[i][j] = std::make_shared("SMALRES", 0, 0, 104 + 76 * i, 128 + 20 * j); + slotLabels[i][j] = std::make_shared(168 + 76 * i, 144 + 20 * j, FONT_SMALL, BOTTOMRIGHT); } } - upgradeAll = new CButton(Point(30, 231), "", CButton::tooltip(CGI->generaltexth->allTexts[432]), [&](){ makeDeal(SlotID(slotsCount));}, SDLK_0); - for (auto image : { "APHLF4R.DEF", "APHLF4Y.DEF", "APHLF4G.DEF" }) + upgradeAll = std::make_shared(Point(30, 231), "", CButton::tooltip(CGI->generaltexth->allTexts[432]), [&](){ makeDeal(SlotID(slotsCount));}, SDLK_0); + for(auto image : { "APHLF4R.DEF", "APHLF4Y.DEF", "APHLF4G.DEF" }) upgradeAll->addImage(image); - quit = new CButton(Point(294, 275), "IOKAY.DEF", CButton::tooltip(), std::bind(&CHillFortWindow::close, this), SDLK_RETURN); - bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + quit = std::make_shared(Point(294, 275), "IOKAY.DEF", CButton::tooltip(), std::bind(&CHillFortWindow::close, this), SDLK_RETURN); + statusBar = std::make_shared(std::make_shared(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); - garr = new CGarrisonInt(108, 60, 18, Point(),background->bg,Point(108,60),hero,nullptr); + garr = std::make_shared(108, 60, 18, Point(), hero, nullptr); updateGarrisons(); } @@ -1366,18 +1428,18 @@ void CHillFortWindow::updateGarrisons() TResources totalSumm; // totalSum[resource ID] = value totalSumm.resize(GameConstants::RESOURCE_QUANTITY); - for (int i=0; icb->getUpgradeInfo(hero, SlotID(i), info); - if (info.newID.size())//we have upgrades here - update costs + if(info.newID.size())//we have upgrades here - update costs { costs[i] = info.cost[0] * hero->getStackCount(SlotID(i)); totalSumm += costs[i]; @@ -1396,10 +1458,10 @@ void CHillFortWindow::updateGarrisons() TResources myRes = LOCPLINT->cb->getResourceAmount(); bool allUpgraded = true;//All creatures are upgraded? - for (int i=0; isetIndex(newState); - CWindowWithGarrison::updateGarrisons(); + garr->recreateSlots(); - for (int i = 0; i < slotsCount; i++) + for(int i = 0; i < slotsCount; i++) { //hide all first for(int j : {0,1}) @@ -1420,9 +1482,9 @@ void CHillFortWindow::updateGarrisons() slotLabels[i][j]->setText(""); } //if can upgrade or can not afford, draw cost - if (currState[i] == 0 || currState[i] == 2) + if(currState[i] == 0 || currState[i] == 2) { - if (costs[i].nonZero()) + if(costs[i].nonZero()) { //reverse iterator is used to display gold as first element int j = 0; @@ -1448,7 +1510,7 @@ void CHillFortWindow::updateGarrisons() } } - for (int i = 0; i < resCount; i++) + for(int i = 0; i < resCount; i++) { if(totalSumm[i] == 0) { @@ -1467,37 +1529,36 @@ void CHillFortWindow::makeDeal(SlotID slot) { assert(slot.getNum()>=0); int offset = (slot.getNum() == slotsCount)?2:0; - switch (currState[slot.getNum()]) + switch(currState[slot.getNum()]) { case 0: - LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[314 + offset], - std::vector(), soundBase::sound_todo); + LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[314 + offset], std::vector>(), soundBase::sound_todo); break; case 1: - LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[313 + offset], - std::vector(), soundBase::sound_todo); + LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[313 + offset], std::vector>(), soundBase::sound_todo); break; case 2: - for (int i=0; icb->getUpgradeInfo(hero, SlotID(i), info); LOCPLINT->cb->upgradeCreature(hero, SlotID(i), info.newID[0]); } + } break; - } } std::string CHillFortWindow::getTextForSlot(SlotID slot) { - if ( !hero->getCreature(slot) )//we don`t have creature here + if(!hero->getCreature(slot))//we don`t have creature here return ""; std::string str = CGI->generaltexth->allTexts[318]; int amount = hero->getStackCount(slot); - if ( amount == 1 ) + if(amount == 1) boost::algorithm::replace_first(str,"%s",hero->getCreature(slot)->nameSing); else boost::algorithm::replace_first(str,"%s",hero->getCreature(slot)->namePl); @@ -1509,16 +1570,16 @@ int CHillFortWindow::getState(SlotID slot) { TResources myRes = LOCPLINT->cb->getResourceAmount(); - if (hero->slotEmpty(slot))//no creature here + if(hero->slotEmpty(slot))//no creature here return -1; UpgradeInfo info; LOCPLINT->cb->getUpgradeInfo(hero, slot, info); - if (!info.newID.size())//already upgraded + if(!info.newID.size())//already upgraded return 1; if(!(info.cost[0] * hero->getStackCount(slot)).canBeAfforded(myRes)) - return 0; + return 0; return 2;//can upgrade } @@ -1527,19 +1588,18 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner): CWindowObject(PLAYER_COLORED | BORDERED, "TpRank"), owner(_owner) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); type |= BLOCK_ADV_HOTKEYS; SThievesGuildInfo tgi; //info to be displayed LOCPLINT->cb->getThievesGuildInfo(tgi, owner); - exitb = new CButton (Point(748, 556), "TPMAGE1", CButton::tooltip(CGI->generaltexth->allTexts[600]), [&](){ close();}, SDLK_RETURN); + exitb = std::make_shared(Point(748, 556), "TPMAGE1", CButton::tooltip(CGI->generaltexth->allTexts[600]), [&](){ close();}, SDLK_RETURN); exitb->assignedKeys.insert(SDLK_ESCAPE); - statusBar = new CGStatusBar(3, 555, "TStatBar.bmp", 742); + statusBar = std::make_shared(3, 555, "TStatBar.bmp", 742); - resdatabar = new CMinorResDataBar(); - resdatabar->pos.x += pos.x; - resdatabar->pos.y += pos.y; + resdatabar = std::make_shared(); + resdatabar->moveBy(pos.topLeft(), true); //data for information table: // fields[row][column] = list of id's of players for this box @@ -1548,8 +1608,6 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner): &SThievesGuildInfo::woodOre, &SThievesGuildInfo::mercSulfCrystGems, &SThievesGuildInfo::obelisks, &SThievesGuildInfo::artifacts, &SThievesGuildInfo::army, &SThievesGuildInfo::income }; - //printing texts & descriptions to background - for(int g=0; g<12; ++g) { int posY[] = {400, 460, 510}; @@ -1561,14 +1619,20 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner): std::string text = CGI->generaltexth->jktexts[24+g]; boost::algorithm::trim_if(text,boost::algorithm::is_any_of("\"")); - new CLabel(135, y, FONT_MEDIUM, CENTER, Colors::YELLOW, text); + rowHeaders.push_back(std::make_shared(135, y, FONT_MEDIUM, CENTER, Colors::YELLOW, text)); } + auto PRSTRIPS = std::make_shared("PRSTRIPS"); + PRSTRIPS->preload(); + for(int g=1; g(PRSTRIPS, g-1, 0, 250 + 66*g, 7)); for(int g=0; ggeneraltexth->jktexts[16+g]); + columnHeaders.push_back(std::make_shared(283 + 66*g, 24, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[16+g])); + + auto itgflags = std::make_shared("itgflags"); + itgflags->preload(); //printing flags for(int g = 0; g < ARRAY_COUNT(fields); ++g) //by lines @@ -1585,17 +1649,15 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner): rowLength[0] = std::min(players.size(), 4); rowLength[1] = players.size() - rowLength[0]; - for (size_t j=0; j< 2; j++) + for(size_t j=0; j < 2; j++) { // origin of this row | offset for 2nd row| shift right for short rows //if we have 2 rows, start either from mid or beginning (depending on count), otherwise center the flags - int rowStartX = xpos + (j ? 6 + (rowLength[j] < 3 ? 12 : 0) : 24 - 6 * rowLength[j]); - int rowStartY = ypos + (j ? 4 : 0); + int rowStartX = xpos + (j ? 6 + (rowLength[j] < 3 ? 12 : 0) : 24 - 6 * rowLength[j]); + int rowStartY = ypos + (j ? 4 : 0); - for (size_t i=0; i< rowLength[j]; i++) - { - new CAnimImage("itgflags", players[i + j*4].getNum(), 0, rowStartX + i*12, rowStartY); - } + for(size_t i=0; i < rowLength[j]; i++) + cells.push_back(std::make_shared(itgflags, players[i + j*4].getNum(), 0, rowStartX + i*12, rowStartY)); } } } @@ -1606,21 +1668,22 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner): int counter = 0; for(auto & iter : tgi.colorToBestHero) { - new CPicture(colorToBox[iter.first.getNum()], 253 + 66 * counter, 334); + banners.push_back(std::make_shared(colorToBox[iter.first.getNum()], 253 + 66 * counter, 334)); if(iter.second.portrait >= 0) { - new CAnimImage("PortraitsSmall", iter.second.portrait, 0, 260 + 66 * counter, 360); + bestHeroes.push_back(std::make_shared("PortraitsSmall", iter.second.portrait, 0, 260 + 66 * counter, 360)); //TODO: r-click info: // - r-click on hero // - r-click on primary skill label if(iter.second.details) { - new CTextBox(CGI->generaltexth->allTexts[184], Rect(260 + 66*counter, 396, 52, 64), - 0, FONT_TINY, TOPLEFT, Colors::WHITE); - for (int i=0; iprimskills.size(); ++i) + primSkillHeaders.push_back(std::make_shared(CGI->generaltexth->allTexts[184], Rect(260 + 66*counter, 396, 52, 64), + 0, FONT_TINY, TOPLEFT, Colors::WHITE)); + + for(int i=0; iprimskills.size(); ++i) { - new CLabel(310 + 66 * counter, 407 + 11*i, FONT_TINY, BOTTOMRIGHT, Colors::WHITE, - boost::lexical_cast(iter.second.details->primskills[i])); + primSkillValues.push_back(std::make_shared(310 + 66 * counter, 407 + 11*i, FONT_TINY, BOTTOMRIGHT, Colors::WHITE, + boost::lexical_cast(iter.second.details->primskills[i]))); } } } @@ -1632,7 +1695,7 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner): for(auto & it : tgi.bestCreature) { if(it.second >= 0) - new CAnimImage("TWCRPORT", it.second+2, 0, 255 + 66 * counter, 479); + bestCreatures.push_back(std::make_shared("TWCRPORT", it.second+2, 0, 255 + 66 * counter, 479)); counter++; } @@ -1650,33 +1713,35 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner): text = CGI->generaltexth->arraytxt[168 + it.second]; } - new CLabel(283 + 66*counter, 459, FONT_SMALL, CENTER, Colors::WHITE, text); + personalities.push_back(std::make_shared(283 + 66*counter, 459, FONT_SMALL, CENTER, Colors::WHITE, text)); counter++; } } -CObjectListWindow::CItem::CItem(CObjectListWindow *_parent, size_t _id, std::string _text): +CObjectListWindow::CItem::CItem(CObjectListWindow * _parent, size_t _id, std::string _text) + : CIntObject(LCLICK), parent(_parent), index(_id) { - OBJ_CONSTRUCTION_CAPTURING_ALL; - border = new CPicture("TPGATES"); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + border = std::make_shared("TPGATES"); pos = border->pos; - addUsedEvents(LCLICK); + type |= REDRAW_PARENT; - text = new CLabel(pos.w/2, pos.h/2, FONT_SMALL, CENTER, Colors::WHITE, _text); + text = std::make_shared(pos.w/2, pos.h/2, FONT_SMALL, CENTER, Colors::WHITE, _text); select(index == parent->selected); } void CObjectListWindow::CItem::select(bool on) { - if (on) - border->recActions = 255; + ui8 mask = UPDATE | SHOWALL; + if(on) + border->recActions |= mask; else - border->recActions = ~(UPDATE | SHOWALL); - redraw(); + border->recActions &= ~mask; + redraw();//??? } void CObjectListWindow::CItem::clickLeft(tribool down, bool previousState) @@ -1685,63 +1750,63 @@ void CObjectListWindow::CItem::clickLeft(tribool down, bool previousState) parent->changeSelection(index); } -CObjectListWindow::CObjectListWindow(const std::vector &_items, CIntObject * titlePic, std::string _title, std::string _descr, - std::function Callback): - CWindowObject(PLAYER_COLORED, "TPGATE"), +CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback) + : CWindowObject(PLAYER_COLORED, "TPGATE"), onSelect(Callback), selected(0) { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); items.reserve(_items.size()); for(int id : _items) { items.push_back(std::make_pair(id, CGI->mh->map->objects[id]->getObjectName())); } - init(titlePic, _title, _descr); + init(titleWidget_, _title, _descr); } -CObjectListWindow::CObjectListWindow(const std::vector &_items, CIntObject * titlePic, std::string _title, std::string _descr, - std::function Callback): - CWindowObject(PLAYER_COLORED, "TPGATE"), +CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback) + : CWindowObject(PLAYER_COLORED, "TPGATE"), onSelect(Callback), selected(0) { + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); items.reserve(_items.size()); - for (size_t i=0; i<_items.size(); i++) + for(size_t i=0; i<_items.size(); i++) items.push_back(std::make_pair(int(i), _items[i])); - init(titlePic, _title, _descr); + init(titleWidget_, _title, _descr); } -void CObjectListWindow::init(CIntObject * titlePic, std::string _title, std::string _descr) +void CObjectListWindow::init(std::shared_ptr titleWidget_, std::string _title, std::string _descr) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + titleWidget = titleWidget_; - title = new CLabel(152, 27, FONT_BIG, CENTER, Colors::YELLOW, _title); - descr = new CLabel(145, 133, FONT_SMALL, CENTER, Colors::WHITE, _descr); + title = std::make_shared(152, 27, FONT_BIG, CENTER, Colors::YELLOW, _title); + descr = std::make_shared(145, 133, FONT_SMALL, CENTER, Colors::WHITE, _descr); - ok = new CButton(Point(15, 402), "IOKAY.DEF", CButton::tooltip(), std::bind(&CObjectListWindow::elementSelected, this), SDLK_RETURN); + ok = std::make_shared(Point(15, 402), "IOKAY.DEF", CButton::tooltip(), std::bind(&CObjectListWindow::elementSelected, this), SDLK_RETURN); ok->block(true); - exit = new CButton( Point(228, 402), "ICANCEL.DEF", CButton::tooltip(), std::bind(&CObjectListWindow::exitPressed, this), SDLK_ESCAPE); + exit = std::make_shared( Point(228, 402), "ICANCEL.DEF", CButton::tooltip(), std::bind(&CObjectListWindow::exitPressed, this), SDLK_ESCAPE); - if (titlePic) + if(titleWidget) { - addChild(titlePic); - titlePic->recActions = defActions; - titlePic->pos.x = pos.w/2 + pos.x - titlePic->pos.w/2; - titlePic->pos.y =75 + pos.y - titlePic->pos.h/2; + addChild(titleWidget.get()); + titleWidget->recActions = 255-DISPOSE; + titleWidget->pos.x = pos.w/2 + pos.x - titleWidget->pos.w/2; + titleWidget->pos.y =75 + pos.y - titleWidget->pos.h/2; } - list = new CListBox(std::bind(&CObjectListWindow::genItem, this, _1), CListBox::DestroyFunc(), + list = std::make_shared(std::bind(&CObjectListWindow::genItem, this, _1), Point(14, 151), Point(0, 25), 9, items.size(), 0, 1, Rect(262, -32, 256, 256) ); list->type |= REDRAW_PARENT; } -CIntObject * CObjectListWindow::genItem(size_t index) +std::shared_ptr CObjectListWindow::genItem(size_t index) { - if (index < items.size()) - return new CItem(this, index, items[index].second); - return nullptr; + if(index < items.size()) + return std::make_shared(this, index, items[index].second); + return std::shared_ptr(); } void CObjectListWindow::elementSelected() @@ -1763,18 +1828,18 @@ void CObjectListWindow::exitPressed() void CObjectListWindow::changeSelection(size_t which) { ok->block(false); - if (selected == which) + if(selected == which) return; - std::list< CIntObject * > elements = list->getItems(); - for(CIntObject * element : elements) + for(std::shared_ptr element : list->getItems()) { - CItem *item; - if ( (item = dynamic_cast(element)) ) + CItem * item = dynamic_cast(element.get()); + if(item) { - if (item->index == selected) + if(item->index == selected) item->select(false); - if (item->index == which) + + if(item->index == which) item->select(true); } } diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index 12bcf3fb8..064ecb9d5 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -33,53 +33,62 @@ class CToggleButton; class CToggleGroup; class CVolumeSlider; class CGStatusBar; +class CTextBox; +class CResDataBar; +class CHeroWithMaybePickedArtifact; /// Recruitment window where you can recruit creatures class CRecruitmentWindow : public CWindowObject { - class CCreatureCard : public CIntObject + class CCreatureCard : public CIntObject, public std::enable_shared_from_this { CRecruitmentWindow * parent; - CCreaturePic *pic; //creature's animation + std::shared_ptr animation; bool selected; - void clickLeft(tribool down, bool previousState) override; - void clickRight(tribool down, bool previousState) override; - void showAll(SDL_Surface *to) override; public: const CCreature * creature; si32 amount; void select(bool on); - CCreatureCard(CRecruitmentWindow * window, const CCreature *crea, int totalAmount); + CCreatureCard(CRecruitmentWindow * window, const CCreature * crea, int totalAmount); + + void clickLeft(tribool down, bool previousState) override; + void clickRight(tribool down, bool previousState) override; + void showAll(SDL_Surface * to) override; }; std::function onRecruit; //void (int ID, int amount) <-- call to recruit creatures int level; - const CArmedInstance *dst; + const CArmedInstance * dst; - CCreatureCard * selected; - std::vector cards; + std::shared_ptr statusBar; - CSlider *slider; //for selecting amount - CButton *maxButton, *buyButton, *cancelButton; - //labels for visible values - CLabel * title; - CLabel * availableValue; - CLabel * toRecruitValue; - CreatureCostBox * costPerTroopValue; - CreatureCostBox * totalCostValue; + std::shared_ptr selected; + std::vector> cards; - void select(CCreatureCard * card); + std::shared_ptr slider; + std::shared_ptr maxButton; + std::shared_ptr buyButton; + std::shared_ptr cancelButton; + std::shared_ptr title; + std::shared_ptr availableValue; + std::shared_ptr toRecruitValue; + std::shared_ptr availableTitle; + std::shared_ptr toRecruitTitle; + std::shared_ptr costPerTroopValue; + std::shared_ptr totalCostValue; + + void select(std::shared_ptr card); void buy(); void sliderMoved(int to); - void showAll(SDL_Surface *to) override; + void showAll(SDL_Surface * to) override; public: const CGDwelling * const dwelling; - CRecruitmentWindow(const CGDwelling *Dwelling, int Level, const CArmedInstance *Dst, const std::function & Recruit, int y_offset = 0); //creatures - pairs //c-tor + CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function & Recruit, int y_offset = 0); void availableCreaturesChanged(); }; @@ -92,12 +101,15 @@ class CSplitWindow : public CWindowObject int leftMin; int rightMin; + std::shared_ptr title; + std::shared_ptr slider; + std::shared_ptr animLeft; + std::shared_ptr animRight; + std::shared_ptr ok; + std::shared_ptr cancel; + std::shared_ptr leftInput; + std::shared_ptr rightInput; - CSlider *slider; - CCreaturePic *animLeft, *animRight; //creature's animation - CButton *ok, *cancel; - - CTextInput *leftInput, *rightInput; void setAmountText(std::string text, bool left); void setAmount(int value, bool left); void sliderMoved(int value); @@ -110,22 +122,27 @@ public: * leftMin, rightMin - minimal amount of creatures in each stack * leftAmount, rightAmount - amount of creatures in each stack */ - CSplitWindow(const CCreature * creature, std::function callback, - int leftMin, int rightMin, int leftAmount, int rightAmount); + CSplitWindow(const CCreature * creature, std::function callback, int leftMin, int rightMin, int leftAmount, int rightAmount); }; -/// Raised up level windowe where you can select one out of two skills +/// Raised up level window where you can select one out of two skills class CLevelWindow : public CWindowObject { - CComponentBox * box; //skills to select + std::shared_ptr portrait; + std::shared_ptr ok; + std::shared_ptr mainTitle; + std::shared_ptr levelTitle; + std::shared_ptr skillIcon; + std::shared_ptr skillValue; + + std::shared_ptr box; //skills to select std::function cb; void selectionChanged(unsigned to); -public: +public: CLevelWindow(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector &skills, std::function callback); ~CLevelWindow(); - }; /// Town portal, castle gate window @@ -133,27 +150,29 @@ class CObjectListWindow : public CWindowObject { class CItem : public CIntObject { - CObjectListWindow *parent; - CLabel *text; - CPicture *border; + CObjectListWindow * parent; + std::shared_ptr text; + std::shared_ptr border; public: const size_t index; - CItem(CObjectListWindow *parent, size_t id, std::string text); + CItem(CObjectListWindow * parent, size_t id, std::string text); void select(bool on); void clickLeft(tribool down, bool previousState) override; }; std::function onSelect;//called when OK button is pressed, returns id of selected item. - CLabel * title; - CLabel * descr; + std::shared_ptr titleWidget; + std::shared_ptr title; + std::shared_ptr descr; - CListBox * list; - CButton *ok, *exit; + std::shared_ptr list; + std::shared_ptr ok; + std::shared_ptr exit; std::vector< std::pair > items;//all items present in list - void init(CIntObject * titlePic, std::string _title, std::string _descr); + void init(std::shared_ptr titleWidget_, std::string _title, std::string _descr); void exitPressed(); public: size_t selected;//index of currently selected item @@ -163,13 +182,10 @@ public: /// Callback will be called when OK button is pressed, returns id of selected item. initState = initially selected item /// Image can be nullptr ///item names will be taken from map objects - CObjectListWindow(const std::vector &_items, CIntObject * titlePic, std::string _title, std::string _descr, - std::function Callback); + CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback); + CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback); - CObjectListWindow(const std::vector &_items, CIntObject * titlePic, std::string _title, std::string _descr, - std::function Callback); - - CIntObject *genItem(size_t index); + std::shared_ptr genItem(size_t index); void elementSelected();//call callback and close this window void changeSelection(size_t which); void keyPressed (const SDL_KeyboardEvent & key) override; @@ -178,23 +194,28 @@ public: class CSystemOptionsWindow : public CWindowObject { private: - CLabel *title; - CLabelGroup *leftGroup; - CLabelGroup *rightGroup; - CButton *load, *save, *restart, *mainMenu, *quitGame, *backToMap; //load and restart are not used yet - CToggleGroup * heroMoveSpeed; - CToggleGroup * enemyMoveSpeed; - CToggleGroup * mapScrollSpeed; - CVolumeSlider * musicVolume, * effectsVolume; + std::shared_ptr title; + std::shared_ptr leftGroup; + std::shared_ptr rightGroup; + std::shared_ptr load; + std::shared_ptr save; + std::shared_ptr restart; + std::shared_ptr mainMenu; + std::shared_ptr quitGame; + std::shared_ptr backToMap; //load and restart are not used yet + std::shared_ptr heroMoveSpeed; + std::shared_ptr enemyMoveSpeed; + std::shared_ptr mapScrollSpeed; + std::shared_ptr musicVolume; + std::shared_ptr effectsVolume; - //CHighlightableButton * showPath; - CToggleButton * showReminder; - CToggleButton * quickCombat; - CToggleButton * spellbookAnim; - CToggleButton * fullscreen; + std::shared_ptr showReminder; + std::shared_ptr quickCombat; + std::shared_ptr spellbookAnim; + std::shared_ptr fullscreen; - CButton *gameResButton; - CLabel *gameResLabel; + std::shared_ptr gameResButton; + std::shared_ptr gameResLabel; SettingsListener onFullscreenChanged; @@ -222,26 +243,39 @@ public: public: std::string hoverName; std::string description; // "XXX is a level Y ZZZ with N artifacts" - const CGHeroInstance *h; + const CGHeroInstance * h; void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; void hover (bool on) override; - HeroPortrait(int &sel, int id, int x, int y, const CGHeroInstance *H); + HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H); private: int *_sel; const int _id; - } *h1, *h2; //recruitable heroes + std::shared_ptr portrait; + }; + + //recruitable heroes + std::shared_ptr h1; + std::shared_ptr h2; //recruitable heroes int selected;//0 (left) or 1 (right) int oldSelected;//0 (left) or 1 (right) - CButton *thiefGuild, *cancel, *recruit; - const CGObjectInstance *tavernObj; + std::shared_ptr thiefGuild; + std::shared_ptr cancel; + std::shared_ptr recruit; - CTavernWindow(const CGObjectInstance *TavernObj); + const CGObjectInstance * tavernObj; + + std::shared_ptr title; + std::shared_ptr cost; + std::shared_ptr rumor; + std::shared_ptr statusBar; + + CTavernWindow(const CGObjectInstance * TavernObj); ~CTavernWindow(); void recruitb(); @@ -249,29 +283,47 @@ public: void show(SDL_Surface * to) override; }; -class CExchangeWindow : public CWindowObject, public CWindowWithGarrison, public CWindowWithArtifacts +class CExchangeWindow : public CWindowObject, public CGarrisonHolder, public CWindowWithArtifacts { - CGStatusBar * ourBar; //internal statusbar + std::array, 2> herosWArt; - CButton * quit, * questlogButton[2]; + std::array, 2> titles; + std::vector> primSkillImages;//shared for both heroes + std::array>, 2> primSkillValues; + std::array>, 2> secSkillIcons; + std::array, 2> specImages; + std::array, 2> expImages; + std::array, 2> expValues; + std::array, 2> manaImages; + std::array, 2> manaValues; + std::array, 2> portraits; - std::vector secSkillAreas[2], primSkillAreas; + std::vector> primSkillAreas; + std::array>, 2> secSkillAreas; - MoraleLuckBox *morale[2], *luck[2]; + std::array, 2> heroAreas; + std::array, 2> specialtyAreas; + std::array, 2> experienceAreas; + std::array, 2> spellPointsAreas; - LRClickableAreaWText *specialty[2]; - LRClickableAreaWText *experience[2]; - LRClickableAreaWText *spellPoints[2]; - CHeroArea *portrait[2]; + std::array, 2> morale; + std::array, 2> luck; + + std::shared_ptr quit; + std::array, 2> questlogButton; + + std::shared_ptr statusBar; + std::shared_ptr garr; public: + std::array heroInst; + std::array, 2> artifs; - const CGHeroInstance* heroInst[2]; - CArtifactsOfHero * artifs[2]; + void updateGarrisons() override; void questlog(int whichHero); //questlog button callback; whichHero: 0 - left, 1 - right - void prepareBackground(); //prepares or redraws bg + void updateWidgets(); CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID); ~CExchangeWindow(); @@ -280,22 +332,23 @@ public: /// Here you can buy ships class CShipyardWindow : public CWindowObject { + std::shared_ptr bgWater; + std::shared_ptr bgShip; + + std::shared_ptr title; + std::shared_ptr costLabel; + + std::shared_ptr woodPic; + std::shared_ptr goldPic; + std::shared_ptr woodCost; + std::shared_ptr goldCost; + + std::shared_ptr build; + std::shared_ptr quit; + + std::shared_ptr statusBar; public: - CGStatusBar *bar; - CPicture *bgWater; - - CLabel *title; - CLabel *costLabel; - - CAnimImage *woodPic, *goldPic; - CLabel *woodCost, *goldCost; - - CAnimImage *bgShip; - CButton *build, *quit; - - CGStatusBar * statusBar; - - CShipyardWindow(const std::vector &cost, int state, int boatType, const std::function &onBuy); + CShipyardWindow(const std::vector & cost, int state, int boatType, const std::function & onBuy); }; /// Puzzle screen which gets uncovered when you visit obilisks @@ -303,23 +356,25 @@ class CPuzzleWindow : public CWindowObject { private: int3 grailPos; + std::shared_ptr logo; + std::shared_ptr title; + std::shared_ptr quitb; + std::shared_ptr resDataBar; - CButton * quitb; - - std::vector piecesToRemove; + std::vector> piecesToRemove; + std::vector> visiblePieces; ui8 currentAlpha; public: void showAll(SDL_Surface * to) override; void show(SDL_Surface * to) override; - CPuzzleWindow(const int3 &grailPos, double discoveredRatio); + CPuzzleWindow(const int3 & grailPos, double discoveredRatio); }; /// Creature transformer window class CTransformerWindow : public CWindowObject, public CGarrisonHolder { -public: class CItem : public CIntObject { public: @@ -327,7 +382,8 @@ public: bool left;//position of the item int size; //size of creature stack CTransformerWindow * parent; - CAnimImage *icon; + std::shared_ptr icon; + std::shared_ptr count; void move(); void clickLeft(tribool down, bool previousState) override; @@ -335,13 +391,23 @@ public: CItem(CTransformerWindow * parent, int size, int id); }; - const CArmedInstance *army;//object with army for transforming (hero or town) - const CGHeroInstance *hero;//only if we have hero in town - const CGTownInstance *town;//market, town garrison is used if hero == nullptr - std::vector items; + const CArmedInstance * army;//object with army for transforming (hero or town) + const CGHeroInstance * hero;//only if we have hero in town + const CGTownInstance * town;//market, town garrison is used if hero == nullptr + + std::shared_ptr titleLeft; + std::shared_ptr titleRight; + std::shared_ptr helpLeft; + std::shared_ptr helpRight; + + std::vector> items; + + std::shared_ptr all; + std::shared_ptr convert; + std::shared_ptr cancel; + std::shared_ptr statusBar; +public: - CButton *all, *convert, *cancel; - CGStatusBar *bar; void makeDeal(); void addAll(); void updateGarrisons() override; @@ -350,8 +416,13 @@ public: class CUniversityWindow : public CWindowObject { - class CItem : public CAnimImage + class CItem : public CIntObject { + std::shared_ptr icon; + std::shared_ptr topBar; + std::shared_ptr bottomBar; + std::shared_ptr name; + std::shared_ptr level; public: int ID;//id of selected skill CUniversityWindow * parent; @@ -364,33 +435,66 @@ class CUniversityWindow : public CWindowObject CItem(CUniversityWindow * _parent, int _ID, int X, int Y); }; -public: - const CGHeroInstance *hero; + const CGHeroInstance * hero; const IMarket * market; - CPicture * green, * yellow, * red;//colored bars near skills - std::vector items; + std::shared_ptr bars; - CButton *cancel; - CGStatusBar *bar; + std::vector> items; + std::shared_ptr cancel; + std::shared_ptr statusBar; + std::shared_ptr titlePic; + std::shared_ptr title; + std::shared_ptr clerkSpeech; + +public: CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market); + + void makeDeal(int skill); }; /// Confirmation window for University class CUnivConfirmWindow : public CWindowObject { -public: - CUniversityWindow * parent; - CGStatusBar *bar; - CButton *confirm, *cancel; + std::shared_ptr clerkSpeech; + std::shared_ptr name; + std::shared_ptr level; + std::shared_ptr icon; + + CUniversityWindow * owner; + std::shared_ptr statusBar; + std::shared_ptr confirm; + std::shared_ptr cancel; + + std::shared_ptr costIcon; + std::shared_ptr cost; - CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bool available); void makeDeal(int skill); + +public: + CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bool available); +}; + +/// Garrison window where you can take creatures out of the hero to place it on the garrison +class CGarrisonWindow : public CWindowObject, public CGarrisonHolder +{ + std::shared_ptr title; + std::shared_ptr banner; + std::shared_ptr portrait; + + std::shared_ptr garr; + +public: + std::shared_ptr quit; + + CGarrisonWindow(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits); + + void updateGarrisons() override; }; /// Hill fort is the building where you can upgrade units -class CHillFortWindow : public CWindowObject, public CWindowWithGarrison +class CHillFortWindow : public CWindowObject, public CGarrisonHolder { private: static const int slotsCount = 7; @@ -400,23 +504,29 @@ private: const CGObjectInstance * fort; const CGHeroInstance * hero; - CGStatusBar * bar; - CHeroArea * heroPic;//clickable hero image - CButton * quit;//closes window - CButton * upgradeAll;//upgrade all creatures + std::shared_ptr title; + std::shared_ptr heroPic; - std::array upgrade;//upgrade single creature + std::array, resCount> totalIcons; + std::array, resCount> totalLabels; + + std::array, slotsCount> upgrade;//upgrade single creature std::array currState;//current state of slot - to avoid calls to getState or updating buttons //there is a place for only 2 resources per slot - std::array< std::array, slotsCount> slotIcons; - std::array< std::array, slotsCount> slotLabels; + std::array< std::array, 2>, slotsCount> slotIcons; + std::array< std::array, 2>, slotsCount> slotLabels; - std::array totalIcons; - std::array totalLabels; + std::shared_ptr upgradeAll; + std::shared_ptr quit; + + std::shared_ptr garr; + + std::shared_ptr statusBar; + + std::string getDefForSlot(SlotID slot); + std::string getTextForSlot(SlotID slot); - std::string getDefForSlot(SlotID slot);//return def name for this slot - std::string getTextForSlot(SlotID slot);//return hover text for this slot void makeDeal(SlotID slot);//-1 for upgrading all creatures int getState(SlotID slot); //-1 = no creature 0=can't upgrade, 1=upgraded, 2=can upgrade public: @@ -428,10 +538,22 @@ class CThievesGuildWindow : public CWindowObject { const CGObjectInstance * owner; - CGStatusBar * statusBar; - CButton * exitb; - CMinorResDataBar * resdatabar; + std::shared_ptr statusBar; + std::shared_ptr exitb; + std::shared_ptr resdatabar; + std::vector> rowHeaders; + std::vector> columnBackgrounds; + std::vector> columnHeaders; + std::vector> cells; + + std::vector> banners; + std::vector> bestHeroes; + std::vector> primSkillHeaders; + std::vector> primSkillValues; + std::vector> bestCreatures; + std::vector> personalities; public: CThievesGuildWindow(const CGObjectInstance * _owner); }; + diff --git a/client/windows/InfoWindows.cpp b/client/windows/InfoWindows.cpp index 48af4c4f7..9c1dae630 100644 --- a/client/windows/InfoWindows.cpp +++ b/client/windows/InfoWindows.cpp @@ -57,7 +57,7 @@ void CSelWindow::selectionChange(unsigned to) { for (unsigned i=0;i(components[i]); + auto pom = std::dynamic_pointer_cast(components[i]); if (!pom) continue; pom->select(i==to); @@ -65,19 +65,19 @@ void CSelWindow::selectionChange(unsigned to) redraw(); } -CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperline, const std::vector &comps, const std::vector > > &Buttons, QueryID askID) +CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperline, const std::vector> & comps, const std::vector > > &Buttons, QueryID askID) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); ID = askID; for (int i = 0; i < Buttons.size(); i++) { - buttons.push_back(new CButton(Point(0, 0), Buttons[i].first, CButton::tooltip(), Buttons[i].second)); + buttons.push_back(std::make_shared(Point(0, 0), Buttons[i].first, CButton::tooltip(), Buttons[i].second)); if (!i && askID.getNum() >= 0) buttons.back()->addCallback(std::bind(&CSelWindow::madeChoice, this)); buttons[i]->addCallback(std::bind(&CInfoWindow::close, this)); //each button will close the window apart from call-defined actions } - text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE); + text = std::make_shared(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE); buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape @@ -92,8 +92,8 @@ CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperl for(int i=0;irecActions = 255; - addChild(comps[i]); + comps[i]->recActions = 255-DISPOSE; + addChild(comps[i].get()); components.push_back(comps[i]); comps[i]->onSelect = std::bind(&CSelWindow::selectionChange,this,i); if(i<9) @@ -109,7 +109,7 @@ void CSelWindow::madeChoice() int ret = -1; for (int i=0;i(components[i])->selected) + if(std::dynamic_pointer_cast(components[i])->selected) { ret = i; } @@ -117,21 +117,21 @@ void CSelWindow::madeChoice() LOCPLINT->cb->selectionMade(ret+1,ID); } -CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps, const TButtonsInfo &Buttons, bool delComps) +CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo & comps, const TButtonsInfo & Buttons) { - OBJ_CONSTRUCTION_CAPTURING_ALL; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); type |= BLOCK_ADV_HOTKEYS; ID = QueryID(-1); for(auto & Button : Buttons) { - CButton *button = new CButton(Point(0,0), Button.first, CButton::tooltip(), std::bind(&CInfoWindow::close,this)); + std::shared_ptr button = std::make_shared(Point(0,0), Button.first, CButton::tooltip(), std::bind(&CInfoWindow::close, this)); button->setBorderColor(Colors::METALLIC_GOLD); button->addCallback(Button.second); //each button will close the window apart from call-defined actions buttons.push_back(button); } - text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE); + text = std::make_shared(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE); if(!text->slider) { text->resize(text->label->textSize); @@ -145,20 +145,18 @@ CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo for(auto & comp : comps) { - comp->recActions = 0xff; - addChild(comp); + comp->recActions = 0xff & ~DISPOSE; + addChild(comp.get()); comp->recActions &= ~(SHOWALL | UPDATE); components.push_back(comp); } - setDelComps(delComps); + CMessage::drawIWindow(this,Text,player); } CInfoWindow::CInfoWindow() { ID = QueryID(-1); - setDelComps(false); - text = nullptr; } void CInfoWindow::close() @@ -173,14 +171,7 @@ void CInfoWindow::show(SDL_Surface * to) CIntObject::show(to); } -CInfoWindow::~CInfoWindow() -{ - if(!delComps) - { - for (auto & elem : components) - removeChild(elem); - } -} +CInfoWindow::~CInfoWindow() = default; void CInfoWindow::showAll(SDL_Surface * to) { @@ -188,19 +179,19 @@ void CInfoWindow::showAll(SDL_Surface * to) CIntObject::showAll(to); } -void CInfoWindow::showInfoDialog(const std::string &text, const std::vector *components, bool DelComps, PlayerColor player) +void CInfoWindow::showInfoDialog(const std::string &text, const TCompsInfo & components, PlayerColor player) { - CInfoWindow * window = CInfoWindow::create(text, player, components, DelComps); + CInfoWindow * window = CInfoWindow::create(text, player, components); GH.pushInt(window); } -void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector *components, const CFunctionList &onYes, const CFunctionList &onNo, bool DelComps, PlayerColor player) +void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & components, const CFunctionList &onYes, const CFunctionList &onNo, PlayerColor player) { assert(!LOCPLINT || LOCPLINT->showingDialog->get()); std::vector > > pom; pom.push_back(std::pair >("IOKAY.DEF",0)); pom.push_back(std::pair >("ICANCEL.DEF",0)); - CInfoWindow * temp = new CInfoWindow(text, player, components ? *components : std::vector(), pom, DelComps); + CInfoWindow * temp = new CInfoWindow(text, player, components, pom); temp->buttons[0]->addCallback( onYes ); temp->buttons[1]->addCallback( onNo ); @@ -208,21 +199,21 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector *components, const std::function & onOk, bool delComps, PlayerColor player) +void CInfoWindow::showOkDialog(const std::string & text, const TCompsInfo & components, const std::function & onOk, PlayerColor player) { std::vector > > pom; pom.push_back(std::pair >("IOKAY.DEF",0)); - CInfoWindow * temp = new CInfoWindow(text, player, *components, pom, delComps); + CInfoWindow * temp = new CInfoWindow(text, player, components, pom); temp->buttons[0]->addCallback(onOk); GH.pushInt(temp); } -CInfoWindow * CInfoWindow::create(const std::string &text, PlayerColor playerID, const std::vector *components, bool DelComps) +CInfoWindow * CInfoWindow::create(const std::string &text, PlayerColor playerID, const TCompsInfo & components) { std::vector > > pom; pom.push_back(std::pair >("IOKAY.DEF",0)); - CInfoWindow * ret = new CInfoWindow(text, playerID, components ? *components : std::vector(), pom, DelComps); + CInfoWindow * ret = new CInfoWindow(text, playerID, components, pom); return ret; } @@ -231,18 +222,6 @@ std::string CInfoWindow::genText(std::string title, std::string description) return std::string("{") + title + "}" + "\n\n" + description; } -void CInfoWindow::setDelComps(bool DelComps) -{ - delComps = DelComps; - for(CComponent *comp : components) - { - if(delComps) - comp->recActions |= DISPOSE; - else - comp->recActions &= ~DISPOSE; - } -} - CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free) :free(Free),bitmap(Bitmap) { @@ -344,7 +323,7 @@ void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCom GH.pushInt(rcpi); } -void CRClickPopup::createAndPush(const std::string &txt, CComponent * component) +void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr component) { CInfoWindow::TCompsInfo intComps; intComps.push_back(component); @@ -408,47 +387,47 @@ Point CInfoBoxPopup::toScreen(Point p) return p; } -CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town): - CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position)) +CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town) + : CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position)) { InfoAboutTown iah; LOCPLINT->cb->getTownInfo(town, iah, adventureInt->selection); //todo: should this be nearest hero? - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CTownTooltip(Point(9, 10), iah); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + tooltip = std::make_shared(Point(9, 10), iah); } -CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero): - CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position)) +CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero) + : CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position)) { InfoAboutHero iah; LOCPLINT->cb->getHeroInfo(hero, iah, adventureInt->selection);//todo: should this be nearest hero? - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CHeroTooltip(Point(9, 10), iah); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + tooltip = std::make_shared(Point(9, 10), iah); } -CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr): - CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position)) +CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr) + : CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position)) { InfoAboutTown iah; LOCPLINT->cb->getTownInfo(garr, iah); - OBJ_CONSTRUCTION_CAPTURING_ALL; - new CArmyTooltip(Point(9, 10), iah); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + tooltip = std::make_shared(Point(9, 10), iah); } CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero { if(nullptr == specific) specific = adventureInt->selection; - + if(nullptr == specific) { logGlobal->error("createInfoWin: no object to describe"); return nullptr; - } - + } + switch(specific->ID) { case Obj::HERO: diff --git a/client/windows/InfoWindows.h b/client/windows/InfoWindows.h index 98de2b340..8640cf84d 100644 --- a/client/windows/InfoWindows.h +++ b/client/windows/InfoWindows.h @@ -10,7 +10,6 @@ #pragma once #include "CWindowObject.h" -//#include "../gui/SDL_Extensions.h" #include "../../lib/FunctionList.h" struct SDL_Surface; @@ -24,6 +23,7 @@ class CGGarrison; class CTextBox; class CButton; class CSlider; +class CArmyTooltip; // Window GUI class class CSimpleWindow : public CIntObject @@ -37,33 +37,30 @@ public: /// text + comp. + ok button class CInfoWindow : public CSimpleWindow -{ //window able to delete its components when closed - bool delComps; //whether comps will be deleted - +{ public: - typedef std::vector > > TButtonsInfo; - typedef std::vector TCompsInfo; + typedef std::vector > > TButtonsInfo; + typedef std::vector> TCompsInfo; QueryID ID; //for identification - CTextBox *text; - std::vector buttons; - std::vector components; + std::shared_ptr text; + std::vector> buttons; + TCompsInfo components; - void setDelComps(bool DelComps); virtual void close(); void show(SDL_Surface * to) override; void showAll(SDL_Surface * to) override; void sliderMoved(int to); - CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps = TCompsInfo(), const TButtonsInfo &Buttons = TButtonsInfo(), bool delComps = true); + CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo & comps = TCompsInfo(), const TButtonsInfo & Buttons = TButtonsInfo()); CInfoWindow(); ~CInfoWindow(); //use only before the game starts! (showYesNoDialog in LOCPLINT must be used then) - static void showInfoDialog( const std::string & text, const std::vector *components, bool DelComps = true, PlayerColor player = PlayerColor(1)); - static void showOkDialog(const std::string & text, const std::vector *components, const std::function & onOk, bool delComps = true, PlayerColor player = PlayerColor(1)); - static void showYesNoDialog( const std::string & text, const std::vector *components, const CFunctionList &onYes, const CFunctionList &onNo, bool DelComps = true, PlayerColor player = PlayerColor(1)); - static CInfoWindow *create(const std::string &text, PlayerColor playerID = PlayerColor(1), const std::vector *components = nullptr, bool DelComps = false); + static void showInfoDialog( const std::string & text, const TCompsInfo & components, PlayerColor player = PlayerColor(1)); + static void showOkDialog(const std::string & text, const TCompsInfo & components, const std::function & onOk, PlayerColor player = PlayerColor(1)); + static void showYesNoDialog( const std::string & text, const TCompsInfo & components, const CFunctionList & onYes, const CFunctionList & onNo, PlayerColor player = PlayerColor(1)); + static CInfoWindow * create(const std::string & text, PlayerColor playerID = PlayerColor(1), const TCompsInfo & components = TCompsInfo()); /// create text from title and description: {title}\n\n description static std::string genText(std::string title, std::string description); @@ -80,9 +77,9 @@ public: virtual ~CRClickPopup(); static CIntObject* createInfoWin(Point position, const CGObjectInstance * specific); - static void createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo()); - static void createAndPush(const std::string &txt, CComponent * component); - static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT); + static void createAndPush(const std::string & txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo()); + static void createAndPush(const std::string & txt, std::shared_ptr component); + static void createAndPush(const CGObjectInstance * obj, const Point & p, EAlignment alignment = BOTTOMRIGHT); }; /// popup displayed on R-click @@ -116,6 +113,7 @@ public: /// popup on adventure map for town\hero objects class CInfoBoxPopup : public CWindowObject { + std::shared_ptr tooltip; Point toScreen(Point pos); public: CInfoBoxPopup(Point position, const CGTownInstance * town); @@ -129,7 +127,7 @@ class CSelWindow : public CInfoWindow public: void selectionChange(unsigned to); void madeChoice(); //looks for selected component and calls callback - CSelWindow(const std::string& text, PlayerColor player, int charperline ,const std::vector &comps, const std::vector > > &Buttons, QueryID askID); + CSelWindow(const std::string & text, PlayerColor player, int charperline ,const std::vector> & comps, const std::vector > > &Buttons, QueryID askID); CSelWindow(){}; //notification - this class inherits important destructor from CInfoWindow }; diff --git a/lib/CGameInterface.h b/lib/CGameInterface.h index 7f071aa8f..00a860d75 100644 --- a/lib/CGameInterface.h +++ b/lib/CGameInterface.h @@ -23,7 +23,6 @@ class CBattleCallback; class ICallback; class CGlobalAI; struct Component; -class CSelectableComponent; struct TryMoveHero; class CGHeroInstance; class CGTownInstance; diff --git a/lib/IGameEventsReceiver.h b/lib/IGameEventsReceiver.h index bb319d5bb..a68d2d19a 100644 --- a/lib/IGameEventsReceiver.h +++ b/lib/IGameEventsReceiver.h @@ -99,7 +99,7 @@ public: virtual void heroMovePointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after movement virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){}; virtual void receivedResource(){}; - virtual void showInfoDialog(const std::string &text, const std::vector &components, int soundID){}; + virtual void showInfoDialog(const std::string & text, const std::vector & components, int soundID){}; virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level){} virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water