瀏覽代碼

Gui cleanup4 (#446)

* use smart pointers for almost all widget fields
* use SDL2 texture for cursor
* a lot af small tweaks and formatting
* removed CompImage class, it is actually useless as long as regular SDLImage support margins
* CGuiHandler: use smart pointers for [push|pop]Int
Alexander Shishkin 7 年之前
父節點
當前提交
75f8c8b29a
共有 62 個文件被更改,包括 701 次插入1291 次删除
  1. 1 1
      CCallback.cpp
  2. 3 3
      CCallback.h
  3. 2 2
      client/CBitmapHandler.cpp
  4. 116 66
      client/CMT.cpp
  5. 1 1
      client/CMessage.cpp
  6. 3 6
      client/CMessage.h
  7. 75 97
      client/CPlayerInterface.cpp
  8. 1 2
      client/CPlayerInterface.h
  9. 3 3
      client/CServerHandler.cpp
  10. 4 5
      client/CVideoHandler.cpp
  11. 3 3
      client/CVideoHandler.h
  12. 3 10
      client/Client.cpp
  13. 4 4
      client/NetPacksLobbyClient.cpp
  14. 1 1
      client/battle/CBattleAnimations.cpp
  15. 1 1
      client/battle/CBattleAnimations.h
  16. 60 92
      client/battle/CBattleInterface.cpp
  17. 21 10
      client/battle/CBattleInterface.h
  18. 8 7
      client/battle/CBattleInterfaceClasses.cpp
  19. 2 2
      client/battle/CBattleInterfaceClasses.h
  20. 2 2
      client/battle/CCreatureAnimation.cpp
  21. 1 1
      client/battle/CCreatureAnimation.h
  22. 25 574
      client/gui/CAnimation.cpp
  23. 2 5
      client/gui/CAnimation.h
  24. 77 43
      client/gui/CCursorHandler.cpp
  25. 14 9
      client/gui/CCursorHandler.h
  26. 19 23
      client/gui/CGuiHandler.cpp
  27. 16 6
      client/gui/CGuiHandler.h
  28. 14 16
      client/gui/CIntObject.cpp
  29. 9 4
      client/gui/CIntObject.h
  30. 2 2
      client/gui/SDL_Extensions.cpp
  31. 5 5
      client/lobby/CBonusSelection.cpp
  32. 6 2
      client/lobby/CLobbyScreen.cpp
  33. 1 1
      client/lobby/CLobbyScreen.h
  34. 1 1
      client/lobby/CSavingScreen.cpp
  35. 1 1
      client/lobby/CScenarioInfoScreen.cpp
  36. 1 1
      client/lobby/CScenarioInfoScreen.h
  37. 2 2
      client/lobby/CSelectionBase.cpp
  38. 1 1
      client/lobby/OptionsTab.cpp
  39. 1 2
      client/mainmenu/CCampaignScreen.cpp
  40. 24 25
      client/mainmenu/CMainMenu.cpp
  41. 7 7
      client/mainmenu/CMainMenu.h
  42. 1 1
      client/mainmenu/CPrologEpilogVideo.cpp
  43. 5 27
      client/widgets/AdventureMapClasses.cpp
  44. 3 4
      client/widgets/AdventureMapClasses.h
  45. 3 3
      client/widgets/CArtifactHolder.cpp
  46. 5 5
      client/widgets/CGarrisonInt.cpp
  47. 7 12
      client/widgets/Images.cpp
  48. 2 4
      client/widgets/Images.h
  49. 1 1
      client/widgets/MiscWidgets.cpp
  50. 11 12
      client/windows/CAdvmapInterface.cpp
  51. 1 1
      client/windows/CAdvmapInterface.h
  52. 43 47
      client/windows/CCastleInterface.cpp
  53. 0 3
      client/windows/CCastleInterface.h
  54. 6 6
      client/windows/CHeroWindow.cpp
  55. 3 3
      client/windows/CQuestLog.cpp
  56. 4 4
      client/windows/CSpellWindow.cpp
  57. 3 6
      client/windows/CTradeWindow.cpp
  58. 7 17
      client/windows/CWindowObject.cpp
  59. 3 5
      client/windows/CWindowObject.h
  60. 15 21
      client/windows/GUIClasses.cpp
  61. 25 45
      client/windows/InfoWindows.cpp
  62. 10 15
      client/windows/InfoWindows.h

+ 1 - 1
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);

+ 3 - 3
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<PlayerColor> 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;

+ 2 - 2
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<height; i++)
@@ -89,7 +89,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
 		int gmask = 0x00ff00;
 		int rmask = 0xff0000;
 #endif
-		ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, rmask, gmask, bmask, 0);
+		ret = SDL_CreateRGBSurface(0, width, height, 24, rmask, gmask, bmask, 0);
 
 		//it == 0xC;
 		for (int i=0; i<height; i++)

+ 116 - 66
client/CMT.cpp

