diff --git a/CCallback.cpp b/CCallback.cpp index c5b69f558..c35b83569 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -166,7 +166,7 @@ bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID) return true; } -int CBattleCallback::battleMakeAction(BattleAction* action) +int CBattleCallback::battleMakeAction(const BattleAction * action) { assert(action->actionType == EActionType::HERO_SPELL); MakeCustomAction mca(*action); diff --git a/CCallback.h b/CCallback.h index 96c7339ea..e5988eaf6 100644 --- a/CCallback.h +++ b/CCallback.h @@ -36,8 +36,8 @@ public: bool waitTillRealize; //if true, request functions will return after they are realized by server bool unlockGsWhenWaiting;//if true after sending each request, gs mutex will be unlocked so the changes can be applied; NOTICE caller must have gs mx locked prior to any call to actiob callback! //battle - virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack - virtual bool battleMakeTacticAction(BattleAction * action) =0; // performs tactic phase actions + virtual int battleMakeAction(const BattleAction * action) = 0;//for casting spells by hero - DO NOT use it for moving active stack + virtual bool battleMakeTacticAction(BattleAction * action) = 0; // performs tactic phase actions }; class IGameActionCallback @@ -88,7 +88,7 @@ protected: public: CBattleCallback(boost::optional Player, CClient *C); - int battleMakeAction(BattleAction* action) override;//for casting spells by hero - DO NOT use it for moving active stack + int battleMakeAction(const BattleAction * action) override;//for casting spells by hero - DO NOT use it for moving active stack bool battleMakeTacticAction(BattleAction * action) override; // performs tactic phase actions friend class CCallback; diff --git a/client/CBitmapHandler.cpp b/client/CBitmapHandler.cpp index acbd6a817..b92a97c39 100644 --- a/client/CBitmapHandler.cpp +++ b/client/CBitmapHandler.cpp @@ -57,7 +57,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size) if (format==PCX8B) { - ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0); + ret = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0); it = 0xC; for (int i=0; i(CGI)->setFromLib(); logGlobal->info("Initializing VCMI_Lib: %d ms", tmh.getDiff()); - - if(!settings["session"]["headless"].Bool()) - { - pomtime.getDiff(); - CCS->curh = new CCursorHandler(); - graphics = new Graphics(); // should be before curh->init() - - CCS->curh->initCursor(); - CCS->curh->show(); - logGlobal->info("Screen handler: %d ms", pomtime.getDiff()); - pomtime.getDiff(); - - graphics->load(); - logGlobal->info("\tMain graphics: %d ms", pomtime.getDiff()); - logGlobal->info("Initializing game graphics: %d ms", tmh.getDiff()); - - CMessage::init(); - logGlobal->info("Message handler: %d ms", tmh.getDiff()); - } } static void prog_version() @@ -466,8 +447,10 @@ int main(int argc, char * argv[]) playIntro(); SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 255); SDL_RenderClear(mainRenderer); + SDL_RenderPresent(mainRenderer); } - SDL_RenderPresent(mainRenderer); + + #ifndef VCMI_NO_THREADED_LOAD #ifdef VCMI_ANDROID // android loads the data quite slowly so we display native progressbar to prevent having only black screen for few seconds { @@ -480,6 +463,27 @@ int main(int argc, char * argv[]) } #endif // ANDROID #endif // THREADED + + if(!settings["session"]["headless"].Bool()) + { + pomtime.getDiff(); + CCS->curh = new CCursorHandler(); + graphics = new Graphics(); // should be before curh->init() + + CCS->curh->initCursor(); + logGlobal->info("Screen handler: %d ms", pomtime.getDiff()); + pomtime.getDiff(); + + graphics->load();//must be after Content loading but should be in main thread + logGlobal->info("Main graphics: %d ms", pomtime.getDiff()); + + CMessage::init(); + logGlobal->info("Message handler: %d ms", pomtime.getDiff()); + + CCS->curh->show(); + } + + logGlobal->info("Initialization of VCMI (together): %d ms", total.getDiff()); session["autoSkip"].Bool() = vm.count("autoSkip"); @@ -500,7 +504,7 @@ int main(int argc, char * argv[]) } else { - GH.curInt = CMainMenu::create(); + GH.curInt = CMainMenu::create().get(); } if(!settings["session"]["headless"].Bool()) @@ -786,9 +790,9 @@ void processCommand(const std::string &message) } else if(cn == "gui") { - for(const IShowActivatable *child : GH.listInt) + for(auto child : GH.listInt) { - if(const CIntObject *obj = dynamic_cast(child)) + if(const CIntObject *obj = dynamic_cast(child.get())) printInfoAboutIntObject(obj, 0); else std::cout << typeid(*child).name() << std::endl; @@ -970,9 +974,9 @@ void processCommand(const std::string &message) //plays intro, ends when intro is over or button has been pressed (handles events) void playIntro() { - if(CCS->videoh->openAndPlayVideo("3DOLOGO.SMK", 0, 1, screen, true, true)) + if(CCS->videoh->openAndPlayVideo("3DOLOGO.SMK", 0, 1, true, true)) { - CCS->videoh->openAndPlayVideo("AZVS.SMK", 0, 1, screen, true, true); + CCS->videoh->openAndPlayVideo("AZVS.SMK", 0, 1, true, true); } } @@ -1044,18 +1048,6 @@ static void cleanupRenderer() SDL_DestroyTexture(screenTexture); screenTexture = nullptr; } - - if(nullptr != mainRenderer) - { - SDL_DestroyRenderer(mainRenderer); - mainRenderer = nullptr; - } - - if(nullptr != mainWindow) - { - SDL_DestroyWindow(mainWindow); - mainWindow = nullptr; - } } static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIndex) @@ -1080,47 +1072,85 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn } bool bufOnScreen = (screenBuf == screen); + bool realFullscreen = settings["video"]["realFullscreen"].Bool(); cleanupRenderer(); - bool realFullscreen = settings["video"]["realFullscreen"].Bool(); - -#ifdef VCMI_ANDROID - mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN); -#else - - if(fullscreen) + if(nullptr == mainWindow) { - if(realFullscreen) - mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), w, h, SDL_WINDOW_FULLSCREEN); - else //in windowed full-screen mode use desktop resolution - mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + + #ifdef VCMI_ANDROID + mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN); + #else + + if(fullscreen) + { + if(realFullscreen) + mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), w, h, SDL_WINDOW_FULLSCREEN); + else //in windowed full-screen mode use desktop resolution + mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + } + else + { + mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex),SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), w, h, 0); + } + #endif + + if(nullptr == mainWindow) + { + throw std::runtime_error("Unable to create window\n"); + } + + //create first available renderer if preferred not set. Use no flags, so HW accelerated will be preferred but SW renderer also will possible + mainRenderer = SDL_CreateRenderer(mainWindow,preferredDriverIndex,0); + + if(nullptr == mainRenderer) + { + throw std::runtime_error("Unable to create renderer\n"); + } + + + SDL_RendererInfo info; + SDL_GetRendererInfo(mainRenderer, &info); + logGlobal->info("Created renderer %s", info.name); + } else { - mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex),SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), w, h, 0); - } +#ifndef VCMI_ANDROID + + if(fullscreen) + { + if(realFullscreen) + { + SDL_SetWindowFullscreen(mainWindow, SDL_WINDOW_FULLSCREEN); + + SDL_DisplayMode mode; + SDL_GetDesktopDisplayMode(displayIndex, &mode); + mode.w = w; + mode.h = h; + + SDL_SetWindowDisplayMode(mainWindow, &mode); + } + else + { + SDL_SetWindowFullscreen(mainWindow, SDL_WINDOW_FULLSCREEN_DESKTOP); + } + + SDL_SetWindowPosition(mainWindow, SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex)); + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + } + else + { + SDL_SetWindowFullscreen(mainWindow, 0); + SDL_SetWindowSize(mainWindow, w, h); + SDL_SetWindowPosition(mainWindow, SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex)); + } #endif - - if(nullptr == mainWindow) - { - throw std::runtime_error("Unable to create window\n"); } - - //create first available renderer if preferred not set. Use no flags, so HW accelerated will be preferred but SW renderer also will possible - mainRenderer = SDL_CreateRenderer(mainWindow,preferredDriverIndex,0); - - if(nullptr == mainRenderer) - { - throw std::runtime_error("Unable to create renderer\n"); - } - - SDL_RendererInfo info; - SDL_GetRendererInfo(mainRenderer, &info); - logGlobal->info("Created renderer %s", info.name); - if(!(fullscreen && realFullscreen)) { SDL_RenderSetLogicalSize(mainRenderer, w, h); @@ -1270,7 +1300,7 @@ static void handleEvent(SDL_Event & ev) }; if(epilogue.hasPrologEpilog) { - GH.pushInt(new CPrologEpilogVideo(epilogue, finisher)); + GH.pushIntT(epilogue, finisher); } else { @@ -1306,6 +1336,13 @@ static void handleEvent(SDL_Event & ev) } return; } + + //preprocessing + if(ev.type == SDL_MOUSEMOTION) + { + CCS->curh->cursorMove(ev.motion.x, ev.motion.y); + } + { boost::unique_lock lock(eventsM); events.push(ev); @@ -1349,6 +1386,19 @@ void handleQuit(bool ask) if(!settings["session"]["headless"].Bool()) { cleanupRenderer(); + + if(nullptr != mainRenderer) + { + SDL_DestroyRenderer(mainRenderer); + mainRenderer = nullptr; + } + + if(nullptr != mainWindow) + { + SDL_DestroyWindow(mainWindow); + mainWindow = nullptr; + } + SDL_Quit(); } diff --git a/client/CMessage.cpp b/client/CMessage.cpp index 7e6195da8..71f1df693 100644 --- a/client/CMessage.cpp +++ b/client/CMessage.cpp @@ -97,7 +97,7 @@ void CMessage::dispose() SDL_Surface * CMessage::drawDialogBox(int w, int h, PlayerColor playerColor) { //prepare surface - SDL_Surface * ret = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); + SDL_Surface * ret = SDL_CreateRGBSurface(0, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); for (int i=0; iw)//background { for (int j=0; jh) diff --git a/client/CMessage.h b/client/CMessage.h index 2e554ee2f..d407eadb2 100644 --- a/client/CMessage.h +++ b/client/CMessage.h @@ -19,16 +19,13 @@ class CComponent; /// Class which draws formatted text messages and generates chat windows class CMessage { -public: - //Function usd only in CMessage.cpp - static std::pair getMaxSizes(std::vector > * txtg, int fontHeight); - - /// Draw border on exiting surface - static void drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int h, int x=0, int y=0); - /// Draw simple dialog box (borders and background only) static SDL_Surface * drawDialogBox(int w, int h, PlayerColor playerColor = PlayerColor(1)); +public: + /// Draw border on exiting surface + static void drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int h, int x=0, int y=0); + static void drawIWindow(CInfoWindow * ret, std::string text, PlayerColor player); /// split text in lines diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 4cf3998d2..fe1224c7a 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -121,8 +121,8 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player) playerID=Player; human=true; currentSelection = nullptr; - castleInt = nullptr; battleInt = nullptr; + castleInt = nullptr; makingTurn = false; showingDialog = new CondSh(false); cingconsole = new CInGameConsole(); @@ -150,9 +150,7 @@ void CPlayerInterface::init(std::shared_ptr CB) initializeHeroTownList(); // always recreate advmap interface to avoid possible memory-corruption bugs - if (adventureInt) - delete adventureInt; - adventureInt = new CAdvMapInt(); + adventureInt.reset(new CAdvMapInt()); } void CPlayerInterface::yourTurn() { @@ -464,11 +462,13 @@ void CPlayerInterface::heroCreated(const CGHeroInstance * hero) } void CPlayerInterface::openTownWindow(const CGTownInstance * town) { - if (castleInt) + if(castleInt) castleInt->close(); + castleInt = nullptr; - castleInt = new CCastleInterface(town); - GH.pushInt(castleInt); + auto newCastleInt = std::make_shared(town); + + GH.pushInt(newCastleInt); } int3 CPlayerInterface::repairScreenPos(int3 pos) @@ -496,7 +496,7 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int EVENT_HANDLER_CALLED_BY_CLIENT; if (which == 4) { - if (CAltarWindow *ctw = dynamic_cast(GH.topInt())) + if (CAltarWindow *ctw = dynamic_cast(GH.topInt().get())) ctw->setExpToLevel(); } else if (which < GameConstants::PRIMARY_SKILLS) //no need to redraw infowin if this is experience (exp is treated as prim skill with id==4) @@ -506,7 +506,7 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int void CPlayerInterface::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) { EVENT_HANDLER_CALLED_BY_CLIENT; - CUniversityWindow* cuw = dynamic_cast(GH.topInt()); + CUniversityWindow* cuw = dynamic_cast(GH.topInt().get()); if (cuw) //university window is open { GH.totalRedraw(); @@ -529,7 +529,7 @@ void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero) void CPlayerInterface::receivedResource() { EVENT_HANDLER_CALLED_BY_CLIENT; - if (CMarketplaceWindow *mw = dynamic_cast(GH.topInt())) + if (CMarketplaceWindow *mw = dynamic_cast(GH.topInt().get())) mw->resourceChanged(); GH.totalRedraw(); @@ -540,21 +540,21 @@ void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, PrimarySkill::Pr EVENT_HANDLER_CALLED_BY_CLIENT; waitWhileDialog(); CCS->soundh->playSound(soundBase::heroNewLevel); - - CLevelWindow *lw = new CLevelWindow(hero,pskill,skills, - [=](ui32 selection){ cb->selectionMade(selection, queryID); }); - GH.pushInt(lw); + GH.pushIntT(hero, pskill, skills, [=](ui32 selection) + { + cb->selectionMade(selection, queryID); + }); } + void CPlayerInterface::commanderGotLevel (const CCommanderInstance * commander, std::vector skills, QueryID queryID) { EVENT_HANDLER_CALLED_BY_CLIENT; waitWhileDialog(); CCS->soundh->playSound(soundBase::heroNewLevel); - - GH.pushInt(new CStackWindow(commander, skills, [=](ui32 selection) + GH.pushIntT(commander, skills, [=](ui32 selection) { cb->selectionMade(selection, queryID); - })); + }); } void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town) @@ -578,17 +578,17 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town) adventureInt->heroList.update(); adventureInt->updateNextHero(nullptr); - if (CCastleInterface *c = castleInt) + if(castleInt) { - c->garr->selectSlot(nullptr); - c->garr->setArmy(town->getUpperArmy(), 0); - c->garr->setArmy(town->visitingHero, 1); - c->garr->recreateSlots(); - c->heroes->update(); + castleInt->garr->selectSlot(nullptr); + castleInt->garr->setArmy(town->getUpperArmy(), 0); + castleInt->garr->setArmy(town->visitingHero, 1); + castleInt->garr->recreateSlots(); + castleInt->heroes->update(); } - for (IShowActivatable *isa : GH.listInt) + for (auto isa : GH.listInt) { - CKingdomInterface *ki = dynamic_cast(isa); + CKingdomInterface *ki = dynamic_cast(isa.get()); if (ki) { ki->townChanged(town); @@ -632,11 +632,11 @@ void CPlayerInterface::garrisonsChanged(std::vector ob for (auto & elem : GH.listInt) { - CGarrisonHolder *cgh = dynamic_cast(elem); + CGarrisonHolder *cgh = dynamic_cast(elem.get()); if (cgh) cgh->updateGarrisons(); - if (CTradeWindow *cmw = dynamic_cast(elem)) + if (CTradeWindow *cmw = dynamic_cast(elem.get())) { if (vstd::contains(objs, cmw->hero)) cmw->garrisonChanged(); @@ -739,7 +739,7 @@ void CPlayerInterface::battleUnitsChanged(const std::vector & units continue; } - CCreatureAnimation * animation = iter->second; + auto animation = iter->second; if(unit->alive() && animation->isDead()) animation->setType(CCreatureAnim::HOLDING); @@ -905,8 +905,7 @@ void CPlayerInterface::battleEnd(const BattleResult *br) if (!battleInt) { - auto resWindow = new CBattleResultWindow(*br, *this); - GH.pushInt(resWindow); + GH.pushIntT(*br, *this); // #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. waitWhileDialog(); @@ -1129,7 +1128,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector { return; } - CInfoWindow *temp = CInfoWindow::create(text, playerID, components); + std::shared_ptr temp = CInfoWindow::create(text, playerID, components); if (makingTurn && GH.listInt.size() && LOCPLINT == this) { @@ -1164,22 +1163,6 @@ void CPlayerInterface::showYesNoDialog(const std::string &text, CFunctionList & components, const MetaString & text, const std::function & onOk) -{ - boost::unique_lock un(*pim); - - std::string str; - text.toString(str); - - stopMovement(); - showingDialog->setn(true); - - 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 ) { EVENT_HANDLER_CALLED_BY_CLIENT; @@ -1212,11 +1195,9 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v int charperline = 35; if (pom.size() > 1) charperline = 50; - auto temp = new CSelWindow(text, playerID, charperline, intComps, pom, askID); - GH.pushInt(temp); + GH.pushIntT(text, playerID, charperline, intComps, pom, askID); intComps[0]->clickLeft(true, false); } - } void CPlayerInterface::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) @@ -1256,13 +1237,12 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component for(auto item : objects) tempList.push_back(item.getNum()); - CComponent * localIconC = new CComponent(icon); + CComponent localIconC(icon); - std::shared_ptr localIcon = localIconC->image; - localIconC->removeChild(localIcon.get(), false); - delete localIconC; + std::shared_ptr localIcon = localIconC.image; + localIconC.removeChild(localIcon.get(), false); - CObjectListWindow * wnd = new CObjectListWindow(tempList, localIcon, localTitle, localDescription, selectCallback); + std::shared_ptr wnd = std::make_shared(tempList, localIcon, localTitle, localDescription, selectCallback); wnd->onExit = cancelCallback; GH.pushInt(wnd); } @@ -1289,7 +1269,7 @@ void CPlayerInterface::tileHidden(const std::unordered_set &pos void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero) { boost::unique_lock un(*pim); - GH.pushInt(new CHeroWindow(hero)); + GH.pushIntT(hero); } void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town ) @@ -1297,13 +1277,13 @@ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town ) EVENT_HANDLER_CALLED_BY_CLIENT; if (const CGTownInstance * townObj = dynamic_cast(town)) { - CFortScreen *fs = dynamic_cast(GH.topInt()); + CFortScreen *fs = dynamic_cast(GH.topInt().get()); if (fs) fs->creaturesChanged(); - for (IShowActivatable *isa : GH.listInt) + for(auto isa : GH.listInt) { - CKingdomInterface *ki = dynamic_cast(isa); + CKingdomInterface *ki = dynamic_cast(isa.get()); if (ki && townObj) ki->townChanged(townObj); } @@ -1311,7 +1291,7 @@ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town ) else if (GH.listInt.size() && (town->ID == Obj::CREATURE_GENERATOR1 || town->ID == Obj::CREATURE_GENERATOR4 || town->ID == Obj::WAR_MACHINE_FACTORY)) { - CRecruitmentWindow *crw = dynamic_cast(GH.topInt()); + CRecruitmentWindow *crw = dynamic_cast(GH.topInt().get()); if (crw && crw->dwelling == town) crw->availableCreaturesChanged(); } @@ -1434,7 +1414,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer waitForAllDialogs(); - auto cgw = new CGarrisonWindow(up,down,removableUnits); + auto cgw = std::make_shared(up, down, removableUnits); cgw->quit->addCallback(onEnd); GH.pushInt(cgw); } @@ -1497,7 +1477,7 @@ void CPlayerInterface::requestRealized( PackageApplied *pa ) void CPlayerInterface::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) { EVENT_HANDLER_CALLED_BY_CLIENT; - GH.pushInt(new CExchangeWindow(hero1, hero2, query)); + GH.pushIntT(hero1, hero2, query); } void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop) @@ -1551,9 +1531,11 @@ void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const C { EVENT_HANDLER_CALLED_BY_CLIENT; waitWhileDialog(); - auto recruitCb = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(dwelling, dst, id, count, -1); }; - CRecruitmentWindow *cr = new CRecruitmentWindow(dwelling, level, dst, recruitCb); - GH.pushInt(cr); + auto recruitCb = [=](CreatureID id, int count) + { + LOCPLINT->cb->recruitCreatures(dwelling, dst, id, count, -1); + }; + GH.pushIntT(dwelling, level, dst, recruitCb); } void CPlayerInterface::waitWhileDialog(bool unlockPim) @@ -1576,8 +1558,7 @@ void CPlayerInterface::showShipyardDialog(const IShipyard *obj) auto state = obj->shipyardStatus(); std::vector cost; obj->getBoatCost(cost); - CShipyardWindow *csw = new CShipyardWindow(cost, state, obj->getBoatType(), [=](){ cb->buildBoat(obj); }); - GH.pushInt(csw); + GH.pushIntT(cost, state, obj->getBoatType(), [=](){ cb->buildBoat(obj); }); } void CPlayerInterface::newObject( const CGObjectInstance * obj ) @@ -2159,7 +2140,7 @@ void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResul adventureInt->deactivate(); if (GH.topInt() == adventureInt) GH.popInt(adventureInt); - vstd::clear_pointer(adventureInt); + adventureInt.reset(); } } @@ -2201,7 +2182,7 @@ void CPlayerInterface::showPuzzleMap() double ratio = 0; int3 grailPos = cb->getGrailPos(&ratio); - GH.pushInt(new CPuzzleWindow(grailPos, ratio)); + GH.pushIntT(grailPos, ratio); } void CPlayerInterface::viewWorldMap() @@ -2213,8 +2194,8 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI { EVENT_HANDLER_CALLED_BY_CLIENT; - if(dynamic_cast(GH.topInt())) - GH.popIntTotally(GH.topInt()); + if(dynamic_cast(GH.topInt().get())) + GH.popInts(1); if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK) eraseCurrentPathOf(caster, false); @@ -2287,7 +2268,7 @@ void CPlayerInterface::acceptTurn() if (settings["session"]["autoSkip"].Bool()) { centerView = false; - while(CInfoWindow *iw = dynamic_cast(GH.topInt())) + while(CInfoWindow *iw = dynamic_cast(GH.topInt().get())) iw->close(); } waitWhileDialog(); @@ -2328,7 +2309,7 @@ void CPlayerInterface::acceptTurn() if(settings["session"]["autoSkip"].Bool() && !LOCPLINT->shiftPressed()) { - if(CInfoWindow *iw = dynamic_cast(GH.topInt())) + if(CInfoWindow *iw = dynamic_cast(GH.topInt().get())) iw->close(); adventureInt->fendTurn(); @@ -2425,54 +2406,51 @@ void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInsta { //EEMarketMode mode = market->availableModes().front(); if (market->allowsTrade(EMarketMode::ARTIFACT_EXP) && visitor->getAlignment() != EAlignment::EVIL) - GH.pushInt(new CAltarWindow(market, visitor, EMarketMode::ARTIFACT_EXP)); + GH.pushIntT(market, visitor, EMarketMode::ARTIFACT_EXP); else if (market->allowsTrade(EMarketMode::CREATURE_EXP) && visitor->getAlignment() != EAlignment::GOOD) - GH.pushInt(new CAltarWindow(market, visitor, EMarketMode::CREATURE_EXP)); + GH.pushIntT(market, visitor, EMarketMode::CREATURE_EXP); } else - GH.pushInt(new CMarketplaceWindow(market, visitor, market->availableModes().front())); + { + GH.pushIntT(market, visitor, market->availableModes().front()); + } } void CPlayerInterface::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) { EVENT_HANDLER_CALLED_BY_CLIENT; - auto cuw = new CUniversityWindow(visitor, market); - GH.pushInt(cuw); + GH.pushIntT(visitor, market); } void CPlayerInterface::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) { EVENT_HANDLER_CALLED_BY_CLIENT; - auto chfw = new CHillFortWindow(visitor, object); - GH.pushInt(chfw); + GH.pushIntT(visitor, object); } void CPlayerInterface::availableArtifactsChanged(const CGBlackMarket * bm) { EVENT_HANDLER_CALLED_BY_CLIENT; - if (CMarketplaceWindow *cmw = dynamic_cast(GH.topInt())) + if (CMarketplaceWindow *cmw = dynamic_cast(GH.topInt().get())) cmw->artifactsChanged(false); } void CPlayerInterface::showTavernWindow(const CGObjectInstance *townOrTavern) { EVENT_HANDLER_CALLED_BY_CLIENT; - auto tv = new CTavernWindow(townOrTavern); - GH.pushInt(tv); + GH.pushIntT(townOrTavern); } void CPlayerInterface::showThievesGuildWindow (const CGObjectInstance * obj) { EVENT_HANDLER_CALLED_BY_CLIENT; - auto tgw = new CThievesGuildWindow(obj); - GH.pushInt(tgw); + GH.pushIntT(obj); } void CPlayerInterface::showQuestLog() { EVENT_HANDLER_CALLED_BY_CLIENT; - CQuestLog * ql = new CQuestLog (LOCPLINT->cb->getMyQuests()); - GH.pushInt (ql); + GH.pushIntT(LOCPLINT->cb->getMyQuests()); } void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj) @@ -2529,9 +2507,9 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->infoBar.showSelection(); - for (IShowActivatable *isa : GH.listInt) + for(auto isa : GH.listInt) { - auto artWin = dynamic_cast(isa); + auto artWin = dynamic_cast(isa.get()); if (artWin) artWin->artifactRemoved(al); } @@ -2541,9 +2519,9 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->infoBar.showSelection(); - for (IShowActivatable *isa : GH.listInt) + for(auto isa : GH.listInt) { - auto artWin = dynamic_cast(isa); + auto artWin = dynamic_cast(isa.get()); if (artWin) artWin->artifactMoved(src, dst); } @@ -2554,9 +2532,9 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->infoBar.showSelection(); - for (IShowActivatable *isa : GH.listInt) + for(auto isa : GH.listInt) { - auto artWin = dynamic_cast(isa); + auto artWin = dynamic_cast(isa.get()); if (artWin) artWin->artifactAssembled(al); } @@ -2566,9 +2544,9 @@ void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->infoBar.showSelection(); - for (IShowActivatable *isa : GH.listInt) + for(auto isa : GH.listInt) { - auto artWin = dynamic_cast(isa); + auto artWin = dynamic_cast(isa.get()); if (artWin) artWin->artifactDisassembled(al); } @@ -2585,7 +2563,7 @@ void CPlayerInterface::playerStartsTurn(PlayerColor player) else { adventureInt->infoBar.showSelection(); - while (GH.listInt.front() != adventureInt && !dynamic_cast(GH.listInt.front())) //don't remove dialogs that expect query answer + while (GH.listInt.front() != adventureInt && !dynamic_cast(GH.listInt.front().get())) //don't remove dialogs that expect query answer GH.popInts(1); } @@ -2820,7 +2798,7 @@ void CPlayerInterface::updateAmbientSounds(bool resetAll) CCS->soundh->ambientStopAllChannels(); return; } - else if(!dynamic_cast(GH.topInt())) + else if(!dynamic_cast(GH.topInt().get())) { return; } diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index ff9c10405..b6d986022 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -82,7 +82,7 @@ public: std::shared_ptr cb; //to communicate with engine const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr) - std::list dialogs; //queue of dialogs awaiting to be shown (not currently shown!) + std::list> dialogs; //queue of dialogs awaiting to be shown (not currently shown!) std::vector wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones) std::vector towns; //our towns on the adventure map @@ -217,7 +217,6 @@ public: 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, const std::vector> & components = std::vector>()); void stopMovement(); diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index e5d792c91..440e6905c 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -494,12 +494,12 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart) { if(CMM) { - GH.curInt = CMM; + GH.curInt = CMM.get(); CMM->enable(); } else { - GH.curInt = CMainMenu::create(); + GH.curInt = CMainMenu::create().get(); } } } @@ -566,7 +566,7 @@ void CServerHandler::debugStartTest(std::string filename, bool save) else startLocalServerAndConnect(); - while(!settings["session"]["headless"].Bool() && !dynamic_cast(GH.topInt())) + while(!settings["session"]["headless"].Bool() && !dynamic_cast(GH.topInt().get())) boost::this_thread::sleep(boost::posix_time::milliseconds(50)); while(!mi || mapInfo->fileURI != CSH->mi->fileURI) { diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index bf7e65c2b..6f3fa8351 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -396,7 +396,7 @@ void CVideoPlayer::close() } // Plays a video. Only works for overlays. -bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey) +bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey) { // Note: either the windows player or the linux player is // broken. Compensate here until the bug is found. @@ -407,11 +407,10 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey) while(nextFrame()) { - if(stopOnKey && keyDown()) return false; - SDL_RenderCopy(mainRenderer, texture, NULL, &pos); + SDL_RenderCopy(mainRenderer, texture, nullptr, &pos); SDL_RenderPresent(mainRenderer); // Wait 3 frames @@ -423,10 +422,10 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey) return true; } -bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey, bool scale) +bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, bool stopOnKey, bool scale) { open(name, false, true, scale); - bool ret = playVideo(x, y, dst, stopOnKey); + bool ret = playVideo(x, y, stopOnKey); close(); return ret; } diff --git a/client/CVideoHandler.h b/client/CVideoHandler.h index 1fba6aca6..9f5fe10e1 100644 --- a/client/CVideoHandler.h +++ b/client/CVideoHandler.h @@ -31,7 +31,7 @@ public: std::string fname; //name of current video file (empty if idle) virtual void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true){} - virtual bool openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey = false, bool scale = false) + virtual bool openAndPlayVideo(std::string name, int x, int y, bool stopOnKey = false, bool scale = false) { return false; } @@ -111,7 +111,7 @@ class CVideoPlayer : public IMainVideoPlayer int refreshCount; bool doLoop; // loop through video - bool playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey); + bool playVideo(int x, int y, bool stopOnKey); bool open(std::string fname, bool loop, bool useOverlay = false, bool scale = false); public: @@ -128,7 +128,7 @@ public: void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true) override; //moves to next frame if appropriate, and blits it or blits only if redraw parameter is set true // Opens video, calls playVideo, closes video; returns playVideo result (if whole video has been played) - bool openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey = false, bool scale = false) override; + bool openAndPlayVideo(std::string name, int x, int y, bool stopOnKey = false, bool scale = false) override; //TODO: bool wait() override {return false;}; diff --git a/client/Client.cpp b/client/Client.cpp index 101e93ab6..19f25437e 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -491,14 +491,11 @@ void CClient::battleStarted(const BattleInfo * info) if(!settings["session"]["headless"].Bool()) { + Rect battleIntRect((screen->w - 800)/2, (screen->h - 600)/2, 800, 600); if(!!att || !!def) { boost::unique_lock un(*CPlayerInterface::pim); - auto bi = new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, - Rect((screen->w - 800)/2, - (screen->h - 600)/2, 800, 600), att, def); - - GH.pushInt(bi); + GH.pushIntT(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, battleIntRect, att, def); } else if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) { @@ -506,11 +503,7 @@ void CClient::battleStarted(const BattleInfo * info) auto spectratorInt = std::dynamic_pointer_cast(playerint[PlayerColor::SPECTATOR]); spectratorInt->cb->setBattle(info); boost::unique_lock un(*CPlayerInterface::pim); - auto bi = new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, - Rect((screen->w - 800) / 2, - (screen->h - 600) / 2, 800, 600), att, def, spectratorInt); - - GH.pushInt(bi); + GH.pushIntT(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, battleIntRect, att, def, spectratorInt); } } diff --git a/client/NetPacksLobbyClient.cpp b/client/NetPacksLobbyClient.cpp index bc7d1c82f..0e34d803c 100644 --- a/client/NetPacksLobbyClient.cpp +++ b/client/NetPacksLobbyClient.cpp @@ -35,7 +35,7 @@ bool LobbyClientConnected::applyOnLobbyHandler(CServerHandler * handler) { handler->c->connectionID = clientId; if(!settings["session"]["headless"].Bool()) - GH.pushInt(new CLobbyScreen(static_cast(handler->screenType))); + GH.pushIntT(static_cast(handler->screenType)); handler->state = EClientState::LOBBY; return true; } @@ -60,7 +60,7 @@ bool LobbyClientDisconnected::applyOnLobbyHandler(CServerHandler * handler) void LobbyClientDisconnected::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) { - GH.popIntTotally(lobby); + GH.popInts(1); } void LobbyChatMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) @@ -114,7 +114,7 @@ bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler) void LobbyStartGame::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) { - GH.pushInt(new CLoadingScreen(std::bind(&CServerHandler::startGameplay, handler))); + GH.pushIntT(std::bind(&CServerHandler::startGameplay, handler)); } bool LobbyUpdateState::applyOnLobbyHandler(CServerHandler * handler) @@ -128,7 +128,7 @@ void LobbyUpdateState::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * { if(!lobby->bonusSel && handler->si->campState && handler->state == EClientState::LOBBY_CAMPAIGN) { - lobby->bonusSel = new CBonusSelection(); + lobby->bonusSel = std::make_shared(); GH.pushInt(lobby->bonusSel); } diff --git a/client/battle/CBattleAnimations.cpp b/client/battle/CBattleAnimations.cpp index 7c2316016..24ab3c612 100644 --- a/client/battle/CBattleAnimations.cpp +++ b/client/battle/CBattleAnimations.cpp @@ -207,7 +207,7 @@ bool CDefenceAnimation::init() if (!rangedAttack && getMyAnimType() != CCreatureAnim::DEFENCE) { float frameLength = AnimationControls::getCreatureAnimationSpeed( - stack->getCreature(), owner->creAnims[stack->ID], getMyAnimType()); + stack->getCreature(), owner->creAnims[stack->ID].get(), getMyAnimType()); timeToWait = myAnim->framesInGroup(getMyAnimType()) * frameLength / 2; diff --git a/client/battle/CBattleAnimations.h b/client/battle/CBattleAnimations.h index af340ea25..25eda4a7c 100644 --- a/client/battle/CBattleAnimations.h +++ b/client/battle/CBattleAnimations.h @@ -39,7 +39,7 @@ public: class CBattleStackAnimation : public CBattleAnimation { public: - CCreatureAnimation * myAnim; //animation for our stack, managed by CBattleInterface + std::shared_ptr myAnim; //animation for our stack, managed by CBattleInterface const CStack * stack; //id of stack whose animation it is CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack); diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index 45d8dfe5a..b1f5121a6 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -47,7 +47,7 @@ CondSh CBattleInterface::animsAreDisplayed(false); CondSh CBattleInterface::givenCommand(nullptr); -static void onAnimationFinished(const CStack *stack, CCreatureAnimation *anim) +static void onAnimationFinished(const CStack *stack, std::shared_ptr anim) { if (anim->isIdle()) { @@ -92,36 +92,37 @@ void CBattleInterface::addNewAnim(CBattleAnimation *anim) } CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet *army2, - const CGHeroInstance *hero1, const CGHeroInstance *hero2, - const SDL_Rect & myRect, - std::shared_ptr att, std::shared_ptr defen, std::shared_ptr spectatorInt) - : background(nullptr), queue(nullptr), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), - activeStack(nullptr), mouseHoveredStack(nullptr), stackToActivate(nullptr), selectedStack(nullptr), previouslyHoveredHex(-1), - currentlyHoveredHex(-1), attackingHex(-1), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellToCast(nullptr), sp(nullptr), - creatureSpellToCast(-1), - siegeH(nullptr), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0), - myTurn(false), resWindow(nullptr), moveStarted(false), moveSoundHander(-1), bresult(nullptr) + const CGHeroInstance *hero1, const CGHeroInstance *hero2, + const SDL_Rect & myRect, + std::shared_ptr att, std::shared_ptr defen, std::shared_ptr spectatorInt) + : background(nullptr), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), + activeStack(nullptr), mouseHoveredStack(nullptr), stackToActivate(nullptr), selectedStack(nullptr), previouslyHoveredHex(-1), + currentlyHoveredHex(-1), attackingHex(-1), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellToCast(nullptr), sp(nullptr), + creatureSpellToCast(-1), + siegeH(nullptr), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0), + myTurn(false), moveStarted(false), moveSoundHander(-1), bresult(nullptr) { OBJ_CONSTRUCTION; if(spectatorInt) + { curInt = spectatorInt; + } else if(!curInt) { //May happen when we are defending during network MP game -> attacker interface is just not present curInt = defenderInt; } - animsAreDisplayed.setn(false); pos = myRect; strongInterest = true; givenCommand.setn(nullptr); //hot-seat -> check tactics for both players (defender may be local human) - if (attackerInt && attackerInt->cb->battleGetTacticDist()) + if(attackerInt && attackerInt->cb->battleGetTacticDist()) tacticianInterface = attackerInt; - else if (defenderInt && defenderInt->cb->battleGetTacticDist()) + else if(defenderInt && defenderInt->cb->battleGetTacticDist()) tacticianInterface = defenderInt; //if we found interface of player with tactics, then enter tactics mode @@ -138,7 +139,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet else embedQueue = screen->h < 700 || queueSize == "small"; - queue = new CStackQueue(embedQueue, this); + queue = std::make_shared(embedQueue, this); if(!embedQueue) { if (settings["battle"]["showQueue"].Bool()) @@ -150,24 +151,24 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet //preparing siege info const CGTownInstance *town = curInt->cb->battleGetDefendedTown(); - if (town && town->hasFort()) + if(town && town->hasFort()) { siegeH = new SiegeHelper(town, this); } - curInt->battleInt = this; + CPlayerInterface::battleInt = this; //initializing armies this->army1 = army1; this->army2 = army2; std::vector stacks = curInt->cb->battleGetAllStacks(true); - for (const CStack *s : stacks) + for(const CStack * s : stacks) { unitAdded(s); } //preparing menu background and terrain - if (siegeH) + if(siegeH) { background = BitmapHandler::loadBitmap( siegeH->getSiegeName(0), false ); ui8 siegeLevel = curInt->cb->battleGetSiegeLevel(); @@ -204,9 +205,6 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet } } - //preparing menu background - //graphics->blueToPlayersAdv(menu, hero1->tempOwner); - //preparing graphics for displaying amounts of creatures amountNormal = BitmapHandler::loadBitmap("CMNUMWIN.BMP"); CSDL_Ext::alphaTransform(amountNormal); @@ -224,77 +222,68 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet CSDL_Ext::alphaTransform(amountEffNeutral); transformPalette(amountEffNeutral, 1.00, 1.00, 0.18); - ////blitting menu background and terrain -// blitAt(background, pos.x, pos.y); -// blitAt(menu, pos.x, 556 + pos.y); - //preparing buttons and console - bOptions = new CButton (Point( 3, 561), "icm003.def", CGI->generaltexth->zelp[381], std::bind(&CBattleInterface::bOptionsf,this), SDLK_o); - bSurrender = new CButton (Point( 54, 561), "icm001.def", CGI->generaltexth->zelp[379], std::bind(&CBattleInterface::bSurrenderf,this), SDLK_s); - bFlee = new CButton (Point(105, 561), "icm002.def", CGI->generaltexth->zelp[380], std::bind(&CBattleInterface::bFleef,this), SDLK_r); - bAutofight = new CButton (Point(157, 561), "icm004.def", CGI->generaltexth->zelp[382], std::bind(&CBattleInterface::bAutofightf,this), SDLK_a); - bSpell = new CButton (Point(645, 561), "icm005.def", CGI->generaltexth->zelp[385], std::bind(&CBattleInterface::bSpellf,this), SDLK_c); - bWait = new CButton (Point(696, 561), "icm006.def", CGI->generaltexth->zelp[386], std::bind(&CBattleInterface::bWaitf,this), SDLK_w); - bDefence = new CButton (Point(747, 561), "icm007.def", CGI->generaltexth->zelp[387], std::bind(&CBattleInterface::bDefencef,this), SDLK_d); + bOptions = std::make_shared(Point( 3, 561), "icm003.def", CGI->generaltexth->zelp[381], std::bind(&CBattleInterface::bOptionsf,this), SDLK_o); + bSurrender = std::make_shared(Point( 54, 561), "icm001.def", CGI->generaltexth->zelp[379], std::bind(&CBattleInterface::bSurrenderf,this), SDLK_s); + bFlee = std::make_shared(Point(105, 561), "icm002.def", CGI->generaltexth->zelp[380], std::bind(&CBattleInterface::bFleef,this), SDLK_r); + bAutofight = std::make_shared(Point(157, 561), "icm004.def", CGI->generaltexth->zelp[382], std::bind(&CBattleInterface::bAutofightf,this), SDLK_a); + bSpell = std::make_shared(Point(645, 561), "icm005.def", CGI->generaltexth->zelp[385], std::bind(&CBattleInterface::bSpellf,this), SDLK_c); + bWait = std::make_shared(Point(696, 561), "icm006.def", CGI->generaltexth->zelp[386], std::bind(&CBattleInterface::bWaitf,this), SDLK_w); + bDefence = std::make_shared(Point(747, 561), "icm007.def", CGI->generaltexth->zelp[387], std::bind(&CBattleInterface::bDefencef,this), SDLK_d); bDefence->assignedKeys.insert(SDLK_SPACE); - bConsoleUp = new CButton (Point(624, 561), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleUpf,this), SDLK_UP); - bConsoleDown = new CButton (Point(624, 580), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleDownf,this), SDLK_DOWN); + bConsoleUp = std::make_shared(Point(624, 561), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleUpf,this), SDLK_UP); + bConsoleDown = std::make_shared(Point(624, 580), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleDownf,this), SDLK_DOWN); bConsoleDown->setImageOrder(2, 3, 4, 5); - console = new CBattleConsole(); + + console = std::make_shared(); console->pos.x += 211; console->pos.y += 560; console->pos.w = 406; console->pos.h = 38; - if (tacticsMode) + if(tacticsMode) { - btactNext = new CButton(Point(213, 560), "icm011.def", std::make_pair("", ""), [&](){ bTacticNextStack(nullptr);}, SDLK_SPACE); - btactEnd = new CButton(Point(419, 560), "icm012.def", std::make_pair("", ""), [&](){ bEndTacticPhase();}, SDLK_RETURN); + btactNext = std::make_shared(Point(213, 560), "icm011.def", std::make_pair("", ""), [&](){ bTacticNextStack(nullptr);}, SDLK_SPACE); + btactEnd = std::make_shared(Point(419, 560), "icm012.def", std::make_pair("", ""), [&](){ bEndTacticPhase();}, SDLK_RETURN); menu = BitmapHandler::loadBitmap("COPLACBR.BMP"); } else { menu = BitmapHandler::loadBitmap("CBAR.BMP"); - btactEnd = btactNext = nullptr; } graphics->blueToPlayersAdv(menu, curInt->playerID); //loading hero animations - if (hero1) // attacking hero + if(hero1) // attacking hero { std::string battleImage; - if ( hero1->sex ) + if(hero1->sex) battleImage = hero1->type->heroClass->imageBattleFemale; else battleImage = hero1->type->heroClass->imageBattleMale; - attackingHero = new CBattleHero(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, this); + attackingHero = std::make_shared(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, this); auto img = attackingHero->animation->getImage(0, 0, true); if(img) attackingHero->pos = genRect(img->height(), img->width(), pos.x - 43, pos.y - 19); } - else - { - attackingHero = nullptr; - } - if (hero2) // defending hero + + + if(hero2) // defending hero { std::string battleImage; - if ( hero2->sex ) + if(hero2->sex) battleImage = hero2->type->heroClass->imageBattleFemale; else battleImage = hero2->type->heroClass->imageBattleMale; - defendingHero = new CBattleHero(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, this); + defendingHero = std::make_shared(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, this); auto img = defendingHero->animation->getImage(0, 0, true); if(img) defendingHero->pos = genRect(img->height(), img->width(), pos.x + 693, pos.y - 19); } - else - { - defendingHero = nullptr; - } + //preparing cells and hexes cellBorder = BitmapHandler::loadBitmap("CCELLGRD.BMP"); @@ -303,7 +292,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet CSDL_Ext::alphaTransform(cellShade); for (int h = 0; h < GameConstants::BFIELD_SIZE; ++h) { - auto hex = new CClickableHex(); + auto hex = std::make_shared(); hex->myNumber = h; hex->pos = hexPosition(h); hex->accessible = true; @@ -385,8 +374,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet } } - for (auto hex : bfield) - addChild(hex); + for(auto hex : bfield) + addChild(hex.get()); if (tacticsMode) bTacticNextStack(); @@ -412,7 +401,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet CBattleInterface::~CBattleInterface() { - curInt->battleInt = nullptr; + CPlayerInterface::battleInt = nullptr; givenCommand.cond.notify_all(); //that two lines should make any activeStack waiting thread to finish if (active) //dirty fix for #485 @@ -427,31 +416,11 @@ CBattleInterface::~CBattleInterface() SDL_FreeSurface(amountEffNeutral); SDL_FreeSurface(cellBorders); SDL_FreeSurface(backgroundWithHexes); - delete bOptions; - delete bSurrender; - delete bFlee; - delete bAutofight; - delete bSpell; - delete bWait; - delete bDefence; - for (auto hex : bfield) - delete hex; - - delete bConsoleUp; - delete bConsoleDown; - delete console; - - delete attackingHero; - delete defendingHero; - delete queue; SDL_FreeSurface(cellBorder); SDL_FreeSurface(cellShade); - for (auto & elem : creAnims) - delete elem.second; - delete siegeH; //TODO: play AI tracks if battle was during AI turn @@ -588,7 +557,7 @@ void CBattleInterface::keyPressed(const SDL_KeyboardEvent & key) } void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent) { - auto hexItr = std::find_if (bfield.begin(), bfield.end(), [](const CClickableHex *hex) + auto hexItr = std::find_if(bfield.begin(), bfield.end(), [](std::shared_ptr hex) { return hex->hovered && hex->strictHovered; }); @@ -786,8 +755,7 @@ void CBattleInterface::bOptionsf() Rect tempRect = genRect(431, 481, 160, 84); tempRect += pos.topLeft(); - auto optionsWin = new CBattleOptionsWindow(tempRect, this); - GH.pushInt(optionsWin); + GH.pushIntT(tempRect, this); } void CBattleInterface::bSurrenderf() @@ -900,7 +868,7 @@ void CBattleInterface::bSpellf() if(spellCastProblem == ESpellCastProblem::OK) { - GH.pushInt(new CSpellWindow(myHero, curInt.get())); + GH.pushIntT(myHero, curInt.get()); } else if (spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED) { @@ -1276,13 +1244,13 @@ void CBattleInterface::displayBattleFinished() CCS->curh->changeGraphic(ECursor::ADVENTURE,0); if(settings["session"]["spectate"].Bool() && settings["session"]["spectate-skip-battle-result"].Bool()) { - GH.popIntTotally(this); + close(); return; } - resWindow = new CBattleResultWindow(*bresult, *this->curInt); - GH.pushInt(resWindow); + GH.pushInt(std::make_shared(*bresult, *(this->curInt))); curInt->waitWhileDialog(); // Avoid freeze when AI end turn after battle. Check bug #1897 + CPlayerInterface::battleInt = nullptr; } void CBattleInterface::spellCast(const BattleSpellCast * sc) @@ -1436,7 +1404,7 @@ void CBattleInterface::setHeroAnimation(ui8 side, int phase) void CBattleInterface::castThisSpell(SpellID spellID) { - spellToCast = new BattleAction(); + spellToCast = std::make_shared(); spellToCast->actionType = EActionType::HERO_SPELL; spellToCast->actionSubtype = spellID; //spell number spellToCast->stackNumber = (attackingHeroInstance->tempOwner == curInt->playerID) ? -1 : -2; @@ -1453,7 +1421,7 @@ void CBattleInterface::castThisSpell(SpellID spellID) if (spellSelMode == NO_LOCATION) //user does not have to select location { spellToCast->aimToHex(BattleHex::INVALID); - curInt->cb->battleMakeAction(spellToCast); + curInt->cb->battleMakeAction(spellToCast.get()); endCastingSpell(); } else @@ -1680,15 +1648,15 @@ void CBattleInterface::activateStack() void CBattleInterface::endCastingSpell() { - if (spellDestSelectMode) + if(spellDestSelectMode) { - vstd::clear_pointer(spellToCast); + spellToCast.reset(); sp = nullptr; spellDestSelectMode = false; CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER); - if (activeStack) + if(activeStack) { getPossibleActionsForStack(activeStack, false); //restore actions after they were cleared myTurn = true; @@ -1696,7 +1664,7 @@ void CBattleInterface::endCastingSpell() } else { - if (activeStack) + if(activeStack) { getPossibleActionsForStack(activeStack, false); GH.fakeMouseMove(); @@ -2419,7 +2387,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) { cursorFrame = ECursor::COMBAT_QUERY; consoleMsg = (boost::format(CGI->generaltexth->allTexts[297]) % shere->getName()).str(); - realizeAction = [=](){ GH.pushInt(new CStackWindow(shere, false)); }; + realizeAction = [=](){ GH.pushIntT(shere, false); }; break; } } @@ -2511,7 +2479,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) spellToCast->aimToHex(myNumber); break; } - curInt->cb->battleMakeAction(spellToCast); + curInt->cb->battleMakeAction(spellToCast.get()); endCastingSpell(); } selectedStack = nullptr; diff --git a/client/battle/CBattleInterface.h b/client/battle/CBattleInterface.h index 947a2f98c..dcabbee8c 100644 --- a/client/battle/CBattleInterface.h +++ b/client/battle/CBattleInterface.h @@ -106,7 +106,7 @@ struct CatapultProjectileInfo /// Big class which handles the overall battle interface actions and it is also responsible for /// drawing everything correctly. -class CBattleInterface : public CIntObject +class CBattleInterface : public WindowBase { enum PossibleActions // actions performed at l-click { @@ -121,14 +121,26 @@ class CBattleInterface : public CIntObject private: SDL_Surface *background, *menu, *amountNormal, *amountNegative, *amountPositive, *amountEffNeutral, *cellBorders, *backgroundWithHexes; - CButton *bOptions, *bSurrender, *bFlee, *bAutofight, *bSpell, - * bWait, *bDefence, *bConsoleUp, *bConsoleDown, *btactNext, *btactEnd; - CBattleConsole *console; - CBattleHero *attackingHero, *defendingHero; //fighting heroes - CStackQueue *queue; + std::shared_ptr bOptions; + std::shared_ptr bSurrender; + std::shared_ptr bFlee; + std::shared_ptr bAutofight; + std::shared_ptr bSpell; + std::shared_ptr bWait; + std::shared_ptr bDefence; + std::shared_ptr bConsoleUp; + std::shared_ptr bConsoleDown; + std::shared_ptr btactNext; + std::shared_ptr btactEnd; + + std::shared_ptr console; + std::shared_ptr attackingHero; + std::shared_ptr defendingHero; + std::shared_ptr queue; + const CCreatureSet *army1, *army2; //copy of initial armies (for result window) const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance; - std::map creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID) + std::map> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID) std::map> idToProjectile; @@ -154,7 +166,7 @@ private: bool stackCanCastSpell; //if true, active stack could possibly cast some target spell bool creatureCasting; //if true, stack currently aims to cats a spell bool spellDestSelectMode; //if true, player is choosing destination for his spell - only for GUI / console - BattleAction *spellToCast; //spell for which player is choosing destination + std::shared_ptr spellToCast; //spell for which player is choosing destination const CSpell *sp; //spell pointer for convenience si32 creatureSpellToCast; std::vector possibleActions; //all actions possible to call at the moment by player @@ -284,11 +296,10 @@ public: int getAnimSpeed() const; //speed of animation; range 1..100 CPlayerInterface *getCurrentPlayerInterface() const; - std::vector bfield; //11 lines, 17 hexes on each + std::vector> bfield; //11 lines, 17 hexes on each SDL_Surface *cellBorder, *cellShade; bool myTurn; //if true, interface is active (commands can be ordered) - CBattleResultWindow *resWindow; //window of end of battle bool moveStarted; //if true, the creature that is already moving is going to make its first step int moveSoundHander; // sound handler used when moving a unit diff --git a/client/battle/CBattleInterfaceClasses.cpp b/client/battle/CBattleInterfaceClasses.cpp index 21b64ae32..428c38b67 100644 --- a/client/battle/CBattleInterfaceClasses.cpp +++ b/client/battle/CBattleInterfaceClasses.cpp @@ -212,7 +212,7 @@ void CBattleHero::clickLeft(tribool down, bool previousState) } CCS->curh->changeGraphic(ECursor::ADVENTURE, 0); - GH.pushInt(new CSpellWindow(myHero, myOwner->getCurrentPlayerInterface())); + GH.pushIntT(myHero, myOwner->getCurrentPlayerInterface()); } } @@ -230,7 +230,7 @@ void CBattleHero::clickRight(tribool down, bool previousState) { auto h = flip ? myOwner->defendingHeroInstance : myOwner->attackingHeroInstance; targetHero.initFromHero(h, InfoAboutHero::EInfoLevel::INBATTLE); - GH.pushInt(new CHeroInfoWindow(targetHero, &windowPosition)); + GH.pushIntT(targetHero, &windowPosition); } } @@ -391,7 +391,7 @@ void CBattleOptionsWindow::bDefaultf() void CBattleOptionsWindow::bExitf() { - GH.popIntTotally(this); + close(); } CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterface & _owner) @@ -560,8 +560,10 @@ void CBattleResultWindow::show(SDL_Surface * to) void CBattleResultWindow::bExitf() { CPlayerInterface &intTmp = owner; //copy reference because "this" will be destructed soon - GH.popIntTotally(this); - if(dynamic_cast(GH.topInt())) + + close(); + + if(dynamic_cast(GH.topInt().get())) GH.popInts(1); //pop battle interface if present //Result window and battle interface are gone. We requested all dialogs to be closed before opening the battle, @@ -689,11 +691,10 @@ void CClickableHex::clickRight(tribool down, bool previousState) const CStack * myst = myInterface->getCurrentPlayerInterface()->cb->battleGetStackByPos(myNumber); //stack info if(hovered && strictHovered && myst!=nullptr) { - if(!myst->alive()) return; if(down) { - GH.pushInt(new CStackWindow(myst, true)); + GH.pushIntT(myst, true); } } } diff --git a/client/battle/CBattleInterfaceClasses.h b/client/battle/CBattleInterfaceClasses.h index cdb496502..079014ba7 100644 --- a/client/battle/CBattleInterfaceClasses.h +++ b/client/battle/CBattleInterfaceClasses.h @@ -89,7 +89,7 @@ public: }; /// Class which manages the battle options window -class CBattleOptionsWindow : public CIntObject +class CBattleOptionsWindow : public WindowBase { private: std::shared_ptr background; @@ -106,7 +106,7 @@ public: }; /// Class which is responsible for showing the battle result window -class CBattleResultWindow : public CIntObject +class CBattleResultWindow : public WindowBase { private: std::shared_ptr background; diff --git a/client/battle/CCreatureAnimation.cpp b/client/battle/CCreatureAnimation.cpp index 9700a90ba..7b86715d5 100644 --- a/client/battle/CCreatureAnimation.cpp +++ b/client/battle/CCreatureAnimation.cpp @@ -34,10 +34,10 @@ SDL_Color AnimationControls::getNoBorder() return creatureNoBorder; } -CCreatureAnimation * AnimationControls::getAnimation(const CCreature * creature) +std::shared_ptr AnimationControls::getAnimation(const CCreature * creature) { auto func = std::bind(&AnimationControls::getCreatureAnimationSpeed, creature, _1, _2); - return new CCreatureAnimation(creature->animDefName, func); + return std::make_shared(creature->animDefName, func); } float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, const CCreatureAnimation * anim, size_t group) diff --git a/client/battle/CCreatureAnimation.h b/client/battle/CCreatureAnimation.h index 86edc7b84..6d9bbcef6 100644 --- a/client/battle/CCreatureAnimation.h +++ b/client/battle/CCreatureAnimation.h @@ -25,7 +25,7 @@ namespace AnimationControls SDL_Color getNoBorder(); /// creates animation object with preset speed control - CCreatureAnimation * getAnimation(const CCreature * creature); + std::shared_ptr getAnimation(const CCreature * creature); /// returns animation speed of specific group, taking in mind game setting (in frames per second) float getCreatureAnimationSpeed(const CCreature * creature, const CCreatureAnimation * anim, size_t groupID); diff --git a/client/gui/CAnimation.cpp b/client/gui/CAnimation.cpp index 316a5ef56..2f6443e91 100644 --- a/client/gui/CAnimation.cpp +++ b/client/gui/CAnimation.cpp @@ -23,7 +23,6 @@ #include "../lib/CRandomGenerator.h" class SDLImageLoader; -class CompImageLoader; typedef std::map > source_map; typedef std::map image_map; @@ -79,9 +78,9 @@ public: public: //Load image from def file - SDLImage(CDefFile *data, size_t frame, size_t group=0, bool compressed=false); + SDLImage(CDefFile *data, size_t frame, size_t group=0); //Load from bitmap file - SDLImage(std::string filename, bool compressed=false); + SDLImage(std::string filename); SDLImage(const JsonNode & conf); //Create using existing surface, extraRef will increase refcount on SDL_Surface @@ -107,65 +106,6 @@ public: friend class SDLImageLoader; }; -/* - * RLE-compressed image data for 8-bit images with alpha-channel, currently far from finished - * primary purpose is not high compression ratio but fast drawing. - * Consist of repeatable segments with format similar to H3 def compression: - * 1st byte: - * if (byte == 0xff) - * raw data, opaque and semi-transparent data always in separate blocks - * else - * RLE-compressed image data with this color - * 2nd byte = size of segment - * raw data (if any) - */ -class CompImage : public IImage -{ - //x,y - margins, w,h - sprite size - Rect sprite; - //total size including borders - Point fullSize; - - //RLE-d data - ui8 * surf; - //array of offsets for each line - ui32 * line; - //palette - SDL_Color *palette; - - //Used internally to blit one block of data - template - void BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha) const; - void BlitBlockWithBpp(ui8 bpp, ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha, bool rotated) const; - -public: - //Load image from def file - CompImage(const CDefFile *data, size_t frame, size_t group=0); - //TODO: load image from SDL_Surface - CompImage(SDL_Surface * surf); - ~CompImage(); - - void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override; - void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override; - - std::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; - int width() const override; - int height() const override; - - void horizontalFlip() override; - void verticalFlip() override; - - void shiftPalette(int from, int howMany) override; - void setBorderPallete(const BorderPallete & borderPallete) override; - - friend class CompImageLoader; -}; - class SDLImageLoader { SDLImage * image; @@ -184,30 +124,6 @@ public: ~SDLImageLoader(); }; -class CompImageLoader -{ - CompImage * image; - ui8 *position; - ui8 *entry; - ui32 currentLine; - - inline ui8 typeOf(ui8 color); - inline void NewEntry(ui8 color, size_t size); - inline void NewEntry(const ui8 * &data, size_t size); - -public: - //load size raw pixels from data - inline void Load(size_t size, const ui8 * data); - //set size pixels to color - inline void Load(size_t size, ui8 color=0); - inline void EndLine(); - //init image with these sizes and palette - inline void init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal); - - CompImageLoader(CompImage * Img); - ~CompImageLoader(); -}; - // Extremely simple file cache. TODO: smarter, more general solution class CFileCache { @@ -576,7 +492,7 @@ SDLImageLoader::SDLImageLoader(SDLImage * Img): void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal) { //Init image - image->surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SpriteSize.x, SpriteSize.y, 8, 0, 0, 0, 0); + image->surf = SDL_CreateRGBSurface(0, SpriteSize.x, SpriteSize.y, 8, 0, 0, 0, 0); image->margins = Margins; image->fullSize = FullSize; @@ -621,182 +537,6 @@ SDLImageLoader::~SDLImageLoader() //TODO: RLE if compressed and bpp>1 } -//////////////////////////////////////////////////////////////////////////////// - -CompImageLoader::CompImageLoader(CompImage * Img): - image(Img), - position(nullptr), - entry(nullptr), - currentLine(0) -{ - -} - -void CompImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal) -{ - image->sprite = Rect(Margins, SpriteSize); - image->fullSize = FullSize; - if (SpriteSize.x && SpriteSize.y) - { - image->palette = new SDL_Color[256]; - memcpy((void*)image->palette, (void*)pal, 256*sizeof(SDL_Color)); - //Allocate enought space for worst possible case, c-style malloc used due to resizing after load - image->surf = (ui8*)malloc(SpriteSize.x*SpriteSize.y*3); - image->line = new ui32[SpriteSize.y+1]; - image->line[0] = 0; - position = image->surf; - } -} - -inline void CompImageLoader::NewEntry(ui8 color, size_t size) -{ - assert(color != 0xff); - assert(size && size<256); - entry = position; - entry[0] = color; - entry[1] = size; - position +=2; -} - -inline void CompImageLoader::NewEntry(const ui8 * &data, size_t size) -{ - assert(size && size<256); - entry = position; - entry[0] = 0xff; - entry[1] = size; - position +=2; - memcpy(position, data, size); - position+=size; - data+=size; -} - -inline ui8 CompImageLoader::typeOf(ui8 color) -{ - if (color == 0) - return 0; - - if (image->palette[color].a != 255) - return 1; - - return 2; -} - -inline void CompImageLoader::Load(size_t size, const ui8 * data) -{ - while (size) - { - //Try to compress data - while(true) - { - ui8 color = data[0]; - if (color != 0xff) - { - size_t runLength = 1; - while (runLength < size && color == data[runLength]) - runLength++; - - if (runLength > 1 && runLength < 255)//Row of one color found - use RLE - { - Load(runLength, color); - data += runLength; - size -= runLength; - if (!size) - return; - } - else - break; - } - else - break; - } - //Select length for new raw entry - size_t runLength = 1; - ui8 color = data[0]; - ui8 type = typeOf(color); - ui8 color2; - ui8 type2; - - if (size > 1) - { - do - { - color2 = data[runLength]; - type2 = typeOf(color2); - runLength++; - } - //While we have data of this type and different colors - while ((runLength < size) && (type == type2) && ( (color2 != 0xff) || (color2 != color))); - } - size -= runLength; - - //add data to last entry - if (entry && entry[0] == 0xff && type == typeOf(entry[2])) - { - size_t toCopy = std::min(runLength, 255 - entry[1]); - runLength -= toCopy; - entry[1] += toCopy; - memcpy(position, data, toCopy); - data+=toCopy; - position+=toCopy; - } - //Create new entries - while (runLength > 255) - { - NewEntry(data, 255); - runLength -= 255; - } - if (runLength) - NewEntry(data, runLength); - } -} - -inline void CompImageLoader::Load(size_t size, ui8 color) -{ - if (!size) - return; - if (color==0xff) - { - auto tmpbuf = new ui8[size]; - memset((void*)tmpbuf, color, size); - Load(size, tmpbuf); - delete [] tmpbuf; - return; - } - //Current entry is RLE with same color as new block - if (entry && entry[0] == color) - { - size_t toCopy = std::min(size, 255 - entry[1]); - size -= toCopy; - entry[1] += toCopy; - } - //Create new entries - while (size > 255) - { - NewEntry(color, 255); - size -= 255; - } - if (size) - NewEntry(color, size); -} - -void CompImageLoader::EndLine() -{ - currentLine++; - image->line[currentLine] = position - image->surf; - entry = nullptr; - -} - -CompImageLoader::~CompImageLoader() -{ - if (!image->surf) - return; - - ui8* newPtr = (ui8*)realloc((void*)image->surf, position - image->surf); - if (newPtr) - image->surf = newPtr; -} - /************************************************************************* * Classes for images, support loading from file and drawing on surface * *************************************************************************/ @@ -805,7 +545,7 @@ IImage::IImage() = default; IImage::~IImage() = default; -SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group, bool compressed) +SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group) : surf(nullptr), margins(0, 0), fullSize(0, 0) @@ -857,15 +597,14 @@ SDLImage::SDLImage(const JsonNode & conf) } } - -SDLImage::SDLImage(std::string filename, bool compressed) +SDLImage::SDLImage(std::string filename) : surf(nullptr), margins(0, 0), fullSize(0, 0) { surf = BitmapHandler::loadBitmap(filename); - if (surf == nullptr) + if(surf == nullptr) { logGlobal->error("Error: failed to load image %s", filename); return; @@ -875,23 +614,8 @@ SDLImage::SDLImage(std::string filename, bool compressed) fullSize.x = surf->w; fullSize.y = surf->h; } - if (compressed) - { - SDL_Surface *temp = surf; - // add RLE flag - if (surf->format->palette) - { - CSDL_Ext::setColorKey(temp,temp->format->palette->colors[0]); - } - SDL_SetSurfaceRLE(temp, SDL_RLEACCEL); - - // convert surface to enable RLE - surf = SDL_ConvertSurface(temp, temp->format, temp->flags); - SDL_FreeSurface(temp); - } } - void SDLImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alpha) const { if(!surf) @@ -1042,282 +766,6 @@ SDLImage::~SDLImage() SDL_FreeSurface(surf); } -CompImage::CompImage(const CDefFile *data, size_t frame, size_t group): - surf(nullptr), - line(nullptr), - palette(nullptr) - -{ - CompImageLoader loader(this); - data->loadFrame(frame, group, loader); -} - -CompImage::CompImage(SDL_Surface * surf) -{ - //TODO - assert(0); -} - -void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alpha) const -{ - Rect dest(posX,posY, width(), height()); - draw(where, &dest, src, alpha); -} - -void CompImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alpha) const -{ - int rotation = 0; //TODO - //rotation & 2 = horizontal rotation - //rotation & 4 = vertical rotation - if (!surf) - return; - Rect sourceRect(sprite); - //TODO: rotation and scaling - if (src) - sourceRect = sourceRect & *src; - //Limit source rect to sizes of surface - sourceRect = sourceRect & Rect(0, 0, where->w, where->h); - - //Starting point on SDL surface - Point dst(sourceRect.x,sourceRect.y); - - if (dest) - { - dst.x += dest->x; - dst.y += dest->y; - } - - if (rotation & 2) - dst.y += sourceRect.h; - if (rotation & 4) - dst.x += sourceRect.w; - - sourceRect -= sprite.topLeft(); - - for (int currY = 0; currY size ) - { - currX -= size; - if (type == 0xff) - data += size; - type = *(data++); - size = *(data++); - } - //This block will be shown partially - calculate size\position - size -= currX; - if (type == 0xff) - data += currX; - - currX = 0; - ui8 bpp = where->format->BytesPerPixel; - - //Calculate position for blitting: pixels + Y + X - ui8* blitPos = (ui8*) where->pixels; - if (rotation & 4) - blitPos += (dst.y - currY) * where->pitch; - else - blitPos += (dst.y + currY) * where->pitch; - blitPos += dst.x * bpp; - - //Blit blocks that must be fully visible - while (currX + size < sourceRect.w) - { - //blit block, pointers will be modified if needed - BlitBlockWithBpp(bpp, type, size, data, blitPos, alpha, rotation & 2); - - currX += size; - type = *(data++); - size = *(data++); - } - //Blit last, semi-visible block - size = sourceRect.w - currX; - BlitBlockWithBpp(bpp, type, size, data, blitPos, alpha, rotation & 2); - } -} - - -std::shared_ptr CompImage::scaleFast(float scale) const -{ - //todo: CompImage::scaleFast - - logAnim->error("CompImage::scaleFast is not implemented"); - - return nullptr; -} - -#define CASEBPP(x,y) case x: BlitBlock(type, size, data, dest, alpha); break - -//FIXME: better way to get blitter -void CompImage::BlitBlockWithBpp(ui8 bpp, ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha, bool rotated) const -{ - assert(bpp>1 && bpp<5); - - if (rotated) - switch (bpp) - { - CASEBPP(2,1); - CASEBPP(3,1); - CASEBPP(4,1); - } - else - switch (bpp) - { - CASEBPP(2,1); - CASEBPP(3,1); - CASEBPP(4,1); - } -} -#undef CASEBPP - -//Blit one block from RLE-d surface -template -void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha) const -{ - //Raw data - if (type == 0xff) - { - ui8 color = *data; - if (alpha != 255)//Per-surface alpha is set - { - for (size_t i=0; i::PutColorAlpha(dest, col); - } - return; - } - - if (palette[color].a == 255) - { - //Put row of RGB data - for (size_t i=0; i::PutColor(dest, palette[*(data++)]); - } - else - { - //Put row of RGBA data - for (size_t i=0; i::PutColorAlpha(dest, palette[*(data++)]); - - } - } - //RLE-d sequence - else - { - if (alpha != 255 && palette[type].a !=0)//Per-surface alpha is set - { - SDL_Color col = palette[type]; - col.a = (int)col.a*(255-alpha)/255; - for (size_t i=0; i::PutColorAlpha(dest, col); - return; - } - - switch (palette[type].a) - { - case 0: - { - //Skip row - dest += size*bpp; - break; - } - case 255: - { - //Put RGB row - ColorPutter::PutColorRow(dest, palette[type], size); - break; - } - default: - { - //Put RGBA row - for (size_t i=0; i::PutColorAlpha(dest, palette[type]); - break; - } - } - } -} - -void CompImage::playerColored(PlayerColor player) -{ - SDL_Color *pal = nullptr; - if(player < PlayerColor::PLAYER_LIMIT) - { - pal = graphics->playerColorPalette + 32*player.getNum(); - } - else if(player == PlayerColor::NEUTRAL) - { - pal = graphics->neutralColorPalette; - } - else - assert(0); - - for(int i=0; i<32; ++i) - { - CSDL_Ext::colorAssign(palette[224+i],pal[i]); - } -} - -void CompImage::setFlagColor(PlayerColor player) -{ - logAnim->error("CompImage::setFlagColor is not implemented"); -} - -int CompImage::width() const -{ - return fullSize.x; -} - -int CompImage::height() const -{ - return fullSize.y; -} - -CompImage::~CompImage() -{ - free(surf); - delete [] line; - delete [] palette; -} - -void CompImage::horizontalFlip() -{ - logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION); -} - -void CompImage::verticalFlip() -{ - logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION); -} - -void CompImage::shiftPalette(int from, int howMany) -{ - logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION); -} - -void CompImage::setBorderPallete(const IImage::BorderPallete & borderPallete) -{ - logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION); -} - -void CompImage::exportBitmap(const boost::filesystem::path & path) const -{ - logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION); -} - - -/************************************************************************* - * CAnimation for animations handling, can load part of file if needed * - *************************************************************************/ - std::shared_ptr CAnimation::getFromExtraDef(std::string filename) { size_t pos = filename.find(':'); @@ -1363,17 +811,14 @@ 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] = std::make_shared(defFile, frame, group); - else - images[group][frame] = std::make_shared(defFile, frame, group); + images[group][frame] = std::make_shared(defFile.get(), frame, group); return true; } } // still here? image is missing printError(frame, group, "LoadFrame"); - images[group][frame] = std::make_shared("DEFAULT", compressed); + images[group][frame] = std::make_shared("DEFAULT"); } else //load from separate file { @@ -1507,11 +952,10 @@ void CAnimation::printError(size_t frame, size_t group, std::string type) const logGlobal->error("%s error: Request for frame not present in CAnimation! File name: %s, Group: %d, Frame: %d", type, name, group, frame); } -CAnimation::CAnimation(std::string Name, bool Compressed): +CAnimation::CAnimation(std::string Name): name(Name), - compressed(Compressed), preloaded(false), - defFile(nullptr) + defFile() { size_t dotPos = name.find_last_of('.'); if ( dotPos!=-1 ) @@ -1521,7 +965,7 @@ CAnimation::CAnimation(std::string Name, bool Compressed): ResourceID resource(std::string("SPRITES/") + name, EResType::ANIMATION); if(CResourceHandler::get()->existsResource(resource)) - defFile = new CDefFile(name); + defFile = std::make_shared(name); init(); @@ -1531,21 +975,28 @@ CAnimation::CAnimation(std::string Name, bool Compressed): CAnimation::CAnimation(): name(""), - compressed(false), preloaded(false), - defFile(nullptr) + defFile() { init(); } -CAnimation::~CAnimation() -{ - if(defFile) - delete defFile; -} +CAnimation::~CAnimation() = default; void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup) { + if(!source.count(sourceGroup)) + { + logAnim->error("Group %d missing in %s", sourceGroup, name); + return; + } + + if(source[sourceGroup].size() <= sourceFrame) + { + logAnim->error("Frame [%d %d] missing in %s", sourceGroup, sourceFrame, name); + return; + } + //todo: clone actual loaded Image object JsonNode clone(source[sourceGroup][sourceFrame]); diff --git a/client/gui/CAnimation.h b/client/gui/CAnimation.h index d988dca8e..9541322a3 100644 --- a/client/gui/CAnimation.h +++ b/client/gui/CAnimation.h @@ -68,12 +68,9 @@ private: //animation file name std::string name; - //if true all frames will be stored in compressed (RLE) state - const bool compressed; - bool preloaded; - CDefFile * defFile; + std::shared_ptr defFile; //loader, will be called by load(), require opened def file for loading from it. Returns true if image is loaded bool loadFrame(size_t frame, size_t group); @@ -93,7 +90,7 @@ private: std::shared_ptr getFromExtraDef(std::string filename); public: - CAnimation(std::string Name, bool Compressed = false); + CAnimation(std::string Name); CAnimation(); ~CAnimation(); diff --git a/client/gui/CCursorHandler.cpp b/client/gui/CCursorHandler.cpp index 9bcfe3a62..e5b97de87 100644 --- a/client/gui/CCursorHandler.cpp +++ b/client/gui/CCursorHandler.cpp @@ -18,8 +18,31 @@ #include "../CMT.h" +void CCursorHandler::clearBuffer() +{ + Uint32 fillColor = SDL_MapRGBA(buffer->format, 0, 0, 0, 0); + CSDL_Ext::fillRect(buffer, nullptr, fillColor); +} + +void CCursorHandler::updateBuffer(CIntObject * payload) +{ + payload->moveTo(Point(0,0)); + payload->showAll(buffer); + + needUpdate = true; +} + +void CCursorHandler::replaceBuffer(CIntObject * payload) +{ + clearBuffer(); + updateBuffer(payload); +} + void CCursorHandler::initCursor() { + cursorLayer = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 40, 40); + SDL_SetTextureBlendMode(cursorLayer, SDL_BLENDMODE_BLEND); + xpos = ypos = 0; type = ECursor::DEFAULT; dndObject = nullptr; @@ -34,9 +57,9 @@ void CCursorHandler::initCursor() currentCursor = cursors.at(int(ECursor::DEFAULT)).get(); - help = CSDL_Ext::newSurface(40,40); - //No blending. Ensure, that we are copying pixels during "screen restore draw" - SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE); + buffer = CSDL_Ext::newSurface(40,40); + + SDL_SetSurfaceBlendMode(buffer, SDL_BLENDMODE_NONE); SDL_ShowCursor(SDL_DISABLE); changeGraphic(ECursor::ADVENTURE, 0); @@ -56,11 +79,17 @@ void CCursorHandler::changeGraphic(ECursor::ECursorTypes type, int index) this->frame = index; currentCursor->setFrame(index); } + + replaceBuffer(currentCursor); } void CCursorHandler::dragAndDropCursor(std::unique_ptr object) { dndObject = std::move(object); + if(dndObject) + replaceBuffer(dndObject.get()); + else + replaceBuffer(currentCursor); } void CCursorHandler::cursorMove(const int & x, const int & y) @@ -69,40 +98,6 @@ void CCursorHandler::cursorMove(const int & x, const int & y) ypos = y; } -void CCursorHandler::drawWithScreenRestore() -{ - if(!showing) return; - int x = xpos, y = ypos; - shiftPos(x, y); - - SDL_Rect temp_rect1 = genRect(40,40,x,y); - SDL_Rect temp_rect2 = genRect(40,40,0,0); - SDL_BlitSurface(screen, &temp_rect1, help, &temp_rect2); - - if (dndObject) - { - dndObject->moveTo(Point(x - dndObject->pos.w/2, y - dndObject->pos.h/2)); - dndObject->showAll(screen); - } - else - { - currentCursor->moveTo(Point(x,y)); - currentCursor->showAll(screen); - } -} - -void CCursorHandler::drawRestored() -{ - if(!showing) - return; - - int x = xpos, y = ypos; - shiftPos(x, y); - - SDL_Rect temp_rect = genRect(40, 40, x, y); - SDL_BlitSurface(help, nullptr, screen, &temp_rect); -} - void CCursorHandler::shiftPos( int &x, int &y ) { if(( type == ECursor::COMBAT && frame != ECursor::COMBAT_POINTER) || type == ECursor::SPELLBOOK) @@ -221,15 +216,54 @@ void CCursorHandler::centerCursor() void CCursorHandler::render() { - drawWithScreenRestore(); - CSDL_Ext::update(screen); - drawRestored(); + if(!showing) + return; + + //the must update texture in the main (renderer) thread, but changes to cursor type may come from other threads + updateTexture(); + + int x = xpos; + int y = ypos; + shiftPos(x, y); + + if(dndObject) + { + x -= dndObject->pos.w/2; + y -= dndObject->pos.h/2; + } + + SDL_Rect destRect; + destRect.x = x; + destRect.y = y; + destRect.w = 40; + destRect.h = 40; + + SDL_RenderCopy(mainRenderer, cursorLayer, nullptr, &destRect); } -CCursorHandler::CCursorHandler() = default; +void CCursorHandler::updateTexture() +{ + if(needUpdate) + { + SDL_UpdateTexture(cursorLayer, nullptr, buffer->pixels, buffer->pitch); + needUpdate = false; + } +} + +CCursorHandler::CCursorHandler() + : needUpdate(true), + buffer(nullptr), + cursorLayer(nullptr), + showing(false) +{ + +} CCursorHandler::~CCursorHandler() { - if(help) - SDL_FreeSurface(help); + if(buffer) + SDL_FreeSurface(buffer); + + if(cursorLayer) + SDL_DestroyTexture(cursorLayer); } diff --git a/client/gui/CCursorHandler.h b/client/gui/CCursorHandler.h index ae9d727b1..30ef0c65b 100644 --- a/client/gui/CCursorHandler.h +++ b/client/gui/CCursorHandler.h @@ -8,9 +8,10 @@ * */ #pragma once - +class CIntObject; class CAnimImage; struct SDL_Surface; +struct SDL_Texture; namespace ECursor { @@ -26,7 +27,10 @@ namespace ECursor /// handles mouse cursor class CCursorHandler final { - SDL_Surface * help; + bool needUpdate; + SDL_Texture * cursorLayer; + + SDL_Surface * buffer; CAnimImage * currentCursor; std::unique_ptr dndObject; //if set, overrides currentCursor @@ -35,10 +39,12 @@ class CCursorHandler final bool showing; - /// Draw cursor preserving original image below cursor - void drawWithScreenRestore(); - /// Restore original image below cursor - void drawRestored(); + void clearBuffer(); + void updateBuffer(CIntObject * payload); + void replaceBuffer(CIntObject * payload); + void shiftPos( int &x, int &y ); + + void updateTexture(); public: /// position of cursor int xpos, ypos; @@ -63,9 +69,8 @@ public: void render(); - void shiftPos( int &x, int &y ); - void hide() { showing=0; }; - void show() { showing=1; }; + void hide() { showing=false; }; + void show() { showing=true; }; /// change cursor's positions to (x, y) void cursorMove(const int & x, const int & y); diff --git a/client/gui/CGuiHandler.cpp b/client/gui/CGuiHandler.cpp index 7428a98c5..3910338e7 100644 --- a/client/gui/CGuiHandler.cpp +++ b/client/gui/CGuiHandler.cpp @@ -96,10 +96,11 @@ void CGuiHandler::handleElementDeActivate(CIntObject * elem, ui16 activityFlag) elem->active_m &= ~activityFlag; } -void CGuiHandler::popInt(IShowActivatable *top) +void CGuiHandler::popInt(std::shared_ptr top) { assert(listInt.front() == top); top->deactivate(); + disposed.push_back(top); listInt.pop_front(); objsToBlit -= top; if(!listInt.empty()) @@ -109,18 +110,10 @@ void CGuiHandler::popInt(IShowActivatable *top) pushSDLEvent(SDL_USEREVENT, EUserEvent::INTERFACE_CHANGED); } -void CGuiHandler::popIntTotally(IShowActivatable *top) -{ - assert(listInt.front() == top); - popInt(top); - delete top; - fakeMouseMove(); -} - -void CGuiHandler::pushInt(IShowActivatable *newInt) +void CGuiHandler::pushInt(std::shared_ptr newInt) { assert(newInt); - assert(boost::range::find(listInt, newInt) == listInt.end()); // do not add same object twice + assert(!vstd::contains(listInt, newInt)); // do not add same object twice //a new interface will be present, we'll need to use buffer surface (unless it's advmapint that will alter screenBuf on activate anyway) screenBuf = screen2; @@ -128,6 +121,7 @@ void CGuiHandler::pushInt(IShowActivatable *newInt) if(!listInt.empty()) listInt.front()->deactivate(); listInt.push_front(newInt); + CCS->curh->changeGraphic(ECursor::ADVENTURE, 0); newInt->activate(); objsToBlit.push_back(newInt); totalRedraw(); @@ -144,7 +138,7 @@ void CGuiHandler::popInts(int howMany) for(int i=0; i < howMany; i++) { objsToBlit -= listInt.front(); - delete listInt.front(); + disposed.push_back(listInt.front()); listInt.pop_front(); } @@ -158,10 +152,10 @@ void CGuiHandler::popInts(int howMany) pushSDLEvent(SDL_USEREVENT, EUserEvent::INTERFACE_CHANGED); } -IShowActivatable * CGuiHandler::topInt() +std::shared_ptr CGuiHandler::topInt() { if(listInt.empty()) - return nullptr; + return std::shared_ptr(); else return listInt.front(); } @@ -234,11 +228,11 @@ void CGuiHandler::handleCurrentEvent() case SDLK_F9: //not working yet since CClient::run remain locked after CBattleInterface removal - if(LOCPLINT->battleInt) - { - GH.popIntTotally(GH.topInt()); - vstd::clear_pointer(LOCPLINT->battleInt); - } +// if(LOCPLINT->battleInt) +// { +// GH.popInts(1); +// vstd::clear_pointer(LOCPLINT->battleInt); +// } break; default: @@ -271,7 +265,6 @@ void CGuiHandler::handleCurrentEvent() } else if(current->type == SDL_MOUSEMOTION) { - CCS->curh->cursorMove(current->motion.x, current->motion.y); handleMouseMotion(); } else if(current->type == SDL_MOUSEBUTTONDOWN) @@ -457,15 +450,18 @@ void CGuiHandler::renderFrame() if(nullptr != curInt) curInt->update(); - if (settings["general"]["showfps"].Bool()) + if(settings["general"]["showfps"].Bool()) drawFPSCounter(); - // draw the mouse cursor and update the screen - CCS->curh->render(); + SDL_UpdateTexture(screenTexture, nullptr, screen->pixels, screen->pitch); SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr); + CCS->curh->render(); + SDL_RenderPresent(mainRenderer); + + disposed.clear(); } mainFPSmng->framerateDelay(); // holds a constant FPS diff --git a/client/gui/CGuiHandler.h b/client/gui/CGuiHandler.h index c786cb0f8..641a885ac 100644 --- a/client/gui/CGuiHandler.h +++ b/client/gui/CGuiHandler.h @@ -58,10 +58,12 @@ class CGuiHandler { public: CFramerateManager * mainFPSmng; //to keep const framerate - std::list listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on) + std::list> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on) CGStatusBar * statusbar; private: + std::vector> disposed; + std::atomic continueEventHandling; typedef std::list CIntObjectList; @@ -86,7 +88,7 @@ public: public: //objs to blit - std::vector objsToBlit; + std::vector> objsToBlit; SDL_Event * current; //current event - can be set to nullptr to stop handling event IUpdateable *curInt; @@ -106,11 +108,19 @@ public: void totalRedraw(); //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering void simpleRedraw(); //update only top interface and draw background from buffer, sets a flag, method gets called at the end of the rendering - void popInt(IShowActivatable *top); //removes given interface from the top and activates next - void popIntTotally(IShowActivatable *top); //deactivates, deletes, removes given interface from the top and activates next - void pushInt(IShowActivatable *newInt); //deactivate old top interface, activates this one and pushes to the top + void pushInt(std::shared_ptr newInt); //deactivate old top interface, activates this one and pushes to the top + template + void pushIntT(Args && ... args) + { + auto newInt = std::make_shared(std::forward(args)...); + pushInt(newInt); + } + void popInts(int howMany); //pops one or more interfaces - deactivates top, deletes and removes given number of interfaces, activates new front - IShowActivatable *topInt(); //returns top interface + + void popInt(std::shared_ptr top); //removes given interface from the top and activates next + + std::shared_ptr topInt(); //returns top interface void updateTime(); //handles timeInterested void handleEvents(); //takes events from queue and calls interested objects diff --git a/client/gui/CIntObject.cpp b/client/gui/CIntObject.cpp index e3a707dd5..11f0af003 100644 --- a/client/gui/CIntObject.cpp +++ b/client/gui/CIntObject.cpp @@ -164,11 +164,6 @@ void CIntObject::printAtLoc(const std::string & text, int x, int y, EFonts font, graphics->fonts[font]->renderTextLeft(dst, text, kolor, Point(pos.x + x, pos.y + y)); } -void CIntObject::printAtRightLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst) -{ - graphics->fonts[font]->renderTextRight(dst, text, kolor, Point(pos.x + x, pos.y + y)); -} - void CIntObject::printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst) { printAtMiddleLoc(text, Point(x,y), font, kolor, dst); @@ -194,11 +189,6 @@ void CIntObject::printAtMiddleWBLoc( const std::string & text, int x, int y, EFo graphics->fonts[font]->renderTextLinesCenter(dst, CMessage::breakText(text, charpr, font), kolor, Point(pos.x + x, pos.y + y)); } -void CIntObject::printToLoc( const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst ) -{ - graphics->fonts[font]->renderTextRight(dst, text, kolor, Point(pos.x + x, pos.y + y)); -} - void CIntObject::addUsedEvents(ui16 newActions) { if (active_m) @@ -223,7 +213,7 @@ void CIntObject::disable() void CIntObject::enable() { - if(!active_m && parent_m->active) + if(!active_m && (!parent_m || parent_m->active)) activate(); recActions = 255; @@ -302,11 +292,6 @@ void CIntObject::removeChild(CIntObject * child, bool adjustPosition) child->pos -= pos; } -void CIntObject::drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &color) -{ - CSDL_Ext::drawBorder(sur, r + pos, color); -} - void CIntObject::redraw() { //currently most of calls come from active objects so this check won't affect them @@ -375,3 +360,16 @@ void CKeyShortcut::keyPressed(const SDL_KeyboardEvent & key) } } + +WindowBase::WindowBase(int used_, Point pos_) + : CIntObject(used_, pos_) +{ + +} + +void WindowBase::close() +{ + if(GH.topInt().get() != this) + logGlobal->error("Only top interface must be closed"); + GH.popInts(1); +} diff --git a/client/gui/CIntObject.h b/client/gui/CIntObject.h index 30a14d36c..01a7f1399 100644 --- a/client/gui/CIntObject.h +++ b/client/gui/CIntObject.h @@ -183,12 +183,9 @@ public: /* * Functions that should be used only by specific GUI elements. Don't use them unless you really know why they are here */ - //wrappers for CSDL_Ext methods. This versions use coordinates relative to pos - void drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &color); + //functions for printing text. Use CLabel where possible instead void printAtLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst); - void printToLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst); - void printAtRightLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst); void printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst); void printAtMiddleLoc(const std::string & text, const Point &p, EFonts font, SDL_Color color, SDL_Surface * dst); void printAtMiddleWBLoc(const std::string & text, int x, int y, EFonts font, int charsPerLine, SDL_Color color, SDL_Surface * dst); @@ -211,3 +208,11 @@ public: CKeyShortcut(std::set Keys); virtual void keyPressed(const SDL_KeyboardEvent & key) override; //call-in }; + +class WindowBase : public CIntObject +{ +public: + WindowBase(int used_ = 0, Point pos_ = Point()); +protected: + void close(); +}; diff --git a/client/gui/SDL_Extensions.cpp b/client/gui/SDL_Extensions.cpp index 96f81d237..711bc71fd 100644 --- a/client/gui/SDL_Extensions.cpp +++ b/client/gui/SDL_Extensions.cpp @@ -39,7 +39,7 @@ void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h) SDL_Surface * CSDL_Ext::newSurface(int w, int h, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given { - SDL_Surface * ret = SDL_CreateRGBSurface(mod->flags,w,h,mod->format->BitsPerPixel,mod->format->Rmask,mod->format->Gmask,mod->format->Bmask,mod->format->Amask); + SDL_Surface * ret = SDL_CreateRGBSurface(0,w,h,mod->format->BitsPerPixel,mod->format->Rmask,mod->format->Gmask,mod->format->Bmask,mod->format->Amask); if (mod->format->palette) { assert(ret->format->palette); @@ -65,7 +65,7 @@ SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height) Channels::px::b.set((Uint8*)&bMask, 255); Channels::px::a.set((Uint8*)&aMask, 255); - return SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, bpp * 8, rMask, gMask, bMask, aMask); + return SDL_CreateRGBSurface(0, width, height, bpp * 8, rMask, gMask, bMask, aMask); } bool isItIn(const SDL_Rect * rect, int x, int y) diff --git a/client/lobby/CBonusSelection.cpp b/client/lobby/CBonusSelection.cpp index d3c74d846..f585b8af4 100644 --- a/client/lobby/CBonusSelection.cpp +++ b/client/lobby/CBonusSelection.cpp @@ -394,14 +394,14 @@ void CBonusSelection::goBack() } else { - GH.popIntTotally(this); + close(); } // TODO: we can actually only pop bonus selection interface for custom campaigns // Though this would require clearing CLobbyScreen::bonusSel pointer when poping this interface /* else { - GH.popIntTotally(this); + close(); CSH->state = EClientState::LOBBY; } */ @@ -420,7 +420,7 @@ void CBonusSelection::startMap() const CCampaignScenario & scenario = getCampaign()->camp->scenarios[CSH->campaignMap]; if(scenario.prolog.hasPrologEpilog) { - GH.pushInt(new CPrologEpilogVideo(scenario.prolog, exitCb)); + GH.pushIntT(scenario.prolog, exitCb); } else { @@ -430,7 +430,7 @@ void CBonusSelection::startMap() if(LOCPLINT) // we're currently ingame, so ask for starting new map and end game { - GH.popInt(this); + close(); LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[67], [=]() { showPrologVideo(); @@ -444,7 +444,7 @@ void CBonusSelection::startMap() void CBonusSelection::restartMap() { - GH.popInt(this); + close(); LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[67], [=]() { CSH->startCampaignScenario(); diff --git a/client/lobby/CLobbyScreen.cpp b/client/lobby/CLobbyScreen.cpp index 469177c9d..ad076088a 100644 --- a/client/lobby/CLobbyScreen.cpp +++ b/client/lobby/CLobbyScreen.cpp @@ -88,7 +88,11 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType) buttonStart->assignedKeys.insert(SDLK_RETURN); - buttonBack = std::make_shared(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [&](){CSH->sendClientDisconnecting(); GH.popIntTotally(this);}, SDLK_ESCAPE); + buttonBack = std::make_shared(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [&]() + { + CSH->sendClientDisconnecting(); + close(); + }, SDLK_ESCAPE); } CLobbyScreen::~CLobbyScreen() @@ -138,7 +142,7 @@ void CLobbyScreen::startScenario(bool allowOnlyAI) } catch(ExceptionNoTemplate & e) { - GH.pushInt(CInfoWindow::create(CGI->generaltexth->allTexts[751])); + CInfoWindow::showInfoDialog(std::ref(CGI->generaltexth->allTexts[751]), CInfoWindow::TCompsInfo(), PlayerColor(1)); } catch(...) { diff --git a/client/lobby/CLobbyScreen.h b/client/lobby/CLobbyScreen.h index 679ed5634..962547fa4 100644 --- a/client/lobby/CLobbyScreen.h +++ b/client/lobby/CLobbyScreen.h @@ -31,5 +31,5 @@ public: const CMapInfo * getMapInfo() override; const StartInfo * getStartInfo() override; - CBonusSelection * bonusSel; + std::shared_ptr bonusSel; }; diff --git a/client/lobby/CSavingScreen.cpp b/client/lobby/CSavingScreen.cpp index 3f4bdc9d1..7632ac691 100644 --- a/client/lobby/CSavingScreen.cpp +++ b/client/lobby/CSavingScreen.cpp @@ -80,7 +80,7 @@ void CSavingScreen::saveGame() Settings lastSave = settings.write["general"]["lastSave"]; lastSave->String() = path; LOCPLINT->cb->save(path); - GH.popIntTotally(this); + close(); }; if(CResourceHandler::get("local")->existsResource(ResourceID(path, EResType::CLIENT_SAVEGAME))) diff --git a/client/lobby/CScenarioInfoScreen.cpp b/client/lobby/CScenarioInfoScreen.cpp index 88402ec48..a64676a4f 100644 --- a/client/lobby/CScenarioInfoScreen.cpp +++ b/client/lobby/CScenarioInfoScreen.cpp @@ -39,7 +39,7 @@ CScenarioInfoScreen::CScenarioInfoScreen() card->changeSelection(); card->iconDifficulty->setSelected(getCurrentDifficulty()); - buttonBack = std::make_shared(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], std::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE); + buttonBack = std::make_shared(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, SDLK_ESCAPE); } CScenarioInfoScreen::~CScenarioInfoScreen() diff --git a/client/lobby/CScenarioInfoScreen.h b/client/lobby/CScenarioInfoScreen.h index 63892bb77..e2a895569 100644 --- a/client/lobby/CScenarioInfoScreen.h +++ b/client/lobby/CScenarioInfoScreen.h @@ -12,7 +12,7 @@ #include "CSelectionBase.h" /// Scenario information screen shown during the game -class CScenarioInfoScreen : public CIntObject, public ISelectionScreenInfo +class CScenarioInfoScreen : public WindowBase, public ISelectionScreenInfo { public: std::shared_ptr buttonBack; diff --git a/client/lobby/CSelectionBase.cpp b/client/lobby/CSelectionBase.cpp index 698a4e84d..35f3adf66 100644 --- a/client/lobby/CSelectionBase.cpp +++ b/client/lobby/CSelectionBase.cpp @@ -86,7 +86,7 @@ CSelectionBase::CSelectionBase(ESelectionScreen type) } pos = background->center(); card = std::make_shared(); - buttonBack = std::make_shared(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], std::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE); + buttonBack = std::make_shared(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, SDLK_ESCAPE); } void CSelectionBase::toggleTab(std::shared_ptr tab) @@ -367,7 +367,7 @@ void CFlagBox::recreate() void CFlagBox::clickRight(tribool down, bool previousState) { if(down && SEL->getMapInfo()) - GH.pushInt(new CFlagBoxTooltipBox(iconsTeamFlags)); + GH.pushIntT(iconsTeamFlags); } CFlagBox::CFlagBoxTooltipBox::CFlagBoxTooltipBox(std::shared_ptr icons) diff --git a/client/lobby/OptionsTab.cpp b/client/lobby/OptionsTab.cpp index 9562bf62b..aacf2419a 100644 --- a/client/lobby/OptionsTab.cpp +++ b/client/lobby/OptionsTab.cpp @@ -422,7 +422,7 @@ void OptionsTab::SelectedBox::clickRight(tribool down, bool previousState) if(settings.hero == -2 && !SEL->getPlayerInfo(settings.color.getNum()).hasCustomMainHero() && CPlayerSettingsHelper::type == HERO) return; - GH.pushInt(new CPlayerOptionTooltipBox(*this)); + GH.pushIntT(*this); } } diff --git a/client/mainmenu/CCampaignScreen.cpp b/client/mainmenu/CCampaignScreen.cpp index d51a6b715..670f2a49c 100644 --- a/client/mainmenu/CCampaignScreen.cpp +++ b/client/mainmenu/CCampaignScreen.cpp @@ -79,8 +79,7 @@ std::shared_ptr CCampaignScreen::createExitButton(const JsonNode & butt if(!button["help"].isNull() && button["help"].Float() > 0) help = CGI->generaltexth->zelp[button["help"].Float()]; - std::function close = std::bind(&CGuiHandler::popIntTotally, &GH, this); - return std::make_shared(Point(button["x"].Float(), button["y"].Float()), button["name"].String(), help, close, button["hotkey"].Float()); + return std::make_shared(Point(button["x"].Float(), button["y"].Float()), button["name"].String(), help, [=](){ close();}, button["hotkey"].Float()); } CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config) diff --git a/client/mainmenu/CMainMenu.cpp b/client/mainmenu/CMainMenu.cpp index ece0bb62e..687c6c6d0 100644 --- a/client/mainmenu/CMainMenu.cpp +++ b/client/mainmenu/CMainMenu.cpp @@ -60,7 +60,7 @@ namespace fs = boost::filesystem; -CMainMenu * CMM = nullptr; +std::shared_ptr CMM; ISelectionScreenInfo * SEL; static void do_quit() @@ -176,7 +176,7 @@ static std::function genCommand(CMenuScreen * menu, std::vector(ESelectionScreen::newGame); }; case 2: return std::bind(CMainMenu::openLobby, ESelectionScreen::campaignList, true, nullptr, ELoadMode::NONE); case 3: @@ -191,7 +191,7 @@ static std::function genCommand(CMenuScreen * menu, std::vector(ESelectionScreen::loadGame); }; case 2: return std::bind(CMainMenu::openLobby, ESelectionScreen::loadGame, true, nullptr, ELoadMode::CAMPAIGN); case 3: @@ -279,8 +279,7 @@ CMainMenu::CMainMenu() pos.h = screen->h; GH.defActionsDef = 63; - CMM = this; - menu = new CMenuScreen(CMainMenuConfig::get().getConfig()["window"]); + menu = std::make_shared(CMainMenuConfig::get().getConfig()["window"]); OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; backgroundAroundMenu = std::make_shared("DIBOXBCK", pos); } @@ -288,8 +287,6 @@ CMainMenu::CMainMenu() CMainMenu::~CMainMenu() { boost::unique_lock lock(*CPlayerInterface::pim); - if(CMM == this) - CMM = nullptr; if(GH.curInt == this) GH.curInt = nullptr; @@ -297,12 +294,12 @@ CMainMenu::~CMainMenu() void CMainMenu::update() { - if(CMM != this) //don't update if you are not a main interface + if(CMM != this->shared_from_this()) //don't update if you are not a main interface return; if(GH.listInt.empty()) { - GH.pushInt(this); + GH.pushInt(CMM); GH.pushInt(menu); menu->switchToTab(0); } @@ -313,7 +310,7 @@ void CMainMenu::update() // check for null othervice crash on finishing a campaign // /FIXME: find out why GH.listInt is empty to begin with - if(GH.topInt() != nullptr) + if(GH.topInt()) GH.topInt()->show(screen); } @@ -323,7 +320,7 @@ void CMainMenu::openLobby(ESelectionScreen screenType, bool host, const std::vec CSH->screenType = screenType; CSH->loadMode = loadMode; - GH.pushInt(new CSimpleJoinScreen(host)); + GH.pushIntT(host); } void CMainMenu::openCampaignLobby(const std::string & campaignFileName) @@ -337,23 +334,23 @@ void CMainMenu::openCampaignLobby(std::shared_ptr campaign) CSH->resetStateForLobby(StartInfo::CAMPAIGN); CSH->screenType = ESelectionScreen::campaignList; CSH->campaignStateToSend = campaign; - GH.pushInt(new CSimpleJoinScreen()); + GH.pushIntT(); } void CMainMenu::openCampaignScreen(std::string name) { if(vstd::contains(CMainMenuConfig::get().getCampaigns().Struct(), name)) { - GH.pushInt(new CCampaignScreen(CMainMenuConfig::get().getCampaigns()[name])); + GH.pushIntT(CMainMenuConfig::get().getCampaigns()[name]); return; } logGlobal->error("Unknown campaign set: %s", name); } -CMainMenu * CMainMenu::create() +std::shared_ptr CMainMenu::create() { if(!CMM) - CMM = new CMainMenu(); + CMM = std::shared_ptr(new CMainMenu()); GH.terminate_cond->set(false); return CMM; @@ -381,19 +378,21 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType) buttonHotseat = std::make_shared(Point(373, 78), "MUBHOT.DEF", CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this)); buttonHost = std::make_shared(Point(373, 78 + 57 * 1), "MUBHOST.DEF", CButton::tooltip("Host TCP/IP game", ""), std::bind(&CMultiMode::hostTCP, this)); buttonJoin = std::make_shared(Point(373, 78 + 57 * 2), "MUBJOIN.DEF", CButton::tooltip("Join TCP/IP game", ""), std::bind(&CMultiMode::joinTCP, this)); - buttonCancel = std::make_shared(Point(373, 424), "MUBCANC.DEF", CGI->generaltexth->zelp[288], [&]() { GH.popIntTotally(this);}, SDLK_ESCAPE); + buttonCancel = std::make_shared(Point(373, 424), "MUBCANC.DEF", CGI->generaltexth->zelp[288], [=](){ close();}, SDLK_ESCAPE); } void CMultiMode::hostTCP() { - GH.popIntTotally(this); - GH.pushInt(new CMultiPlayers(settings["general"]["playerName"].String(), screenType, true, ELoadMode::MULTI)); + auto savedScreenType = screenType; + close(); + GH.pushIntT(settings["general"]["playerName"].String(), savedScreenType, true, ELoadMode::MULTI); } void CMultiMode::joinTCP() { - GH.popIntTotally(this); - GH.pushInt(new CMultiPlayers(settings["general"]["playerName"].String(), screenType, false, ELoadMode::MULTI)); + auto savedScreenType = screenType; + close(); + GH.pushIntT(settings["general"]["playerName"].String(), savedScreenType, false, ELoadMode::MULTI); } void CMultiMode::onNameChange(std::string newText) @@ -420,7 +419,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); + buttonCancel = std::make_shared(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], [=](){ close();}, SDLK_ESCAPE); statusBar = std::make_shared(std::make_shared(Rect(7, 381, 348, 18), 0)); //226, 472 inputNames[0]->setText(firstPlayer, true); @@ -497,9 +496,9 @@ void CSimpleJoinScreen::leaveScreen() textTitle->setText("Closing..."); CSH->state = EClientState::CONNECTION_CANCELLED; } - else if(GH.listInt.size() && GH.listInt.front() == this) + else if(GH.listInt.size() && GH.listInt.front().get() == this) { - GH.popIntTotally(this); + close(); } } @@ -516,9 +515,9 @@ void CSimpleJoinScreen::connectThread(const std::string addr, const ui16 port) else CSH->justConnectToServer(addr, port); - if(GH.listInt.size() && GH.listInt.front() == this) + if(GH.listInt.size() && GH.listInt.front().get() == this) { - GH.popIntTotally(this); + close(); } } diff --git a/client/mainmenu/CMainMenu.h b/client/mainmenu/CMainMenu.h index 4561d334e..a84437837 100644 --- a/client/mainmenu/CMainMenu.h +++ b/client/mainmenu/CMainMenu.h @@ -69,7 +69,7 @@ public: }; /// Multiplayer mode -class CMultiMode : public CIntObject +class CMultiMode : public WindowBase { public: ESelectionScreen screenType; @@ -89,7 +89,7 @@ public: }; /// Hot seat player window -class CMultiPlayers : public CIntObject +class CMultiPlayers : public WindowBase { bool host; ELoadMode loadMode; @@ -124,14 +124,14 @@ private: }; /// Handles background screen, loads graphics for victory/loss condition and random town or hero selection -class CMainMenu : public CIntObject, public IUpdateable +class CMainMenu : public CIntObject, public IUpdateable, public std::enable_shared_from_this { std::shared_ptr backgroundAroundMenu; CMainMenu(); //Use CMainMenu::create public: - CMenuScreen * menu; + std::shared_ptr menu; ~CMainMenu(); void update() override; @@ -140,14 +140,14 @@ public: static void openCampaignLobby(std::shared_ptr campaign); void openCampaignScreen(std::string name); - static CMainMenu * create(); + static std::shared_ptr create(); static std::shared_ptr createPicture(const JsonNode & config); }; /// Simple window to enter the server's address. -class CSimpleJoinScreen : public CIntObject +class CSimpleJoinScreen : public WindowBase { std::shared_ptr background; std::shared_ptr textTitle; @@ -179,4 +179,4 @@ public: void showAll(SDL_Surface * to) override; }; -extern CMainMenu * CMM; +extern std::shared_ptr CMM; diff --git a/client/mainmenu/CPrologEpilogVideo.cpp b/client/mainmenu/CPrologEpilogVideo.cpp index ce7e825bb..5f2e5d92b 100644 --- a/client/mainmenu/CPrologEpilogVideo.cpp +++ b/client/mainmenu/CPrologEpilogVideo.cpp @@ -58,7 +58,7 @@ void CPrologEpilogVideo::show(SDL_Surface * to) void CPrologEpilogVideo::clickLeft(tribool down, bool previousState) { - GH.popInt(this); + close(); CCS->soundh->stopSound(voiceSoundHandle); exitCb(); } diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index f774baf5f..00a4c558f 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -1250,21 +1250,16 @@ void CAdvMapPanel::addChildToPanel(std::shared_ptr obj, ui8 actions) CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color) : CAdvMapPanel(bg, position), icons(_icons) { - fillerHeight = bg ? spaceBottom - pos.y - pos.h : 0; + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + int fillerHeight = bg ? spaceBottom - pos.y - pos.h : 0; - if (fillerHeight > 0) + if(fillerHeight > 0) { - tmpBackgroundFiller = CMessage::drawDialogBox(pos.w, fillerHeight, color); + backgroundFiller = std::make_shared("DIBOXBCK", Rect(0, pos.h, pos.w, fillerHeight)); } - else - tmpBackgroundFiller = nullptr; } -CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel() -{ - if (tmpBackgroundFiller) - SDL_FreeSurface(tmpBackgroundFiller); -} +CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel() = default; void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOffset) { @@ -1275,13 +1270,6 @@ void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOff const auto & data = iconsData.at(idx); currentIcons[idx]->setFrame(data.first + indexOffset); } - - if(fillerHeight > 0) - { - if(tmpBackgroundFiller) - SDL_FreeSurface(tmpBackgroundFiller); - tmpBackgroundFiller = CMessage::drawDialogBox(pos.w, fillerHeight, color); - } } void CAdvMapWorldViewPanel::addChildIcon(std::pair data, int indexOffset) @@ -1290,13 +1278,3 @@ void CAdvMapWorldViewPanel::addChildIcon(std::pair data, int indexOf iconsData.push_back(data); currentIcons.push_back(std::make_shared(icons, data.first + indexOffset, 0, data.second.x, data.second.y)); } - -void CAdvMapWorldViewPanel::showAll(SDL_Surface * to) -{ - if (tmpBackgroundFiller) - { - blitAt(tmpBackgroundFiller, pos.x, pos.y + pos.h, to); - } - - CAdvMapPanel::showAll(to); -} diff --git a/client/widgets/AdventureMapClasses.h b/client/widgets/AdventureMapClasses.h index 3cacc3995..2fe8ede48 100644 --- a/client/widgets/AdventureMapClasses.h +++ b/client/widgets/AdventureMapClasses.h @@ -16,6 +16,7 @@ class CArmedInstance; class CAnimation; class CAnimImage; class CShowableAnim; +class CFilledTexture; class CGGarrison; class CGObjectInstance; class CGHeroInstance; @@ -384,9 +385,8 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel std::vector> iconsData; /// ptrs to child-pictures constructed from iconsData 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; + /// surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod) + std::shared_ptr backgroundFiller; std::shared_ptr icons; public: CAdvMapWorldViewPanel(std::shared_ptr _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color); @@ -395,7 +395,6 @@ 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 showAll(SDL_Surface * to) override; }; class CInGameConsole : public CIntObject diff --git a/client/widgets/CArtifactHolder.cpp b/client/widgets/CArtifactHolder.cpp index 65b882f38..822455eca 100644 --- a/client/widgets/CArtifactHolder.cpp +++ b/client/widgets/CArtifactHolder.cpp @@ -126,7 +126,7 @@ void CHeroArtPlace::clickLeft(tribool down, bool previousState) if(ourArt && !down && previousState && !ourOwner->commonInfo->src.AOH) { if(ourArt->artType->id == ArtifactID::SPELLBOOK) - GH.pushInt(new CSpellWindow(ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt)); + GH.pushIntT(ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt); } if (!down && previousState) @@ -678,14 +678,14 @@ CArtifactsOfHero::~CArtifactsOfHero() void CArtifactsOfHero::updateParentWindow() { - if (CHeroWindow* chw = dynamic_cast(GH.topInt())) + if (CHeroWindow* chw = dynamic_cast(GH.topInt().get())) { if(updateState) chw->curHero = curHero; else chw->update(curHero, true); } - else if(CExchangeWindow* cew = dynamic_cast(GH.topInt())) + else if(CExchangeWindow* cew = dynamic_cast(GH.topInt().get())) { //use our copy of hero to draw window if(cew->heroInst[0]->id == curHero->id) diff --git a/client/widgets/CGarrisonInt.cpp b/client/widgets/CGarrisonInt.cpp index abd286d3d..839b2ee0f 100644 --- a/client/widgets/CGarrisonInt.cpp +++ b/client/widgets/CGarrisonInt.cpp @@ -161,7 +161,7 @@ bool CGarrisonSlot::viewInfo() elem->block(true); redraw(); - GH.pushInt(new CStackWindow(myStack, dism, pom, upgr)); + GH.pushIntT(myStack, dism, pom, upgr); return true; } @@ -170,7 +170,7 @@ bool CGarrisonSlot::viewInfo() bool CGarrisonSlot::highlightOrDropArtifact() { bool artSelected = false; - if (CWindowWithArtifacts* chw = dynamic_cast(GH.topInt())) //dirty solution + if (CWindowWithArtifacts* chw = dynamic_cast(GH.topInt().get())) //dirty solution { const std::shared_ptr commonInfo = chw->getCommonPart(); const CArtifactInstance * art = nullptr; @@ -241,8 +241,8 @@ bool CGarrisonSlot::split() int countLeft = selection->myStack ? selection->myStack->count : 0; int countRight = myStack ? myStack->count : 0; - GH.pushInt(new CSplitWindow(selection->creature, std::bind(&CGarrisonInt::splitStacks, owner, _1, _2), - minLeft, minRight, countLeft, countRight)); + GH.pushIntT(selection->creature, std::bind(&CGarrisonInt::splitStacks, owner, _1, _2), + minLeft, minRight, countLeft, countRight); return true; } @@ -278,7 +278,7 @@ void CGarrisonSlot::clickRight(tribool down, bool previousState) { if(creature && down) { - GH.pushInt(new CStackWindow(myStack, true)); + GH.pushIntT(myStack, true); } } diff --git a/client/widgets/Images.cpp b/client/widgets/Images.cpp index 4261a0ef1..5577ba886 100644 --- a/client/widgets/Images.cpp +++ b/client/widgets/Images.cpp @@ -173,7 +173,7 @@ void CPicture::createSimpleRect(const Rect &r, bool screenFormat, ui32 color) if(screenFormat) bg = CSDL_Ext::newSurface(r.w, r.h); else - bg = SDL_CreateRGBSurface(SDL_SWSURFACE, r.w, r.h, 8, 0, 0, 0, 0); + bg = SDL_CreateRGBSurface(0, r.w, r.h, 8, 0, 0, 0, 0); SDL_FillRect(bg, nullptr, color); freeSurf = true; @@ -296,7 +296,7 @@ void CAnimImage::playerColored(PlayerColor currPlayer) } CShowableAnim::CShowableAnim(int x, int y, std::string name, ui8 Flags, ui32 Delay, size_t Group): - anim(new CAnimation(name, Flags & USE_RLE)), + anim(std::make_shared(name)), group(Group), frame(0), first(0), @@ -319,7 +319,6 @@ CShowableAnim::CShowableAnim(int x, int y, std::string name, ui8 Flags, ui32 Del CShowableAnim::~CShowableAnim() { anim->unloadGroup(group); - delete anim; } void CShowableAnim::setAlpha(ui32 alphaValue) @@ -410,8 +409,8 @@ void CShowableAnim::blitImage(size_t frame, size_t group, SDL_Surface *to) assert(to); Rect src( xOffset, yOffset, pos.w, pos.h); auto img = anim->getImage(frame, group); - if (img) - img->draw(to, pos.x-xOffset, pos.y-yOffset, &src, alpha); + if(img) + img->draw(to, pos.x, pos.y, &src, alpha); } void CShowableAnim::rotate(bool on, bool vertical) @@ -423,15 +422,11 @@ void CShowableAnim::rotate(bool on, bool vertical) flags &= ~flag; } -CCreatureAnim::CCreatureAnim(int x, int y, std::string name, Rect picPos, ui8 flags, EAnimType type): +CCreatureAnim::CCreatureAnim(int x, int y, std::string name, ui8 flags, EAnimType type): CShowableAnim(x,y,name,flags,4,type) { - xOffset = picPos.x; - yOffset = picPos.y; - if (picPos.w) - pos.w = picPos.w; - if (picPos.h) - pos.h = picPos.h; + xOffset = 0; + yOffset = 0; } void CCreatureAnim::loopPreview(bool warMachine) diff --git a/client/widgets/Images.h b/client/widgets/Images.h index 71defa97f..e4f4b7a70 100644 --- a/client/widgets/Images.h +++ b/client/widgets/Images.h @@ -105,12 +105,11 @@ public: BASE=1, //base frame will be blitted before current one HORIZONTAL_FLIP=2, //TODO: will be displayed rotated VERTICAL_FLIP=4, //TODO: will be displayed rotated - USE_RLE=8, //RLE-d version, support full alpha-channel for 8-bit images PLAYER_COLORED=16, //TODO: all loaded images will be player-colored PLAY_ONCE=32 //play animation only once and stop at last frame }; protected: - CAnimation * anim; + std::shared_ptr anim; size_t group, frame;//current frame @@ -227,7 +226,6 @@ public: //clear queue and set animation to this sequence void clearAndSet(EAnimType type); - CCreatureAnim(int x, int y, std::string name, Rect picPos, - ui8 flags= USE_RLE, EAnimType = HOLDING ); + CCreatureAnim(int x, int y, std::string name, ui8 flags = 0, EAnimType = HOLDING); }; diff --git a/client/widgets/MiscWidgets.cpp b/client/widgets/MiscWidgets.cpp index 33265b424..8ccb7dc74 100644 --- a/client/widgets/MiscWidgets.cpp +++ b/client/widgets/MiscWidgets.cpp @@ -457,7 +457,7 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A bg = std::make_shared(CGI->townh->factions[faction]->creatureBg130); else bg = std::make_shared(CGI->townh->factions[faction]->creatureBg120); - anim = std::make_shared(0, 0, cre->animDefName, Rect()); + anim = std::make_shared(0, 0, cre->animDefName); anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h); anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON)); diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index fdb6a580f..a42dc2171 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -59,7 +59,7 @@ #define ADVOPT (conf.go()->ac) using namespace CSDL_Ext; -CAdvMapInt *adventureInt; +std::shared_ptr adventureInt; static void setScrollingCursor(ui8 direction) { @@ -565,7 +565,6 @@ CAdvMapInt::CAdvMapInt(): swipeEnabled(settings["general"]["swipe"].Bool()), swipeMovementRequested(false), swipeTargetPosition(int3(-1, -1, -1)) { - adventureInt = this; pos.x = pos.y = 0; pos.w = screen->w; pos.h = screen->h; @@ -723,7 +722,7 @@ CAdvMapInt::~CAdvMapInt() void CAdvMapInt::fshowOverview() { - GH.pushInt(new CKingdomInterface()); + GH.pushIntT(); } void CAdvMapInt::fworldViewBack() @@ -811,17 +810,17 @@ void CAdvMapInt::fshowSpellbok() centerOn(selection); - GH.pushInt(new CSpellWindow(curHero(), LOCPLINT, false)); + GH.pushIntT(curHero(), LOCPLINT, false); } void CAdvMapInt::fadventureOPtions() { - GH.pushInt(new CAdventureOptions()); + GH.pushIntT(); } void CAdvMapInt::fsystemOptions() { - GH.pushInt(new CSystemOptionsWindow()); + GH.pushIntT(); } void CAdvMapInt::fnextHero() @@ -1088,7 +1087,7 @@ void CAdvMapInt::handleMapScrollingUpdate() int scrollSpeed = settings["adventure"]["scrollSpeed"].Float(); //if advmap needs updating AND (no dialog is shown OR ctrl is pressed) if((animValHitCount % (4 / scrollSpeed)) == 0 - && ((GH.topInt() == this) || isCtrlKeyDown())) + && ((GH.topInt().get() == this) || isCtrlKeyDown())) { if((scrollingDir & LEFT) && (position.x > -CGI->mh->frameW)) position.x--; @@ -1224,7 +1223,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) return; case SDLK_s: if(isActive() && key.type == SDL_KEYUP) - GH.pushInt(new CSavingScreen()); + GH.pushIntT(); return; case SDLK_d: { @@ -1274,7 +1273,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) } case SDLK_ESCAPE: { - if(isActive() || GH.topInt() != this || !spellBeingCasted || key.state != SDL_PRESSED) + if(isActive() || GH.topInt().get() != this || !spellBeingCasted || key.state != SDL_PRESSED) return; leaveCastingMode(); @@ -1300,7 +1299,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) } if(townWithMarket) //if any town has marketplace, open window - GH.pushInt(new CMarketplaceWindow(townWithMarket)); + GH.pushIntT(townWithMarket); else //if not - complain LOCPLINT->showInfoDialog("No available marketplace!"); } @@ -1957,11 +1956,11 @@ void CAdventureOptions::showScenarioInfo() { if(LOCPLINT->cb->getStartInfo()->campState) { - GH.pushInt(new CBonusSelection()); + GH.pushIntT(); } else { - GH.pushInt(new CScenarioInfoScreen()); + GH.pushIntT(); } } diff --git a/client/windows/CAdvmapInterface.h b/client/windows/CAdvmapInterface.h index 72dfbc173..81a21a2cb 100644 --- a/client/windows/CAdvmapInterface.h +++ b/client/windows/CAdvmapInterface.h @@ -266,4 +266,4 @@ public: }; -extern CAdvMapInt *adventureInt; +extern std::shared_ptr adventureInt; diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 403f715e0..3733a20ee 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -41,13 +41,12 @@ #include "../../lib/mapObjects/CGTownInstance.h" CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town, const CStructure * Str) - : CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE | CShowableAnim::USE_RLE), + : CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE), parent(Par), town(Town), str(Str), stateCounter(80) { - recActions = ACTIVATE | DEACTIVATE | DISPOSE | SHARE_POS; addUsedEvents(LCLICK | RCLICK | HOVER); pos.x += str->pos.x; pos.y += str->pos.y; @@ -131,7 +130,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState) else { int level = ( bid - BuildingID::DWELL_FIRST ) % GameConstants::CREATURES_PER_TOWN; - GH.pushInt(new CDwellingInfoBox(parent->pos.x+parent->pos.w/2, parent->pos.y+parent->pos.h/2, town, level)); + GH.pushIntT(parent->pos.x+parent->pos.w/2, parent->pos.y+parent->pos.h/2, town, level); } } } @@ -421,7 +420,7 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState) { setHighlight(true); owner->garr->selectSlot(nullptr); - showAll(screen2); + redraw(); } //refresh statusbar @@ -434,7 +433,7 @@ void CHeroGSlot::clickRight(tribool down, bool previousState) { if(hero && down) { - GH.pushInt(new CInfoBoxPopup(Point(pos.x + 175, pos.y + 100), hero)); + GH.pushIntT(Point(pos.x + 175, pos.y + 100), hero); } } @@ -522,17 +521,26 @@ void HeroSlots::swapArmies() } -template class SORTHELP { public: - bool operator() (const std::shared_ptr a, const std::shared_ptr b) + bool operator() (const CIntObject * a, const CIntObject * b) { - return (*a)<(*b); + auto b1 = dynamic_cast(a); + auto b2 = dynamic_cast(b); + + if(!b1 && !b2) + return intptr_t(a) < intptr_t(b); + if(b1 && !b2) + return false; + if(!b1 && b2) + return true; + + return (*b1)<(*b2); } }; -SORTHELP buildSorter; +SORTHELP buildSorter; CCastleBuildings::CCastleBuildings(const CGTownInstance* Town): town(Town), @@ -552,8 +560,7 @@ CCastleBuildings::~CCastleBuildings() = default; void CCastleBuildings::recreate() { selectedBuilding = nullptr; - //TODO: remove show[all] method and try UPDATE+SHOWALL - OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(ACTIVATE+SHARE_POS); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); buildings.clear(); groups.clear(); @@ -600,7 +607,8 @@ void CCastleBuildings::recreate() buildings.push_back(std::make_shared(this, town, toAdd)); } - boost::sort(buildings, buildSorter); + + boost::sort(children, buildSorter); //TODO: create building in blit order } void CCastleBuildings::addBuilding(BuildingID building) @@ -632,20 +640,6 @@ void CCastleBuildings::removeBuilding(BuildingID building) recreate(); } -void CCastleBuildings::show(SDL_Surface * to) -{ - CIntObject::show(to); - for(auto str : buildings) - str->show(to); -} - -void CCastleBuildings::showAll(SDL_Surface * to) -{ - CIntObject::showAll(to); - for(auto str : buildings) - str->showAll(to); -} - const CGHeroInstance * CCastleBuildings::getHero() { if(town->visitingHero) @@ -689,7 +683,7 @@ void CCastleBuildings::buildingClicked(BuildingID building) case BuildingID::FORT: case BuildingID::CITADEL: case BuildingID::CASTLE: - GH.pushInt(new CFortScreen(town)); + GH.pushIntT(town); break; case BuildingID::VILLAGE_HALL: @@ -700,7 +694,7 @@ void CCastleBuildings::buildingClicked(BuildingID building) break; case BuildingID::MARKETPLACE: - GH.pushInt(new CMarketplaceWindow(town, town->visitingHero)); + GH.pushIntT(town, town->visitingHero); break; case BuildingID::BLACKSMITH: @@ -718,7 +712,7 @@ void CCastleBuildings::buildingClicked(BuildingID building) case ETownType::DUNGEON://Artifact Merchant case ETownType::CONFLUX: if(town->visitingHero) - GH.pushInt(new CMarketplaceWindow(town, town->visitingHero, EMarketMode::RESOURCE_ARTIFACT)); + GH.pushIntT(town, town->visitingHero, EMarketMode::RESOURCE_ARTIFACT); else LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s. break; @@ -742,14 +736,14 @@ void CCastleBuildings::buildingClicked(BuildingID building) case ETownType::STRONGHOLD: //Freelancer's Guild if(getHero()) - GH.pushInt(new CMarketplaceWindow(town, getHero(), EMarketMode::CREATURE_RESOURCE)); + GH.pushIntT(town, getHero(), EMarketMode::CREATURE_RESOURCE); else LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s. break; case ETownType::CONFLUX: //Magic University if (getHero()) - GH.pushInt(new CUniversityWindow(getHero(), town)); + GH.pushIntT(getHero(), town); else enterBuilding(building); break; @@ -772,7 +766,7 @@ void CCastleBuildings::buildingClicked(BuildingID building) break; case ETownType::NECROPOLIS: //Skeleton Transformer - GH.pushInt( new CTransformerWindow(getHero(), town) ); + GH.pushIntT(getHero(), town); break; case ETownType::DUNGEON: //Portal of Summoning @@ -810,7 +804,7 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID) int price = CGI->arth->artifacts[artifactID]->price; bool possible = LOCPLINT->cb->getResourceAmount(Res::GOLD) >= price && !hero->hasArt(artifactID); CreatureID cre = artifactID.toArtifact()->warMachine; - GH.pushInt(new CBlacksmithDialog(possible, cre, artifactID, hero->id)); + GH.pushIntT(possible, cre, artifactID, hero->id); } void CCastleBuildings::enterBuilding(BuildingID building) @@ -838,20 +832,20 @@ void CCastleBuildings::enterCastleGate() } } 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))); + GH.pushIntT(availableTowns, gateIcon, CGI->generaltexth->jktexts[40], + CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1)); } void CCastleBuildings::enterDwelling(int level) { assert(level >= 0 && level < town->creatures.size()); auto recruitCb = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level); }; - GH.pushInt(new CRecruitmentWindow(town, level, town, recruitCb, -87)); + GH.pushIntT(town, level, town, recruitCb, -87); } void CCastleBuildings::enterToTheQuickRecruitmentWindow() { - GH.pushInt(new QuickRecruitmentWindow(town, pos)); + GH.pushIntT(town, pos); } void CCastleBuildings::enterFountain(BuildingID building) @@ -915,7 +909,7 @@ void CCastleBuildings::enterTownHall() else { LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[673]); - dynamic_cast(GH.topInt())->buttons[0]->addCallback(std::bind(&CCastleBuildings::openTownHall, this)); + dynamic_cast(GH.topInt().get())->buttons[0]->addCallback(std::bind(&CCastleBuildings::openTownHall, this)); } } else @@ -928,12 +922,12 @@ void CCastleBuildings::openMagesGuild() { std::string mageGuildBackground; mageGuildBackground = LOCPLINT->castleInt->town->town->clientInfo.guildBackground; - GH.pushInt(new CMageGuildScreen(LOCPLINT->castleInt,mageGuildBackground)); + GH.pushIntT(LOCPLINT->castleInt,mageGuildBackground); } void CCastleBuildings::openTownHall() { - GH.pushInt(new CHallInterface(town)); + GH.pushIntT(town); } CCreaInfo::CCreaInfo(Point position, const CGTownInstance * Town, int Level, bool compact, bool ShowAvailable): @@ -1016,7 +1010,7 @@ void CCreaInfo::clickLeft(tribool down, bool previousState) { LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level); }; - GH.pushInt(new CRecruitmentWindow(town, level, town, recruitCb, offset)); + GH.pushIntT(town, level, town, recruitCb, offset); } } @@ -1036,7 +1030,7 @@ void CCreaInfo::clickRight(tribool down, bool previousState) if(down) { if (showAvailable) - GH.pushInt(new CDwellingInfoBox(screen->w/2, screen->h/2, town, level)); + GH.pushIntT(screen->w/2, screen->h/2, town, level); else CRClickPopup::createAndPush(genGrowthText(), std::make_shared(CComponent::creature, creature->idNumber)); } @@ -1141,7 +1135,8 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst CCastleInterface::~CCastleInterface() { - LOCPLINT->castleInt = nullptr; + if(LOCPLINT->castleInt == this) + LOCPLINT->castleInt = nullptr; } void CCastleInterface::updateGarrisons() @@ -1170,12 +1165,13 @@ void CCastleInterface::castleTeleport(int where) void CCastleInterface::townChange() { + //TODO: do not recreate window const CGTownInstance * dest = LOCPLINT->towns[townlist->getSelectedIndex()]; const CGTownInstance * town = this->town;// "this" is going to be deleted if ( dest == town ) return; close(); - GH.pushInt(new CCastleInterface(dest, town)); + GH.pushIntT(dest, town); } void CCastleInterface::addBuilding(BuildingID bid) @@ -1299,13 +1295,13 @@ void CHallInterface::CBuildingBox::hover(bool on) void CHallInterface::CBuildingBox::clickLeft(tribool down, bool previousState) { if(previousState && (!down)) - GH.pushInt(new CBuildWindow(town,building,state,0)); + GH.pushIntT(town,building,state,0); } void CHallInterface::CBuildingBox::clickRight(tribool down, bool previousState) { if(down) - GH.pushInt(new CBuildWindow(town,building,state,1)); + GH.pushIntT(town,building,state,1); } CHallInterface::CHallInterface(const CGTownInstance * Town): @@ -1756,7 +1752,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, Art animBG->needRefresh = true; const CCreature * creature = CGI->creh->creatures[creMachineID]; - anim = std::make_shared(64, 50, creature->animDefName, Rect()); + anim = std::make_shared(64, 50, creature->animDefName); anim->clipRect(113,125,200,150); title = std::make_shared(165, 28, FONT_BIG, CENTER, Colors::YELLOW, diff --git a/client/windows/CCastleInterface.h b/client/windows/CCastleInterface.h index f3fdb52e2..1bc020531 100644 --- a/client/windows/CCastleInterface.h +++ b/client/windows/CCastleInterface.h @@ -156,9 +156,6 @@ public: void buildingClicked(BuildingID building); void addBuilding(BuildingID building); void removeBuilding(BuildingID building);//FIXME: not tested!!! - - void show(SDL_Surface * to) override; - void showAll(SDL_Surface * to) override; }; /// Creature info window diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index 6a8b06361..2683506b4 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -78,8 +78,8 @@ void CHeroSwitcher::clickLeft(tribool down, bool previousState) owner->update(hero, true); #else const CGHeroInstance * buf = hero; - GH.popIntTotally(parent); - GH.pushInt(new CHeroWindow(buf)); + GH.popInts(1); + GH.pushIntT(buf); #endif // 0 } } @@ -297,16 +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(auto isa : GH.listInt) { - if(CExchangeWindow * cew = dynamic_cast(isa)) + if(CExchangeWindow * cew = dynamic_cast(isa.get())) { for(int g=0; g < cew->heroInst.size(); ++g) if(cew->heroInst[g] == curHero) noDismiss = true; } - if(dynamic_cast(isa)) + if(dynamic_cast(isa.get())) noDismiss = true; } //if player only have one hero and no towns @@ -374,7 +374,7 @@ void CHeroWindow::commanderWindow() } else { - GH.pushInt(new CStackWindow(curHero->commander, false)); + GH.pushIntT(curHero->commander, false); } } diff --git a/client/windows/CQuestLog.cpp b/client/windows/CQuestLog.cpp index 3218a2b05..3a8ae9811 100644 --- a/client/windows/CQuestLog.cpp +++ b/client/windows/CQuestLog.cpp @@ -40,8 +40,7 @@ void CQuestLabel::clickLeft(tribool down, bool previousState) void CQuestLabel::showAll(SDL_Surface * to) { - if (active) - CMultiLineLabel::showAll (to); + CMultiLineLabel::showAll (to); } CQuestIcon::CQuestIcon (const std::string &defname, int index, int x, int y) : @@ -204,8 +203,9 @@ void CQuestLog::recreateLabelList() void CQuestLog::showAll(SDL_Surface * to) { CWindowObject::showAll(to); - if(labels.size() && labels[questIndex]->active) + if(questIndex >= 0 && questIndex < labels.size()) { + //TODO: use child object to selection rect Rect rect = Rect::around(labels[questIndex]->pos); rect.x -= 2; // Adjustment needed as we want selection box on top of border in graphics rect.w += 2; diff --git a/client/windows/CSpellWindow.cpp b/client/windows/CSpellWindow.cpp index 623dee304..3931287e4 100644 --- a/client/windows/CSpellWindow.cpp +++ b/client/windows/CSpellWindow.cpp @@ -255,7 +255,7 @@ void CSpellWindow::fexitb() (myInt->battleInt ? myInt->spellbookSettings.spellbookLastTabBattle : myInt->spellbookSettings.spellbookLastTabAdvmap) = selectedTab; (myInt->battleInt ? myInt->spellbookSettings.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap) = currentPage; - GH.popIntTotally(this); + close(); } void CSpellWindow::fadvSpellsb() @@ -414,13 +414,13 @@ void CSpellWindow::setCurrentPage(int value) void CSpellWindow::turnPageLeft() { if(settings["video"]["spellbookAnimation"].Bool()) - CCS->videoh->openAndPlayVideo("PGTRNLFT.SMK", pos.x+13, pos.y+15, screen); + CCS->videoh->openAndPlayVideo("PGTRNLFT.SMK", pos.x+13, pos.y+15); } void CSpellWindow::turnPageRight() { if(settings["video"]["spellbookAnimation"].Bool()) - CCS->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15, screen); + CCS->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15); } void CSpellWindow::keyPressed(const SDL_KeyboardEvent & key) @@ -568,7 +568,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState) else //adventure spell { const CGHeroInstance * h = owner->myHero; - GH.popInt(owner); + GH.popInts(1); auto guard = vstd::makeScopeGuard([this]() { diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index 35db8683f..20e3cbbee 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -605,22 +605,19 @@ void CTradeWindow::setMode(EMarketMode::EMarketMode Mode) { const IMarket *m = market; const CGHeroInstance *h = hero; - CTradeWindow *nwindow = nullptr; - GH.popIntTotally(this); + close(); switch(Mode) { case EMarketMode::CREATURE_EXP: case EMarketMode::ARTIFACT_EXP: - nwindow = new CAltarWindow(m, h, Mode); + GH.pushIntT(m, h, Mode); break; default: - nwindow = new CMarketplaceWindow(m, h, Mode); + GH.pushIntT(m, h, Mode); break; } - - GH.pushInt(nwindow); } void CTradeWindow::artifactSelected(CHeroArtPlace *slot) diff --git a/client/windows/CWindowObject.cpp b/client/windows/CWindowObject.cpp index 6b1e95845..ef26f873c 100644 --- a/client/windows/CWindowObject.cpp +++ b/client/windows/CWindowObject.cpp @@ -34,8 +34,7 @@ #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt): - CIntObject(getUsedEvents(options_), Point()), - shadow(nullptr), + WindowBase(getUsedEvents(options_), Point()), options(options_), background(createBg(imageName, options & PLAYER_COLORED)) { @@ -56,7 +55,7 @@ CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt } CWindowObject::CWindowObject(int options_, std::string imageName): - CIntObject(getUsedEvents(options_), Point()), + WindowBase(getUsedEvents(options_), Point()), options(options_), background(createBg(imageName, options_ & PLAYER_COLORED)) { @@ -122,10 +121,10 @@ void CWindowObject::setShadow(bool on) //size of shadow static const int size = 8; - if(on == bool(shadow)) + if(on == !shadowParts.empty()) return; - shadow.reset(); + shadowParts.clear(); //object too small to cast shadow if(pos.h <= size || pos.w <= size) @@ -214,15 +213,11 @@ void CWindowObject::setShadow(bool on) //generate "shadow" object with these 3 pieces in it { OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); - shadow = std::make_shared(); - } - { - OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255); + shadowParts.push_back(std::make_shared(shadowCorner, shadowPos.x, shadowPos.y)); + shadowParts.push_back(std::make_shared(shadowRight, shadowPos.x, shadowStart.y)); + shadowParts.push_back(std::make_shared(shadowBottom, shadowStart.x, shadowPos.y)); - 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)); } } } @@ -238,11 +233,6 @@ void CWindowObject::showAll(SDL_Surface *to) CMessage::drawBorder(color, to, pos.w+28, pos.h+29, pos.x-14, pos.y-15); } -void CWindowObject::close() -{ - GH.popIntTotally(this); -} - void CWindowObject::clickRight(tribool down, bool previousState) { close(); diff --git a/client/windows/CWindowObject.h b/client/windows/CWindowObject.h index 44b5ca3b9..acdf01ccd 100644 --- a/client/windows/CWindowObject.h +++ b/client/windows/CWindowObject.h @@ -11,13 +11,13 @@ #include "../gui/CIntObject.h" -/// Basic class for windows -class CWindowObject : public CIntObject +class CWindowObject : public WindowBase { std::shared_ptr createBg(std::string imageName, bool playerColored); int getUsedEvents(int options); - std::shared_ptr shadow; + std::vector> shadowParts; + void setShadow(bool on); int options; @@ -25,8 +25,6 @@ class CWindowObject : public CIntObject protected: 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 diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 67ddf3592..ee210bc23 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -96,7 +96,7 @@ void CRecruitmentWindow::CCreatureCard::clickLeft(tribool down, bool previousSta void CRecruitmentWindow::CCreatureCard::clickRight(tribool down, bool previousState) { if(down) - GH.pushInt(new CStackWindow(creature, true)); + GH.pushIntT(creature, true); } void CRecruitmentWindow::CCreatureCard::showAll(SDL_Surface * to) @@ -569,8 +569,7 @@ void CSystemOptionsWindow::selectGameRes() items.push_back(resX + 'x' + resY); } - GH.pushInt(new CObjectListWindow(items, nullptr, texts["label"].String(), texts["help"].String(), - std::bind(&CSystemOptionsWindow::setGameRes, this, _1))); + GH.pushIntT(items, nullptr, texts["label"].String(), texts["help"].String(), std::bind(&CSystemOptionsWindow::setGameRes, this, _1)); } void CSystemOptionsWindow::setGameRes(int index) @@ -599,7 +598,7 @@ void CSystemOptionsWindow::bquitf() void CSystemOptionsWindow::breturnf() { - GH.popIntTotally(this); + close(); } void CSystemOptionsWindow::bmainmenuf() @@ -609,14 +608,14 @@ void CSystemOptionsWindow::bmainmenuf() void CSystemOptionsWindow::bloadf() { - GH.popIntTotally(this); + close(); LOCPLINT->proposeLoadingGame(); } void CSystemOptionsWindow::bsavef() { - GH.popIntTotally(this); - GH.pushInt(new CSavingScreen()); + close(); + GH.pushIntT(); } void CSystemOptionsWindow::brestartf() @@ -626,7 +625,7 @@ void CSystemOptionsWindow::brestartf() void CSystemOptionsWindow::closeAndPushEvent(int eventType, int code) { - GH.popIntTotally(this); + close(); GH.pushSDLEvent(eventType, code); } @@ -705,7 +704,7 @@ void CTavernWindow::recruitb() void CTavernWindow::thievesguildb() { - GH.pushInt( new CThievesGuildWindow(tavernObj) ); + GH.pushIntT(tavernObj); } CTavernWindow::~CTavernWindow() @@ -745,9 +744,7 @@ void CTavernWindow::HeroPortrait::clickLeft(tribool down, bool previousState) void CTavernWindow::HeroPortrait::clickRight(tribool down, bool previousState) { if(h && down) - { - GH.pushInt(new CRClickPopupInt(new CHeroWindow(h), true)); - } + GH.pushIntT(std::make_shared(h)); } CTavernWindow::HeroPortrait::HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H) @@ -990,7 +987,7 @@ CShipyardWindow::CShipyardWindow(const std::vector & cost, int state, int 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 = std::make_shared(boatFilenames[boatType], 0, 7, 120, 96, CShowableAnim::USE_RLE); + bgShip = std::make_shared(boatFilenames[boatType], 0, 7, 120, 96, 0); bgShip->center(waterCenter); // Create resource icons and costs. @@ -1110,7 +1107,7 @@ void CTransformerWindow::CItem::clickLeft(tribool down, bool previousState) if(previousState && (!down)) { move(); - parent->showAll(screen2); + parent->redraw(); } } @@ -1152,7 +1149,7 @@ void CTransformerWindow::addAll() if(elem->left) elem->move(); } - showAll(screen2); + redraw(); } void CTransformerWindow::updateGarrisons() @@ -1215,10 +1212,7 @@ void CUniversityWindow::CItem::clickLeft(tribool down, bool previousState) if(previousState && (!down)) { if(state() == 2) - { - auto win = new CUnivConfirmWindow(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000); - GH.pushInt(win); - } + GH.pushIntT(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000); } } @@ -1813,14 +1807,14 @@ void CObjectListWindow::elementSelected() { std::function toCall = onSelect;//save int where = items[selected].first; //required variables - GH.popIntTotally(this);//then destroy window + close();//then destroy window toCall(where);//and send selected object } void CObjectListWindow::exitPressed() { std::function toCall = onExit;//save - GH.popIntTotally(this);//then destroy window + close();//then destroy window if(toCall) toCall(); } diff --git a/client/windows/InfoWindows.cpp b/client/windows/InfoWindows.cpp index 9c1dae630..3a68d72bf 100644 --- a/client/windows/InfoWindows.cpp +++ b/client/windows/InfoWindows.cpp @@ -161,7 +161,8 @@ CInfoWindow::CInfoWindow() void CInfoWindow::close() { - GH.popIntTotally(this); + WindowBase::close(); + if(LOCPLINT) LOCPLINT->showingDialog->setn(false); } @@ -181,8 +182,7 @@ void CInfoWindow::showAll(SDL_Surface * to) void CInfoWindow::showInfoDialog(const std::string &text, const TCompsInfo & components, PlayerColor player) { - CInfoWindow * window = CInfoWindow::create(text, player, components); - GH.pushInt(window); + GH.pushInt(CInfoWindow::create(text, player, components)); } void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & components, const CFunctionList &onYes, const CFunctionList &onNo, PlayerColor player) @@ -191,7 +191,7 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & c 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, pom); + std::shared_ptr temp = std::make_shared(text, player, components, pom); temp->buttons[0]->addCallback( onYes ); temp->buttons[1]->addCallback( onNo ); @@ -199,22 +199,11 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & c GH.pushInt(temp); } -void CInfoWindow::showOkDialog(const std::string & text, const TCompsInfo & components, const std::function & onOk, PlayerColor player) +std::shared_ptr CInfoWindow::create(const std::string &text, PlayerColor playerID, const TCompsInfo & components) { std::vector > > pom; pom.push_back(std::pair >("IOKAY.DEF",0)); - 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 TCompsInfo & components) -{ - std::vector > > pom; - pom.push_back(std::pair >("IOKAY.DEF",0)); - CInfoWindow * ret = new CInfoWindow(text, playerID, components, pom); - return ret; + return std::make_shared(text, playerID, components, pom); } std::string CInfoWindow::genText(std::string title, std::string description) @@ -268,7 +257,7 @@ void CInfoPopup::close() { if(free) SDL_FreeSurface(bitmap); - GH.popIntTotally(this); + WindowBase::close(); } void CInfoPopup::show(SDL_Surface * to) @@ -307,7 +296,7 @@ void CRClickPopup::clickRight(tribool down, bool previousState) void CRClickPopup::close() { - GH.popIntTotally(this); + WindowBase::close(); } void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps) @@ -316,11 +305,11 @@ void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCom if(settings["session"]["spectate"].Bool())//TODO: there must be better way to implement this player = PlayerColor(1); - CSimpleWindow * temp = new CInfoWindow(txt, player, comps); + auto temp = std::make_shared(txt, player, comps); temp->center(Point(GH.current->motion)); //center on mouse temp->fitToScreen(10); - auto rcpi = new CRClickPopupInt(temp,true); - GH.pushInt(rcpi); + + GH.pushIntT(temp); } void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr component) @@ -331,14 +320,16 @@ void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptrcurHero()) + if(adventureInt->curHero()) CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero())); else CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID)); @@ -354,31 +345,20 @@ CRClickPopup::~CRClickPopup() { } -void CRClickPopupInt::show(SDL_Surface * to) -{ - inner->show(to); -} - -CRClickPopupInt::CRClickPopupInt( IShowActivatable *our, bool deleteInt ) +CRClickPopupInt::CRClickPopupInt(std::shared_ptr our) { CCS->curh->hide(); + defActions = SHOWALL | UPDATE; + our->recActions = defActions; inner = our; - delInner = deleteInt; + addChild(our.get(), false); } CRClickPopupInt::~CRClickPopupInt() { - if(delInner) - delete inner; - CCS->curh->show(); } -void CRClickPopupInt::showAll(SDL_Surface * to) -{ - inner->showAll(to); -} - Point CInfoBoxPopup::toScreen(Point p) { vstd::abetween(p.x, adventureInt->terrain.pos.x + 100, adventureInt->terrain.pos.x + adventureInt->terrain.pos.w - 100); @@ -417,7 +397,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr) tooltip = std::make_shared(Point(9, 10), iah); } -CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero +std::shared_ptr CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero { if(nullptr == specific) specific = adventureInt->selection; @@ -431,13 +411,13 @@ CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance switch(specific->ID) { case Obj::HERO: - return new CInfoBoxPopup(position, dynamic_cast(specific)); + return std::make_shared(position, dynamic_cast(specific)); case Obj::TOWN: - return new CInfoBoxPopup(position, dynamic_cast(specific)); + return std::make_shared(position, dynamic_cast(specific)); case Obj::GARRISON: case Obj::GARRISON2: - return new CInfoBoxPopup(position, dynamic_cast(specific)); + return std::make_shared(position, dynamic_cast(specific)); default: - return nullptr; + return std::shared_ptr(); } } diff --git a/client/windows/InfoWindows.h b/client/windows/InfoWindows.h index 8640cf84d..95924308d 100644 --- a/client/windows/InfoWindows.h +++ b/client/windows/InfoWindows.h @@ -26,11 +26,11 @@ class CSlider; class CArmyTooltip; // Window GUI class -class CSimpleWindow : public CIntObject +class CSimpleWindow : public WindowBase { public: SDL_Surface * bitmap; //background - virtual void show(SDL_Surface * to) override; + void show(SDL_Surface * to) override; CSimpleWindow():bitmap(nullptr){}; virtual ~CSimpleWindow(); }; @@ -58,16 +58,15 @@ public: //use only before the game starts! (showYesNoDialog in LOCPLINT must be used then) 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()); + static std::shared_ptr 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); }; /// popup displayed on R-click -class CRClickPopup : public CIntObject +class CRClickPopup : public WindowBase { public: virtual void close(); @@ -76,7 +75,7 @@ public: CRClickPopup(); virtual ~CRClickPopup(); - static CIntObject* createInfoWin(Point position, const CGObjectInstance * specific); + static std::shared_ptr 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, std::shared_ptr component); static void createAndPush(const CGObjectInstance * obj, const Point & p, EAlignment alignment = BOTTOMRIGHT); @@ -85,13 +84,9 @@ public: /// popup displayed on R-click class CRClickPopupInt : public CRClickPopup { + std::shared_ptr inner; public: - IShowActivatable *inner; - bool delInner; - - void show(SDL_Surface * to) override; - void showAll(SDL_Surface * to) override; - CRClickPopupInt(IShowActivatable *our, bool deleteInt); + CRClickPopupInt(std::shared_ptr our); virtual ~CRClickPopupInt(); }; @@ -123,11 +118,11 @@ public: /// component selection window class CSelWindow : public CInfoWindow -{ //warning - this window deletes its components by closing! +{ 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(){}; + CSelWindow(const std::string & text, PlayerColor player, int charperline, const std::vector> & comps, const std::vector > > &Buttons, QueryID askID); + //notification - this class inherits important destructor from CInfoWindow };