@@ -118,32 +118,13 @@ static void mainLoop();
 
 void init()
 {
-	CStopWatch tmh, pomtime;
+	CStopWatch tmh;
 
 	loadDLLClasses();
 	const_cast<CGameInfo*>(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<const CIntObject *>(child))
+			if(const CIntObject *obj = dynamic_cast<const CIntObject *>(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,46 +1072,84 @@ 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();
+	if(nullptr == mainWindow)
+	{
 
-#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
+	#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);
 
-	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
+#ifndef VCMI_ANDROID
 
-	if(nullptr == mainWindow)
-	{
-		throw std::runtime_error("Unable to create window\n");
-	}
+		if(fullscreen)
+		{
+			if(realFullscreen)
+			{
+				SDL_SetWindowFullscreen(mainWindow, SDL_WINDOW_FULLSCREEN);
 
+				SDL_DisplayMode mode;
+				SDL_GetDesktopDisplayMode(displayIndex, &mode);
+				mode.w = w;
+				mode.h = h;
 
-	//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);
+				SDL_SetWindowDisplayMode(mainWindow, &mode);
+			}
+			else
+			{
+				SDL_SetWindowFullscreen(mainWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
+			}
 
-	if(nullptr == mainRenderer)
-	{
-		throw std::runtime_error("Unable to create renderer\n");
-	}
+			SDL_SetWindowPosition(mainWindow, SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex));
 
-	SDL_RendererInfo info;
-	SDL_GetRendererInfo(mainRenderer, &info);
-	logGlobal->info("Created renderer %s", info.name);
+			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(!(fullscreen && realFullscreen))
 	{
@@ -1270,7 +1300,7 @@ static void handleEvent(SDL_Event & ev)
 				};
 				if(epilogue.hasPrologEpilog)
 				{
-					GH.pushInt(new CPrologEpilogVideo(epilogue, finisher));
+					GH.pushIntT<CPrologEpilogVideo>(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<boost::mutex> 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();
 		}
 

+ 1 - 1
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; i<w; i+=background->w)//background
 	{
 		for (int j=0; j<h; j+=background->h)

+ 3 - 6
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<int,int> getMaxSizes(std::vector<std::vector<SDL_Surface*> > * txtg, int fontHeight);
+	/// 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);
 
-	/// Draw simple dialog box (borders and background only)
-	static SDL_Surface * drawDialogBox(int w, int h, PlayerColor playerColor = PlayerColor(1));
-
 	static void drawIWindow(CInfoWindow * ret, std::string text, PlayerColor player);
 
 	/// split text in lines

+ 75 - 97
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<bool>(false);
 	cingconsole = new CInGameConsole();
@@ -150,9 +150,7 @@ void CPlayerInterface::init(std::shared_ptr<CCallback> 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;
+
+	auto newCastleInt = std::make_shared<CCastleInterface>(town);
 
-	castleInt = new CCastleInterface(town);
-	GH.pushInt(castleInt);
+	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<CAltarWindow *>(GH.topInt()))
+		if (CAltarWindow *ctw = dynamic_cast<CAltarWindow *>(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<CUniversityWindow*>(GH.topInt());
+	CUniversityWindow* cuw = dynamic_cast<CUniversityWindow*>(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<CMarketplaceWindow *>(GH.topInt()))
+	if (CMarketplaceWindow *mw = dynamic_cast<CMarketplaceWindow *>(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<CLevelWindow>(hero, pskill, skills, [=](ui32 selection)
+	{
+		cb->selectionMade(selection, queryID);
+	});
 }
+
 void CPlayerInterface::commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	waitWhileDialog();
 	CCS->soundh->playSound(soundBase::heroNewLevel);
-
-	GH.pushInt(new CStackWindow(commander, skills, [=](ui32 selection)
+	GH.pushIntT<CStackWindow>(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<CKingdomInterface*>(isa);
+		CKingdomInterface *ki = dynamic_cast<CKingdomInterface*>(isa.get());
 		if (ki)
 		{
 			ki->townChanged(town);
@@ -632,11 +632,11 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob
 
 	for (auto & elem : GH.listInt)
 	{
-		CGarrisonHolder *cgh = dynamic_cast<CGarrisonHolder*>(elem);
+		CGarrisonHolder *cgh = dynamic_cast<CGarrisonHolder*>(elem.get());
 		if (cgh)
 			cgh->updateGarrisons();
 
-		if (CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(elem))
+		if (CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(elem.get()))
 		{
 			if (vstd::contains(objs, cmw->hero))
 				cmw->garrisonChanged();
@@ -739,7 +739,7 @@ void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & 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<CBattleResultWindow>(*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<CInfoWindow> 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<vo
 	CInfoWindow::showYesNoDialog(text, components, onYes, onNo, playerID);
 }
 
-void CPlayerInterface::showOkDialog(std::vector<Component> & components, const MetaString & text, const std::function<void()> & onOk)
-{
-	boost::unique_lock<boost::recursive_mutex> un(*pim);
-
-	std::string str;
-	text.toString(str);
-
-	stopMovement();
-	showingDialog->setn(true);
-
-	std::vector<std::shared_ptr<CComponent>> intComps;
-	for (auto & component : components)
-		intComps.push_back(std::make_shared<CComponent>(component));
-	CInfoWindow::showOkDialog(str, intComps, onOk, playerID);
-}
-
 void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &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<CSelWindow>(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<CIntObject> localIcon = localIconC->image;
-	localIconC->removeChild(localIcon.get(), false);
-	delete localIconC;
+	std::shared_ptr<CIntObject> localIcon = localIconC.image;
+	localIconC.removeChild(localIcon.get(), false);
 
-	CObjectListWindow * wnd = new CObjectListWindow(tempList, localIcon, localTitle, localDescription, selectCallback);
+	std::shared_ptr<CObjectListWindow> wnd = std::make_shared<CObjectListWindow>(tempList, localIcon, localTitle, localDescription, selectCallback);
 	wnd->onExit = cancelCallback;
 	GH.pushInt(wnd);
 }
@@ -1289,7 +1269,7 @@ void CPlayerInterface::tileHidden(const std::unordered_set<int3, ShashInt3> &pos
 void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	GH.pushInt(new CHeroWindow(hero));
+	GH.pushIntT<CHeroWindow>(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<const CGTownInstance*>(town))
 	{
-		CFortScreen *fs = dynamic_cast<CFortScreen*>(GH.topInt());
+		CFortScreen *fs = dynamic_cast<CFortScreen*>(GH.topInt().get());
 		if (fs)
 			fs->creaturesChanged();
 
-		for (IShowActivatable *isa : GH.listInt)
+		for(auto isa : GH.listInt)
 		{
-			CKingdomInterface *ki = dynamic_cast<CKingdomInterface*>(isa);
+			CKingdomInterface *ki = dynamic_cast<CKingdomInterface*>(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<CRecruitmentWindow*>(GH.topInt());
+		CRecruitmentWindow *crw = dynamic_cast<CRecruitmentWindow*>(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<CGarrisonWindow>(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<CExchangeWindow>(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<CRecruitmentWindow>(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<si32> cost;
 	obj->getBoatCost(cost);
-	CShipyardWindow *csw = new CShipyardWindow(cost, state, obj->getBoatType(), [=](){ cb->buildBoat(obj); });
-	GH.pushInt(csw);
+	GH.pushIntT<CShipyardWindow>(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<CPuzzleWindow>(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<CSpellWindow *>(GH.topInt()))
-		GH.popIntTotally(GH.topInt());
+	if(dynamic_cast<CSpellWindow *>(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<CInfoWindow *>(GH.topInt()))
+		while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(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<CInfoWindow *>(GH.topInt()))
+		if(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(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<CAltarWindow>(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<CAltarWindow>(market, visitor, EMarketMode::CREATURE_EXP);
 	}
 	else
-		GH.pushInt(new CMarketplaceWindow(market, visitor, market->availableModes().front()));
+	{
+		GH.pushIntT<CMarketplaceWindow>(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<CUniversityWindow>(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<CHillFortWindow>(visitor, object);
 }
 
 void CPlayerInterface::availableArtifactsChanged(const CGBlackMarket * bm)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
-	if (CMarketplaceWindow *cmw = dynamic_cast<CMarketplaceWindow*>(GH.topInt()))
+	if (CMarketplaceWindow *cmw = dynamic_cast<CMarketplaceWindow*>(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<CTavernWindow>(townOrTavern);
 }
 
 void CPlayerInterface::showThievesGuildWindow (const CGObjectInstance * obj)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
-	auto  tgw = new CThievesGuildWindow(obj);
-	GH.pushInt(tgw);
+	GH.pushIntT<CThievesGuildWindow>(obj);
 }
 
 void CPlayerInterface::showQuestLog()
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
-	CQuestLog * ql = new CQuestLog (LOCPLINT->cb->getMyQuests());
-	GH.pushInt (ql);
+	GH.pushIntT<CQuestLog>(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<CArtifactHolder*>(isa);
+		auto artWin = dynamic_cast<CArtifactHolder*>(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<CArtifactHolder*>(isa);
+		auto artWin = dynamic_cast<CArtifactHolder*>(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<CArtifactHolder*>(isa);
+		auto artWin = dynamic_cast<CArtifactHolder*>(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<CArtifactHolder*>(isa);
+		auto artWin = dynamic_cast<CArtifactHolder*>(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<CInfoWindow*>(GH.listInt.front())) //don't remove dialogs that expect query answer
+		while (GH.listInt.front() != adventureInt && !dynamic_cast<CInfoWindow*>(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<CAdvMapInt *>(GH.topInt()))
+	else if(!dynamic_cast<CAdvMapInt *>(GH.topInt().get()))
 	{
 		return;
 	}

+ 1 - 2
client/CPlayerInterface.h

@@ -82,7 +82,7 @@ public:
 	std::shared_ptr<CCallback> cb; //to communicate with engine
 	const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr)
 
-	std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
+	std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
 
 	std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
 	std::vector<const CGTownInstance *> towns; //our towns on the adventure map
@@ -217,7 +217,6 @@ public:
 	void showInfoDialog(const std::string &text, std::shared_ptr<CComponent> component);
 	void showInfoDialog(const std::string &text, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>(), int soundID = 0);
 	void showInfoDialogAndWait(std::vector<Component> & components, const MetaString & text);
-	void showOkDialog(std::vector<Component> & components, const MetaString & text, const std::function<void()> & onOk);
 	void showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>());
 
 	void stopMovement();

+ 3 - 3
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<CLobbyScreen *>(GH.topInt()))
+	while(!settings["session"]["headless"].Bool() && !dynamic_cast<CLobbyScreen *>(GH.topInt().get()))
 		boost::this_thread::sleep(boost::posix_time::milliseconds(50));
 	while(!mi || mapInfo->fileURI != CSH->mi->fileURI)
 	{

+ 4 - 5
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;
 }

+ 3 - 3
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;};

+ 3 - 10
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<boost::recursive_mutex> 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<CBattleInterface>(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<CPlayerInterface>(playerint[PlayerColor::SPECTATOR]);
 			spectratorInt->cb->setBattle(info);
 			boost::unique_lock<boost::recursive_mutex> 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<CBattleInterface>(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, battleIntRect, att, def, spectratorInt);
 		}
 	}
 

+ 4 - 4
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<ESelectionScreen>(handler->screenType)));
+			GH.pushIntT<CLobbyScreen>(static_cast<ESelectionScreen>(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<CLoadingScreen>(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<CBonusSelection>();
 		GH.pushInt(lobby->bonusSel);
 	}
 

+ 1 - 1
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;
 

+ 1 - 1
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<CCreatureAnimation> myAnim; //animation for our stack, managed by CBattleInterface
 	const CStack * stack; //id of stack whose animation it is
 
 	CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack);

+ 60 - 92
client/battle/CBattleInterface.cpp

@@ -47,7 +47,7 @@
 CondSh<bool> CBattleInterface::animsAreDisplayed(false);
 CondSh<BattleAction *> CBattleInterface::givenCommand(nullptr);
 
-static void onAnimationFinished(const CStack *stack, CCreatureAnimation *anim)
+static void onAnimationFinished(const CStack *stack, std::shared_ptr<CCreatureAnimation> 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<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen, std::shared_ptr<CPlayerInterface> 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<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen, std::shared_ptr<CPlayerInterface> 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<CStackQueue>(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<const CStack*> 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<CButton>(Point(  3, 561), "icm003.def", CGI->generaltexth->zelp[381], std::bind(&CBattleInterface::bOptionsf,this), SDLK_o);
+	bSurrender = std::make_shared<CButton>(Point( 54, 561), "icm001.def", CGI->generaltexth->zelp[379], std::bind(&CBattleInterface::bSurrenderf,this), SDLK_s);
+	bFlee = std::make_shared<CButton>(Point(105, 561), "icm002.def", CGI->generaltexth->zelp[380], std::bind(&CBattleInterface::bFleef,this), SDLK_r);
+	bAutofight = std::make_shared<CButton>(Point(157, 561), "icm004.def", CGI->generaltexth->zelp[382], std::bind(&CBattleInterface::bAutofightf,this), SDLK_a);
+	bSpell = std::make_shared<CButton>(Point(645, 561), "icm005.def", CGI->generaltexth->zelp[385], std::bind(&CBattleInterface::bSpellf,this), SDLK_c);
+	bWait = std::make_shared<CButton>(Point(696, 561), "icm006.def", CGI->generaltexth->zelp[386], std::bind(&CBattleInterface::bWaitf,this), SDLK_w);
+	bDefence = std::make_shared<CButton>(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<CButton>(Point(624, 561), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleUpf,this), SDLK_UP);
+	bConsoleDown = std::make_shared<CButton>(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<CBattleConsole>();
 	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<CButton>(Point(213, 560), "icm011.def", std::make_pair("", ""), [&](){ bTacticNextStack(nullptr);}, SDLK_SPACE);
+		btactEnd = std::make_shared<CButton>(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<CBattleHero>(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<CBattleHero>(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<CClickableHex>();
 		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<CClickableHex> 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<CBattleOptionsWindow>(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<CSpellWindow>(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<CBattleResultWindow>(*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<BattleAction>();
 	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<CStackWindow>(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;

+ 21 - 10
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<CButton> bOptions;
+	std::shared_ptr<CButton> bSurrender;
+	std::shared_ptr<CButton> bFlee;
+	std::shared_ptr<CButton> bAutofight;
+	std::shared_ptr<CButton> bSpell;
+	std::shared_ptr<CButton> bWait;
+	std::shared_ptr<CButton> bDefence;
+	std::shared_ptr<CButton> bConsoleUp;
+	std::shared_ptr<CButton> bConsoleDown;
+	std::shared_ptr<CButton> btactNext;
+	std::shared_ptr<CButton> btactEnd;
+
+	std::shared_ptr<CBattleConsole> console;
+	std::shared_ptr<CBattleHero> attackingHero;
+	std::shared_ptr<CBattleHero> defendingHero;
+	std::shared_ptr<CStackQueue> queue;
+
 	const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
 	const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
-	std::map<int, CCreatureAnimation *> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
+	std::map<int32_t, std::shared_ptr<CCreatureAnimation>> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
 
 	std::map<int, std::shared_ptr<CAnimation>> 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<BattleAction> spellToCast; //spell for which player is choosing destination
 	const CSpell *sp; //spell pointer for convenience
 	si32 creatureSpellToCast;
 	std::vector<PossibleActions> 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<CClickableHex*> bfield; //11 lines, 17 hexes on each
+	std::vector<std::shared_ptr<CClickableHex>> 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

+ 8 - 7
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<CSpellWindow>(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<CHeroInfoWindow>(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<CBattleInterface*>(GH.topInt()))
+
+	close();
+
+	if(dynamic_cast<CBattleInterface*>(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<CStackWindow>(myst, true);
 		}
 	}
 }

+ 2 - 2
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<CPicture> 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<CPicture> background;

+ 2 - 2
client/battle/CCreatureAnimation.cpp

@@ -34,10 +34,10 @@ SDL_Color AnimationControls::getNoBorder()
 	return creatureNoBorder;
 }
 
-CCreatureAnimation * AnimationControls::getAnimation(const CCreature * creature)
+std::shared_ptr<CCreatureAnimation> AnimationControls::getAnimation(const CCreature * creature)
 {
 	auto func = std::bind(&AnimationControls::getCreatureAnimationSpeed, creature, _1, _2);
-	return new CCreatureAnimation(creature->animDefName, func);
+	return std::make_shared<CCreatureAnimation>(creature->animDefName, func);
 }
 
 float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, const CCreatureAnimation * anim, size_t group)

+ 1 - 1
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<CCreatureAnimation> 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);

+ 25 - 574
client/gui/CAnimation.cpp

@@ -23,7 +23,6 @@
 #include "../lib/CRandomGenerator.h"
 
 class SDLImageLoader;
-class CompImageLoader;
 
 typedef std::map <size_t, std::vector <JsonNode> > source_map;
 typedef std::map<size_t, IImage* > 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<int bpp, int dir>
-	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<IImage> 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<size_t>(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_t>(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 <sourceRect.h; currY++)
-	{
-		ui8* data = surf + line[currY+sourceRect.y];
-		ui8 type = *(data++);
-		ui8 size = *(data++);
-		int currX = sourceRect.x;
-
-		//Skip blocks until starting position reached
-		while ( currX > 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<IImage> CompImage::scaleFast(float scale) const
-{
-	//todo: CompImage::scaleFast
-
-	logAnim->error("CompImage::scaleFast is not implemented");
-
-    return nullptr;
-}
-
-#define CASEBPP(x,y) case x: BlitBlock<x,y>(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<int bpp, int dir>
-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<size; i++)
-			{
-				SDL_Color col = palette[*(data++)];
-				col.a = (ui32)col.a*alpha/255;
-				ColorPutter<bpp, 1>::PutColorAlpha(dest, col);
-			}
-			return;
-		}
-
-		if (palette[color].a == 255)
-		{
-			//Put row of RGB data
-			for (size_t i=0; i<size; i++)
-				ColorPutter<bpp, 1>::PutColor(dest, palette[*(data++)]);
-		}
-		else
-		{
-			//Put row of RGBA data
-			for (size_t i=0; i<size; i++)
-				ColorPutter<bpp, 1>::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<size; i++)
-				ColorPutter<bpp, 1>::PutColorAlpha(dest, col);
-			return;
-		}
-
-		switch (palette[type].a)
-		{
-			case 0:
-			{
-				//Skip row
-				dest += size*bpp;
-				break;
-			}
-			case 255:
-			{
-				//Put RGB row
-				ColorPutter<bpp, 1>::PutColorRow(dest, palette[type], size);
-				break;
-			}
-			default:
-			{
-				//Put RGBA row
-				for (size_t i=0; i<size; i++)
-					ColorPutter<bpp, 1>::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<IImage> 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<CompImage>(defFile, frame, group);
-				else
-					images[group][frame] = std::make_shared<SDLImage>(defFile, frame, group);
+				images[group][frame] = std::make_shared<SDLImage>(defFile.get(), frame, group);
 				return true;
 			}
 		}
 		// still here? image is missing
 
 		printError(frame, group, "LoadFrame");
-		images[group][frame] = std::make_shared<SDLImage>("DEFAULT", compressed);
+		images[group][frame] = std::make_shared<SDLImage>("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<CDefFile>(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]);
 

+ 2 - 5
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<CDefFile> 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<IImage> getFromExtraDef(std::string filename);
 
 public:
-	CAnimation(std::string Name, bool Compressed = false);
+	CAnimation(std::string Name);
 	CAnimation();
 	~CAnimation();
 

+ 77 - 43
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<CAnimImage> 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);
+}
+
+void CCursorHandler::updateTexture()
+{
+	if(needUpdate)
+	{
+		SDL_UpdateTexture(cursorLayer, nullptr, buffer->pixels, buffer->pitch);
+		needUpdate = false;
+	}
 }
 
-CCursorHandler::CCursorHandler() = default;
+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);
 }

+ 14 - 9
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<CAnimImage> 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);

+ 19 - 23
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<IShowActivatable> 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<IShowActivatable> 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<IShowActivatable> CGuiHandler::topInt()
 {
 	if(listInt.empty())
-		return nullptr;
+		return std::shared_ptr<IShowActivatable>();
 	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

+ 16 - 6
client/gui/CGuiHandler.h

@@ -58,10 +58,12 @@ class CGuiHandler
 {
 public:
 	CFramerateManager * mainFPSmng; //to keep const framerate
-	std::list<IShowActivatable *> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
+	std::list<std::shared_ptr<IShowActivatable>> 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<std::shared_ptr<IShowActivatable>> disposed;
+
 	std::atomic<bool> continueEventHandling;
 	typedef std::list<CIntObject*> CIntObjectList;
 
@@ -86,7 +88,7 @@ public:
 
 public:
 	//objs to blit
-	std::vector<IShowable*> objsToBlit;
+	std::vector<std::shared_ptr<IShowActivatable>> 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<IShowActivatable> newInt); //deactivate old top interface, activates this one and pushes to the top
+	template <typename T, typename ... Args>
+	void pushIntT(Args && ... args)
+	{
+		auto newInt = std::make_shared<T>(std::forward<Args>(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<IShowActivatable> top); //removes given interface from the top and activates next
+
+	std::shared_ptr<IShowActivatable> topInt(); //returns top interface
 
 	void updateTime(); //handles timeInterested
 	void handleEvents(); //takes events from queue and calls interested objects

+ 14 - 16
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);
+}

+ 9 - 4
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<int> 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();
+};

+ 2 - 2
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<bpp>::b.set((Uint8*)&bMask, 255);
 	Channels::px<bpp>::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)

+ 5 - 5
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<CPrologEpilogVideo>(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();

+ 6 - 2
client/lobby/CLobbyScreen.cpp

@@ -88,7 +88,11 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType)
 
 	buttonStart->assignedKeys.insert(SDLK_RETURN);
 
-	buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [&](){CSH->sendClientDisconnecting(); GH.popIntTotally(this);}, SDLK_ESCAPE);
+	buttonBack = std::make_shared<CButton>(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(...)
 	{

+ 1 - 1
client/lobby/CLobbyScreen.h

@@ -31,5 +31,5 @@ public:
 	const CMapInfo * getMapInfo() override;
 	const StartInfo * getStartInfo() override;
 
-	CBonusSelection * bonusSel;
+	std::shared_ptr<CBonusSelection> bonusSel;
 };

+ 1 - 1
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)))

+ 1 - 1
client/lobby/CScenarioInfoScreen.cpp

@@ -39,7 +39,7 @@ CScenarioInfoScreen::CScenarioInfoScreen()
 	card->changeSelection();
 
 	card->iconDifficulty->setSelected(getCurrentDifficulty());
-	buttonBack = std::make_shared<CButton>(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], std::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE);
+	buttonBack = std::make_shared<CButton>(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, SDLK_ESCAPE);
 }
 
 CScenarioInfoScreen::~CScenarioInfoScreen()

+ 1 - 1
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<CButton> buttonBack;

+ 2 - 2
client/lobby/CSelectionBase.cpp

@@ -86,7 +86,7 @@ CSelectionBase::CSelectionBase(ESelectionScreen type)
 	}
 	pos = background->center();
 	card = std::make_shared<InfoCard>();
-	buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], std::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE);
+	buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, SDLK_ESCAPE);
 }
 
 void CSelectionBase::toggleTab(std::shared_ptr<CIntObject> 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<CFlagBoxTooltipBox>(iconsTeamFlags);
 }
 
 CFlagBox::CFlagBoxTooltipBox::CFlagBoxTooltipBox(std::shared_ptr<CAnimation> icons)

+ 1 - 1
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<CPlayerOptionTooltipBox>(*this);
 	}
 }
 

+ 1 - 2
client/mainmenu/CCampaignScreen.cpp

@@ -79,8 +79,7 @@ std::shared_ptr<CButton> CCampaignScreen::createExitButton(const JsonNode & butt
 	if(!button["help"].isNull() && button["help"].Float() > 0)
 		help = CGI->generaltexth->zelp[button["help"].Float()];
 
-	std::function<void()> close = std::bind(&CGuiHandler::popIntTotally, &GH, this);
-	return std::make_shared<CButton>(Point(button["x"].Float(), button["y"].Float()), button["name"].String(), help, close, button["hotkey"].Float());
+	return std::make_shared<CButton>(Point(button["x"].Float(), button["y"].Float()), button["name"].String(), help, [=](){ close();}, button["hotkey"].Float());
 }
 
 CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config)

+ 24 - 25
client/mainmenu/CMainMenu.cpp

@@ -60,7 +60,7 @@
 
 namespace fs = boost::filesystem;
 
-CMainMenu * CMM = nullptr;
+std::shared_ptr<CMainMenu> CMM;
 ISelectionScreenInfo * SEL;
 
 static void do_quit()
@@ -176,7 +176,7 @@ static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::str
 				case 0:
 					return std::bind(CMainMenu::openLobby, ESelectionScreen::newGame, true, nullptr, ELoadMode::NONE);
 				case 1:
-					return []() { GH.pushInt(new CMultiMode(ESelectionScreen::newGame)); };
+					return []() { GH.pushIntT<CMultiMode>(ESelectionScreen::newGame); };
 				case 2:
 					return std::bind(CMainMenu::openLobby, ESelectionScreen::campaignList, true, nullptr, ELoadMode::NONE);
 				case 3:
@@ -191,7 +191,7 @@ static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::str
 				case 0:
 					return std::bind(CMainMenu::openLobby, ESelectionScreen::loadGame, true, nullptr, ELoadMode::SINGLE);
 				case 1:
-					return []()     { GH.pushInt(new CMultiMode(ESelectionScreen::loadGame)); };
+					return []() { GH.pushIntT<CMultiMode>(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<CMenuScreen>(CMainMenuConfig::get().getConfig()["window"]);
 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
 	backgroundAroundMenu = std::make_shared<CFilledTexture>("DIBOXBCK", pos);
 }
@@ -288,8 +287,6 @@ CMainMenu::CMainMenu()
 CMainMenu::~CMainMenu()
 {
 	boost::unique_lock<boost::recursive_mutex> 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<CSimpleJoinScreen>(host);
 }
 
 void CMainMenu::openCampaignLobby(const std::string & campaignFileName)
@@ -337,23 +334,23 @@ void CMainMenu::openCampaignLobby(std::shared_ptr<CCampaignState> campaign)
 	CSH->resetStateForLobby(StartInfo::CAMPAIGN);
 	CSH->screenType = ESelectionScreen::campaignList;
 	CSH->campaignStateToSend = campaign;
-	GH.pushInt(new CSimpleJoinScreen());
+	GH.pushIntT<CSimpleJoinScreen>();
 }
 
 void CMainMenu::openCampaignScreen(std::string name)
 {
 	if(vstd::contains(CMainMenuConfig::get().getCampaigns().Struct(), name))
 	{
-		GH.pushInt(new CCampaignScreen(CMainMenuConfig::get().getCampaigns()[name]));
+		GH.pushIntT<CCampaignScreen>(CMainMenuConfig::get().getCampaigns()[name]);
 		return;
 	}
 	logGlobal->error("Unknown campaign set: %s", name);
 }
 
-CMainMenu * CMainMenu::create()
+std::shared_ptr<CMainMenu> CMainMenu::create()
 {
 	if(!CMM)
-		CMM = new CMainMenu();
+		CMM = std::shared_ptr<CMainMenu>(new CMainMenu());
 
 	GH.terminate_cond->set(false);
 	return CMM;
@@ -381,19 +378,21 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType)
 	buttonHotseat = std::make_shared<CButton>(Point(373, 78), "MUBHOT.DEF", CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this));
 	buttonHost = std::make_shared<CButton>(Point(373, 78 + 57 * 1), "MUBHOST.DEF", CButton::tooltip("Host TCP/IP game", ""), std::bind(&CMultiMode::hostTCP, this));
 	buttonJoin = std::make_shared<CButton>(Point(373, 78 + 57 * 2), "MUBJOIN.DEF", CButton::tooltip("Join TCP/IP game", ""), std::bind(&CMultiMode::joinTCP, this));
-	buttonCancel = std::make_shared<CButton>(Point(373, 424), "MUBCANC.DEF", CGI->generaltexth->zelp[288], [&]() { GH.popIntTotally(this);}, SDLK_ESCAPE);
+	buttonCancel = std::make_shared<CButton>(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<CMultiPlayers>(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<CMultiPlayers>(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<CButton>(Point(95, 338), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CMultiPlayers::enterSelectionScreen, this), SDLK_RETURN);
-	buttonCancel = std::make_shared<CButton>(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CGuiHandler::popIntTotally, std::ref(GH), this), SDLK_ESCAPE);
+	buttonCancel = std::make_shared<CButton>(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], [=](){ close();}, SDLK_ESCAPE);
 	statusBar = std::make_shared<CGStatusBar>(std::make_shared<CPicture>(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();
 	}
 }
 

+ 7 - 7
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<CMainMenu>
 {
 	std::shared_ptr<CFilledTexture> backgroundAroundMenu;
 
 	CMainMenu(); //Use CMainMenu::create
 
 public:
-	CMenuScreen * menu;
+	std::shared_ptr<CMenuScreen> menu;
 
 	~CMainMenu();
 	void update() override;
@@ -140,14 +140,14 @@ public:
 	static void openCampaignLobby(std::shared_ptr<CCampaignState> campaign);
 	void openCampaignScreen(std::string name);
 
-	static CMainMenu * create();
+	static std::shared_ptr<CMainMenu> create();
 
 	static std::shared_ptr<CPicture> createPicture(const JsonNode & config);
 
 };
 
 /// Simple window to enter the server's address.
-class CSimpleJoinScreen : public CIntObject
+class CSimpleJoinScreen : public WindowBase
 {
 	std::shared_ptr<CPicture> background;
 	std::shared_ptr<CTextBox> textTitle;
@@ -179,4 +179,4 @@ public:
 	void showAll(SDL_Surface * to) override;
 };
 
-extern CMainMenu * CMM;
+extern std::shared_ptr<CMainMenu> CMM;

+ 1 - 1
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();
 }

+ 5 - 27
client/widgets/AdventureMapClasses.cpp

@@ -1250,21 +1250,16 @@ void CAdvMapPanel::addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions)
 CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _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<CFilledTexture>("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<int, Point> data, int indexOffset)
@@ -1290,13 +1278,3 @@ void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOf
 	iconsData.push_back(data);
 	currentIcons.push_back(std::make_shared<CAnimImage>(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);
-}

+ 3 - 4
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<std::pair<int, Point>> iconsData;
 	/// ptrs to child-pictures constructed from iconsData
 	std::vector<std::shared_ptr<CAnimImage>> 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<CFilledTexture> backgroundFiller;
 	std::shared_ptr<CAnimation> icons;
 public:
 	CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color);
@@ -395,7 +395,6 @@ public:
 	void addChildIcon(std::pair<int, Point> 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

+ 3 - 3
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<CSpellWindow>(ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt);
 	}
 
 	if (!down && previousState)
@@ -678,14 +678,14 @@ CArtifactsOfHero::~CArtifactsOfHero()
 
 void CArtifactsOfHero::updateParentWindow()
 {
-	if (CHeroWindow* chw = dynamic_cast<CHeroWindow*>(GH.topInt()))
+	if (CHeroWindow* chw = dynamic_cast<CHeroWindow*>(GH.topInt().get()))
 	{
 		if(updateState)
 			chw->curHero = curHero;
 		else
 			chw->update(curHero, true);
 	}
-	else if(CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt()))
+	else if(CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt().get()))
 	{
 		//use our copy of hero to draw window
 		if(cew->heroInst[0]->id == curHero->id)

+ 5 - 5
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<CStackWindow>(myStack, dism, pom, upgr);
 	return true;
 }
 
@@ -170,7 +170,7 @@ bool CGarrisonSlot::viewInfo()
 bool CGarrisonSlot::highlightOrDropArtifact()
 {
 	bool artSelected = false;
-	if (CWindowWithArtifacts* chw = dynamic_cast<CWindowWithArtifacts*>(GH.topInt())) //dirty solution
+	if (CWindowWithArtifacts* chw = dynamic_cast<CWindowWithArtifacts*>(GH.topInt().get())) //dirty solution
 	{
 		const std::shared_ptr<CArtifactsOfHero::SCommonPart> 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<CSplitWindow>(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<CStackWindow>(myStack, true);
 	}
 }
 

+ 7 - 12
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<CAnimation>(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)

+ 2 - 4
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<CAnimation> 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);
 
 };

+ 1 - 1
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<CPicture>(CGI->townh->factions[faction]->creatureBg130);
 	else
 		bg = std::make_shared<CPicture>(CGI->townh->factions[faction]->creatureBg120);
-	anim = std::make_shared<CCreatureAnim>(0, 0, cre->animDefName, Rect());
+	anim = std::make_shared<CCreatureAnim>(0, 0, cre->animDefName);
 	anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h);
 	anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON));
 

+ 11 - 12
client/windows/CAdvmapInterface.cpp

@@ -59,7 +59,7 @@
 #define ADVOPT (conf.go()->ac)
 using namespace CSDL_Ext;
 
-CAdvMapInt *adventureInt;
+std::shared_ptr<CAdvMapInt> 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<CKingdomInterface>();
 }
 
 void CAdvMapInt::fworldViewBack()
@@ -811,17 +810,17 @@ void CAdvMapInt::fshowSpellbok()
 
 	centerOn(selection);
 
-	GH.pushInt(new CSpellWindow(curHero(), LOCPLINT, false));
+	GH.pushIntT<CSpellWindow>(curHero(), LOCPLINT, false);
 }
 
 void CAdvMapInt::fadventureOPtions()
 {
-	GH.pushInt(new CAdventureOptions());
+	GH.pushIntT<CAdventureOptions>();
 }
 
 void CAdvMapInt::fsystemOptions()
 {
-	GH.pushInt(new CSystemOptionsWindow());
+	GH.pushIntT<CSystemOptionsWindow>();
 }
 
 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<CSavingScreen>();
 		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<CMarketplaceWindow>(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<CBonusSelection>();
 	}
 	else
 	{
-		GH.pushInt(new CScenarioInfoScreen());
+		GH.pushIntT<CScenarioInfoScreen>();
 	}
 }
 

+ 1 - 1
client/windows/CAdvmapInterface.h

@@ -266,4 +266,4 @@ public:
 
 };
 
-extern CAdvMapInt *adventureInt;
+extern std::shared_ptr<CAdvMapInt> adventureInt;

+ 43 - 47
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<CDwellingInfoBox>(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<CInfoBoxPopup>(Point(pos.x + 175, pos.y + 100), hero);
 	}
 }
 
@@ -522,17 +521,26 @@ void HeroSlots::swapArmies()
 }
 
 
-template <class T>
 class SORTHELP
 {
 public:
-	bool operator() (const std::shared_ptr<T> a, const std::shared_ptr<T> b)
+	bool operator() (const CIntObject * a, const CIntObject * b)
 	{
-		return (*a)<(*b);
+		auto b1 = dynamic_cast<const CBuildingRect *>(a);
+		auto b2 = dynamic_cast<const CBuildingRect *>(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<CBuildingRect> 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<CBuildingRect>(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<CFortScreen>(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<CMarketplaceWindow>(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<CMarketplaceWindow>(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<CMarketplaceWindow>(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<CUniversityWindow>(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<CTransformerWindow>(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<CBlacksmithDialog>(possible, cre, artifactID, hero->id);
 }
 
 void CCastleBuildings::enterBuilding(BuildingID building)
@@ -838,20 +832,20 @@ void CCastleBuildings::enterCastleGate()
 		}
 	}
 	auto gateIcon = std::make_shared<CAnimImage>(town->town->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window
-	GH.pushInt(new CObjectListWindow(availableTowns, gateIcon, CGI->generaltexth->jktexts[40],
-		CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1)));
+	GH.pushIntT<CObjectListWindow>(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<CRecruitmentWindow>(town, level, town, recruitCb, -87);
 }
 
 void CCastleBuildings::enterToTheQuickRecruitmentWindow()
 {
-	GH.pushInt(new QuickRecruitmentWindow(town, pos));
+	GH.pushIntT<QuickRecruitmentWindow>(town, pos);
 }
 
 void CCastleBuildings::enterFountain(BuildingID building)
@@ -915,7 +909,7 @@ void CCastleBuildings::enterTownHall()
 		else
 		{
 			LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[673]);
-			dynamic_cast<CInfoWindow*>(GH.topInt())->buttons[0]->addCallback(std::bind(&CCastleBuildings::openTownHall, this));
+			dynamic_cast<CInfoWindow*>(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<CMageGuildScreen>(LOCPLINT->castleInt,mageGuildBackground);
 }
 
 void CCastleBuildings::openTownHall()
 {
-	GH.pushInt(new CHallInterface(town));
+	GH.pushIntT<CHallInterface>(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<CRecruitmentWindow>(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<CDwellingInfoBox>(screen->w/2, screen->h/2, town, level);
 		else
 			CRClickPopup::createAndPush(genGrowthText(), std::make_shared<CComponent>(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<CCastleInterface>(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<CBuildWindow>(town,building,state,0);
 }
 
 void CHallInterface::CBuildingBox::clickRight(tribool down, bool previousState)
 {
 	if(down)
-		GH.pushInt(new CBuildWindow(town,building,state,1));
+		GH.pushIntT<CBuildWindow>(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<CCreatureAnim>(64, 50, creature->animDefName, Rect());
+	anim = std::make_shared<CCreatureAnim>(64, 50, creature->animDefName);
 	anim->clipRect(113,125,200,150);
 
 	title = std::make_shared<CLabel>(165, 28, FONT_BIG, CENTER, Colors::YELLOW,

+ 0 - 3
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

+ 6 - 6
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<CHeroWindow>(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<CExchangeWindow*>(isa))
+		if(CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>(isa.get()))
 		{
 			for(int g=0; g < cew->heroInst.size(); ++g)
 				if(cew->heroInst[g] == curHero)
 					noDismiss = true;
 		}
 
-		if(dynamic_cast<CKingdomInterface*>(isa))
+		if(dynamic_cast<CKingdomInterface*>(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<CStackWindow>(curHero->commander, false);
 	}
 }
 

+ 3 - 3
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;

+ 4 - 4
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]()
 			{

+ 3 - 6
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<CAltarWindow>(m, h, Mode);
 		break;
 	default:
-		nwindow = new CMarketplaceWindow(m, h, Mode);
+		GH.pushIntT<CMarketplaceWindow>(m, h, Mode);
 		break;
 	}
-
-	GH.pushInt(nwindow);
 }
 
 void CTradeWindow::artifactSelected(CHeroArtPlace *slot)

+ 7 - 17
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<CIntObject>();
-		}
 
-		{
-			OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255);
+			shadowParts.push_back(std::make_shared<CPicture>(shadowCorner, shadowPos.x, shadowPos.y));
+			shadowParts.push_back(std::make_shared<CPicture>(shadowRight, shadowPos.x, shadowStart.y));
+			shadowParts.push_back(std::make_shared<CPicture>(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();

+ 3 - 5
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<CPicture> createBg(std::string imageName, bool playerColored);
 	int getUsedEvents(int options);
 
-	std::shared_ptr<CIntObject> shadow;
+	std::vector<std::shared_ptr<CPicture>> shadowParts;
+
 	void setShadow(bool on);
 
 	int options;
@@ -25,8 +25,6 @@ class CWindowObject : public CIntObject
 protected:
 	std::shared_ptr<CPicture> 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

+ 15 - 21
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<CStackWindow>(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<CObjectListWindow>(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<CSavingScreen>();
 }
 
 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<CThievesGuildWindow>(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<CRClickPopupInt>(std::make_shared<CHeroWindow>(h));
 }
 
 CTavernWindow::HeroPortrait::HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H)
@@ -990,7 +987,7 @@ CShipyardWindow::CShipyardWindow(const std::vector<si32> & 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<CAnimImage>(boatFilenames[boatType], 0, 7, 120, 96, CShowableAnim::USE_RLE);
+	bgShip = std::make_shared<CAnimImage>(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<CUnivConfirmWindow>(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000);
 	}
 }
 
@@ -1813,14 +1807,14 @@ void CObjectListWindow::elementSelected()
 {
 	std::function<void(int)> 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<void()> toCall = onExit;//save
-	GH.popIntTotally(this);//then destroy window
+	close();//then destroy window
 	if(toCall)
 		toCall();
 }

+ 25 - 45
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<void( ) > &onYes, const CFunctionList<void()> &onNo, PlayerColor player)
@@ -191,7 +191,7 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & c
 	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
 	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
 	pom.push_back(std::pair<std::string,CFunctionList<void()> >("ICANCEL.DEF",0));
-	CInfoWindow * temp = new CInfoWindow(text, player, components, pom);
+	std::shared_ptr<CInfoWindow> temp =  std::make_shared<CInfoWindow>(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<void()> & onOk, PlayerColor player)
-{
-	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
-	pom.push_back(std::pair<std::string,CFunctionList<void()> >("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::shared_ptr<CInfoWindow> CInfoWindow::create(const std::string &text, PlayerColor playerID, const TCompsInfo & components)
 {
 	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
 	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
-	CInfoWindow * ret = new CInfoWindow(text, playerID, components, pom);
-	return ret;
+	return std::make_shared<CInfoWindow>(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<CInfoWindow>(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<CRClickPopupInt>(temp);
 }
 
 void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr<CComponent> component)
@@ -331,14 +320,16 @@ void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr<CCompo
 	createAndPush(txt, intComps);
 }
 
-void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment)
+void CRClickPopup::createAndPush(const CGObjectInstance * obj, const Point & p, EAlignment alignment)
 {
-	CIntObject *iWin = createInfoWin(p, obj); //try get custom infowindow for this obj
+	auto iWin = createInfoWin(p, obj); //try get custom infowindow for this obj
 	if(iWin)
+	{
 		GH.pushInt(iWin);
+	}
 	else
 	{
-		if (adventureInt->curHero())
+		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<CIntObject> 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<CArmyTooltip>(Point(9, 10), iah);
 }
 
-CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
+std::shared_ptr<WindowBase> 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<const CGHeroInstance *>(specific));
+		return std::make_shared<CInfoBoxPopup>(position, dynamic_cast<const CGHeroInstance *>(specific));
 	case Obj::TOWN:
-		return new CInfoBoxPopup(position, dynamic_cast<const CGTownInstance *>(specific));
+		return std::make_shared<CInfoBoxPopup>(position, dynamic_cast<const CGTownInstance *>(specific));
 	case Obj::GARRISON:
 	case Obj::GARRISON2:
-		return new CInfoBoxPopup(position, dynamic_cast<const CGGarrison *>(specific));
+		return std::make_shared<CInfoBoxPopup>(position, dynamic_cast<const CGGarrison *>(specific));
 	default:
-		return nullptr;
+		return std::shared_ptr<WindowBase>();
 	}
 }

+ 10 - 15
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<void()> & onOk, PlayerColor player = PlayerColor(1));
 	static void showYesNoDialog( const std::string & text, const TCompsInfo & components, const CFunctionList<void()> & onYes, const CFunctionList<void()> & onNo, PlayerColor player = PlayerColor(1));
-	static CInfoWindow * create(const std::string & text, PlayerColor playerID = PlayerColor(1), const TCompsInfo & components = TCompsInfo());
+	static std::shared_ptr<CInfoWindow> create(const std::string & text, PlayerColor playerID = PlayerColor(1), const TCompsInfo & components = TCompsInfo());
 
 	/// create text from title and description: {title}\n\n description
 	static std::string genText(std::string title, std::string description);
 };
 
 /// 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<WindowBase> 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<CComponent> 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<CIntObject> 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<CIntObject> 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<std::shared_ptr<CSelectableComponent>> & comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID);
-	CSelWindow(){};
+	CSelWindow(const std::string & text, PlayerColor player, int charperline, const std::vector<std::shared_ptr<CSelectableComponent>> & comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID);
+
 	//notification - this class inherits important destructor from CInfoWindow
 };