Browse Source

Partial encapsulation of AdvMapInt

Ivan Savenko 2 years ago
parent
commit
91b17bed79

+ 7 - 57
client/CPlayerInterface.cpp

@@ -203,8 +203,7 @@ void CPlayerInterface::yourTurn()
 			autosaveCount %= 5;
 		}
 
-		if (adventureInt->player != playerID)
-			adventureInt->setPlayer(playerID);
+		adventureInt->setPlayer(playerID);
 
 		if (CSH->howManyPlayerInterfaces() > 1) //hot seat message
 		{
@@ -360,7 +359,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
 #ifndef VCMI_ANDROID
 		// currently android doesn't seem to be able to handle all these full redraws here, so let's disable it so at least it looks less choppy;
 		// most likely this is connected with the way that this manual animation+framerate handling is solved
-		adventureInt->updateScreen = true;
+		adventureInt->requestRedrawMapOnNextFrame();
 #endif
 
 		//evil returns here ...
@@ -1582,23 +1581,13 @@ void CPlayerInterface::update()
 		dialogs.pop_front();
 	}
 
-	//in some conditions we may receive calls before selection is initialized - we must ignore them
-	if(adventureInt && GH.topInt() == adventureInt
-		&& (!adventureInt->selection && !settings["session"]["spectate"].Bool()))
-	{
-		return;
-	}
+	assert(adventureInt);
+	assert(adventureInt->selection);
 
 	// Handles mouse and key input
 	GH.updateTime();
 	GH.handleEvents();
-
-	if (!adventureInt || adventureInt->isActive())
-		GH.simpleRedraw();
-	else if((adventureInt->swipeEnabled && adventureInt->swipeMovementRequested) || (adventureInt->scrollingDir && GH.isKeyboardCtrlDown()))
-		GH.totalRedraw(); //player forces map scrolling though interface is disabled
-	else
-		GH.simpleRedraw();
+	GH.simpleRedraw();
 }
 
 int CPlayerInterface::getLastIndex( std::string namePrefix)
@@ -1858,7 +1847,7 @@ void CPlayerInterface::showPuzzleMap()
 
 void CPlayerInterface::viewWorldMap()
 {
-	adventureInt->changeMode(EAdvMapMode::WORLD_VIEW);
+	adventureInt->changeMode(EAdvMapMode::WORLD_VIEW, 0.36F);
 }
 
 void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellID)
@@ -1935,10 +1924,8 @@ CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
 
 void CPlayerInterface::acceptTurn()
 {
-	bool centerView = true;
 	if (settings["session"]["autoSkip"].Bool())
 	{
-		centerView = false;
 		while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
 			iw->close();
 	}
@@ -1950,44 +1937,7 @@ void CPlayerInterface::acceptTurn()
 		adventureInt->startTurn();
 	}
 
-	adventureInt->heroList->update();
-	adventureInt->townList->update();
-
-	const CGHeroInstance * heroToSelect = nullptr;
-
-	// find first non-sleeping hero
-	for (auto hero : wanderingHeroes)
-	{
-		if (boost::range::find(sleepingHeroes, hero) == sleepingHeroes.end())
-		{
-			heroToSelect = hero;
-			break;
-		}
-	}
-
-	//select first hero if available.
-	if (heroToSelect != nullptr)
-	{
-		adventureInt->select(heroToSelect, centerView);
-	}
-	else if (towns.size())
-		adventureInt->select(towns.front(), centerView);
-	else
-		adventureInt->select(wanderingHeroes.front());
-
-	//show new day animation and sound on infobar
-	adventureInt->infoBar->showDate();
-
-	adventureInt->updateNextHero(nullptr);
-	adventureInt->showAll(screen);
-
-	if(settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown())
-	{
-		if(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
-			iw->close();
-
-		adventureInt->fendTurn();
-	}
+	adventureInt->initializeNewTurn();
 
 	// warn player if he has no town
 	if (cb->howManyTowns() == 0)

+ 4 - 23
client/ClientCommandManager.cpp

@@ -115,25 +115,6 @@ void ClientCommandManager::processCommand(const std::string &message, bool calle
 	{
 		exit(EXIT_SUCCESS);
 	}
-	else if(commandName == std::string("activate"))
-	{
-		int what;
-		singleWordBuffer >> what;
-		switch (what)
-		{
-			case 0:
-				GH.topInt()->activate();
-				break;
-			case 1:
-				adventureInt->activate();
-				break;
-			case 2:
-				LOCPLINT->castleInt->activate();
-				break;
-			default:
-				printCommandMessage("Wrong argument specified!", ELogLevel::ERROR);
-		}
-	}
 	else if(commandName == "redraw")
 	{
 		GH.totalRedraw();
@@ -274,7 +255,7 @@ void ClientCommandManager::processCommand(const std::string &message, bool calle
 	}
 	else if(commandName == "mp" && adventureInt)
 	{
-		if(const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection))
+		if(const CGHeroInstance *h = adventureInt->curHero())
 			printCommandMessage(std::to_string(h->movement) + "; max: " + std::to_string(h->maxMovePoints(true)) + "/" + std::to_string(h->maxMovePoints(false)) + "\n");
 	}
 	else if(commandName == "bonuses")
@@ -288,12 +269,12 @@ void ClientCommandManager::processCommand(const std::string &message, bool calle
 			ss << b;
 			return ss.str();
 		};
-		printCommandMessage("Bonuses of " + adventureInt->selection->getObjectName() + "\n");
-		printCommandMessage(format(adventureInt->selection->getBonusList()) + "\n");
+		printCommandMessage("Bonuses of " + adventureInt->curArmy()->getObjectName() + "\n");
+		printCommandMessage(format(adventureInt->curArmy()->getBonusList()) + "\n");
 
 		printCommandMessage("\nInherited bonuses:\n");
 		TCNodes parents;
-		adventureInt->selection->getParents(parents);
+		adventureInt->curArmy()->getParents(parents);
 		for(const CBonusSystemNode *parent : parents)
 		{
 			printCommandMessage(std::string("\nBonuses from ") + typeid(*parent).name() + "\n" + format(*parent->getAllBonuses(Selector::all, Selector::all)) + "\n");

+ 89 - 18
client/adventureMap/CAdvMapInt.cpp

@@ -52,7 +52,7 @@
 
 std::shared_ptr<CAdvMapInt> adventureInt;
 
-static void setScrollingCursor(ui8 direction)
+void CAdvMapInt::setScrollingCursor(ui8 direction) const
 {
 	if(direction & CAdvMapInt::RIGHT)
 	{
@@ -90,7 +90,7 @@ CAdvMapInt::CAdvMapInt():
 	terrain(new CTerrainRect),
 	state(NA),
 	spellBeingCasted(nullptr), position(int3(0, 0, 0)), selection(nullptr),
-	updateScreen(false), anim(0), animValHitCount(0), heroAnim(0), heroAnimValHitCount(0),
+	redrawOnNextFrame(false), anim(0), animValHitCount(0), heroAnim(0), heroAnimValHitCount(0),
 	activeMapPanel(nullptr), duringAITurn(false), scrollingDir(0), scrollingState(false),
 	swipeEnabled(settings["general"]["swipe"].Bool()), swipeMovementRequested(false),
 	swipeTargetPosition(int3(-1, -1, -1))
@@ -237,7 +237,7 @@ CAdvMapInt::CAdvMapInt():
 
 	activeMapPanel = panelMain;
 
-	changeMode(EAdvMapMode::NORMAL);
+	changeMode(EAdvMapMode::NORMAL, 0.36F);
 
 	underground->block(!CGI->mh->map->twoLevel);
 	questlog->block(!CGI->mh->map->quests.size());
@@ -253,7 +253,7 @@ void CAdvMapInt::fshowOverview()
 
 void CAdvMapInt::fworldViewBack()
 {
-	changeMode(EAdvMapMode::NORMAL);
+	changeMode(EAdvMapMode::NORMAL, 0.36F);
 	CGI->mh->discardWorldViewCache();
 
 	auto hero = curHero();
@@ -292,7 +292,7 @@ void CAdvMapInt::fswitchLevel()
 	worldViewUnderground->setIndex(position.z, true);
 	worldViewUnderground->redraw();
 
-	updateScreen = true;
+	redrawOnNextFrame = true;
 	minimap->setLevel(position.z);
 
 	if (mode == EAdvMapMode::WORLD_VIEW)
@@ -525,7 +525,7 @@ void CAdvMapInt::showAll(SDL_Surface * to)
 	}
 	activeMapPanel->showAll(to);
 
-	updateScreen = true;
+	redrawOnNextFrame = true;
 	minimap->showAll(to);
 	show(to);
 
@@ -570,7 +570,7 @@ void CAdvMapInt::show(SDL_Surface * to)
 		CGI->mh->updateWater();
 		animValHitCount = 0;
 		++anim;
-		updateScreen = true;
+		redrawOnNextFrame = true;
 	}
 
 	if(swipeEnabled)
@@ -591,7 +591,7 @@ void CAdvMapInt::show(SDL_Surface * to)
 		else
 			gems[i]->setFrame(LOCPLINT->playerID.getNum());
 	}
-	if(updateScreen)
+	if(redrawOnNextFrame)
 	{
 		int3 betterPos = LOCPLINT->repairScreenPos(position);
 		if (betterPos != position)
@@ -603,7 +603,7 @@ void CAdvMapInt::show(SDL_Surface * to)
 		terrain->show(to);
 		for(int i = 0; i < 4; i++)
 			gems[i]->showAll(to);
-		updateScreen=false;
+		redrawOnNextFrame=false;
 		LOCPLINT->cingconsole->show(to);
 	}
 	else
@@ -621,8 +621,7 @@ void CAdvMapInt::handleMapScrollingUpdate()
 {
 	int scrollSpeed = static_cast<int>(settings["adventure"]["scrollSpeed"].Float());
 	//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
-	if((animValHitCount % (4 / scrollSpeed)) == 0
-	   && GH.isKeyboardCtrlDown())
+	if((animValHitCount % (4 / scrollSpeed)) == 0)
 	{
 		if((scrollingDir & LEFT) && (position.x > -CGI->mh->frameW))
 			position.x--;
@@ -640,7 +639,7 @@ void CAdvMapInt::handleMapScrollingUpdate()
 		{
 			setScrollingCursor(scrollingDir);
 			scrollingState = true;
-			updateScreen = true;
+			redrawOnNextFrame = true;
 			minimap->redraw();
 			if(mode == EAdvMapMode::WORLD_VIEW)
 				terrain->redraw();
@@ -661,7 +660,7 @@ void CAdvMapInt::handleSwipeUpdate()
 		position.x = fixedPos.x;
 		position.y = fixedPos.y;
 		CCS->curh->set(Cursor::Map::POINTER);
-		updateScreen = true;
+		redrawOnNextFrame = true;
 		minimap->redraw();
 		swipeMovementRequested = false;
 	}
@@ -700,7 +699,7 @@ void CAdvMapInt::centerOn(int3 on, bool fade)
 	on = LOCPLINT->repairScreenPos(on);
 
 	position = on;
-	updateScreen=true;
+	redrawOnNextFrame=true;
 	underground->setIndex(on.z,true); //change underground switch button image
 	underground->redraw();
 	worldViewUnderground->setIndex(on.z, true);
@@ -877,11 +876,14 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
 				  (direction->y<0 ? UP    : 0) |
 				  (direction->y>0 ? DOWN  : 0) ;
 
-			scrollingDir |= Dir;
+
 
 			//ctrl makes arrow move screen, not hero
 			if(GH.isKeyboardCtrlDown())
+			{
+				scrollingDir |= Dir;
 				return;
+			}
 
 			if(!h || !isActive())
 				return;
@@ -1057,13 +1059,16 @@ void CAdvMapInt::startHotSeatWait(PlayerColor Player)
 
 void CAdvMapInt::setPlayer(PlayerColor Player)
 {
+	if (Player == player)
+		return;
+
 	player = Player;
 	bg->playerColored(player);
 
 	panelMain->setPlayerColor(player);
 	panelWorldView->setPlayerColor(player);
 	panelWorldView->recolorIcons(player, player.getNum() * 19);
-	resdatabar->background->colorize(player);
+	resdatabar->colorize(player);
 }
 
 void CAdvMapInt::startTurn()
@@ -1077,6 +1082,50 @@ void CAdvMapInt::startTurn()
 	}
 }
 
+void CAdvMapInt::initializeNewTurn()
+{
+	heroList->update();
+	townList->update();
+
+	const CGHeroInstance * heroToSelect = nullptr;
+
+	// find first non-sleeping hero
+	for (auto hero : LOCPLINT->wanderingHeroes)
+	{
+		if (boost::range::find(LOCPLINT->sleepingHeroes, hero) == LOCPLINT->sleepingHeroes.end())
+		{
+			heroToSelect = hero;
+			break;
+		}
+	}
+
+	bool centerView = !settings["session"]["autoSkip"].Bool();
+
+	//select first hero if available.
+	if (heroToSelect != nullptr)
+	{
+		select(heroToSelect, centerView);
+	}
+	else if (LOCPLINT->towns.size())
+		select(LOCPLINT->towns.front(), centerView);
+	else
+		select(LOCPLINT->wanderingHeroes.front());
+
+	//show new day animation and sound on infobar
+	infoBar->showDate();
+
+	updateNextHero(nullptr);
+	showAll(screen);
+
+	if(settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown())
+	{
+		if(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
+			iw->close();
+
+		endingTurn();
+	}
+}
+
 void CAdvMapInt::endingTurn()
 {
 	if(settings["session"]["spectate"].Bool())
@@ -1415,7 +1464,7 @@ void CAdvMapInt::leaveCastingMode(bool cast, int3 dest)
 const CGHeroInstance * CAdvMapInt::curHero() const
 {
 	if(selection && selection->ID == Obj::HERO)
-		return static_cast<const CGHeroInstance *>(selection);
+		return dynamic_cast<const CGHeroInstance *>(selection);
 	else
 		return nullptr;
 }
@@ -1423,11 +1472,29 @@ const CGHeroInstance * CAdvMapInt::curHero() const
 const CGTownInstance * CAdvMapInt::curTown() const
 {
 	if(selection && selection->ID == Obj::TOWN)
-		return static_cast<const CGTownInstance *>(selection);
+		return dynamic_cast<const CGTownInstance *>(selection);
+	else
+		return nullptr;
+}
+
+const CArmedInstance * CAdvMapInt::curArmy() const
+{
+	if (selection)
+		return dynamic_cast<const CArmedInstance *>(selection);
 	else
 		return nullptr;
 }
 
+Rect CAdvMapInt::terrainAreaPixels() const
+{
+	return terrain->pos;
+}
+
+Rect CAdvMapInt::terrainAreaTiles() const
+{
+	return terrain->visibleTilesArea();
+}
+
 const IShipyard * CAdvMapInt::ourInaccessibleShipyard(const CGObjectInstance *obj) const
 {
 	const IShipyard *ret = IShipyard::castFrom(obj);
@@ -1537,3 +1604,7 @@ void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
 	info.additionalIcons = &iconPositions;
 }
 
+void CAdvMapInt::requestRedrawMapOnNextFrame()
+{
+	redrawOnNextFrame = true;
+}

+ 82 - 54
client/adventureMap/CAdvMapInt.h

@@ -53,74 +53,77 @@ enum class EAdvMapMode
 /// can get to the towns and heroes.
 class CAdvMapInt : public CIntObject
 {
-	//Return object that must be active at this tile (=clickable)
-	const CGObjectInstance *getActiveObject(const int3 &tile);
-
-	boost::optional<Point> keyToMoveDirection(const SDL_Keycode & key);
+	//TODO: remove
+	friend class CPlayerInterface;
+	friend class CTerrainRect;
 
-public:
-	CAdvMapInt();
-
-	int3 position; //top left corner of visible map part
-	PlayerColor player;
+private:
+	enum EDirections {LEFT=1, RIGHT=2, UP=4, DOWN=8};
+	enum EGameStates {NA, INGAME, WAITING};
 
-	bool duringAITurn;
+	struct WorldViewOptions
+	{
+		bool showAllTerrain; //for expert viewEarth
+		std::vector<ObjectPosInfo> iconPositions;
+		WorldViewOptions();
+		void clear();
+		void adjustDrawingInfo(MapDrawingInfo & info);
+	};
 
-	enum{LEFT=1, RIGHT=2, UP=4, DOWN=8};
-	ui8 scrollingDir; //uses enum: LEFT RIGHT, UP, DOWN
-	bool scrollingState;
 	bool swipeEnabled;
 	bool swipeMovementRequested;
 	int3 swipeTargetPosition;
 
-	enum{NA, INGAME, WAITING} state;
+	EGameStates state;
 
-	bool updateScreen;
 	ui8 anim, animValHitCount; //animation frame
 	ui8 heroAnim, heroAnimValHitCount; //animation frame
 
+	/// top left corner of visible map part
+	int3 position;
+
 	EAdvMapMode mode;
 	float worldViewScale;
 
-	struct WorldViewOptions
-	{
-		bool showAllTerrain; //for expert viewEarth
+	WorldViewOptions worldViewOptions;
 
-		std::vector<ObjectPosInfo> iconPositions;
+	/// Currently selected object, can be town, hero or null
+	const CArmedInstance *selection;
 
-		WorldViewOptions();
+	/// currently acting player
+	PlayerColor player;
 
-		void clear();
+	bool duringAITurn;
 
-		void adjustDrawingInfo(MapDrawingInfo & info);
-	};
+	/// uses EDirections enum
+	ui8 scrollingDir;
+	bool scrollingState;
 
-	WorldViewOptions worldViewOptions;
+	const CSpell *spellBeingCasted; //nullptr if none
 
-	std::shared_ptr<IImage> bg;
-	std::shared_ptr<IImage> bgWorldView;
 	std::vector<std::shared_ptr<CAnimImage>> gems;
-	std::shared_ptr<CMinimap> minimap;
-	std::shared_ptr<CGStatusBar> statusbar;
 
+	std::shared_ptr<IImage> bg;
+	std::shared_ptr<IImage> bgWorldView;
 	std::shared_ptr<CButton> kingOverview;
+	std::shared_ptr<CButton> sleepWake;
 	std::shared_ptr<CButton> underground;
 	std::shared_ptr<CButton> questlog;
-	std::shared_ptr<CButton> sleepWake;
 	std::shared_ptr<CButton> moveHero;
 	std::shared_ptr<CButton> spellbook;
 	std::shared_ptr<CButton> advOptions;
 	std::shared_ptr<CButton> sysOptions;
 	std::shared_ptr<CButton> nextHero;
 	std::shared_ptr<CButton> endTurn;
-
 	std::shared_ptr<CButton> worldViewUnderground;
 
-	std::shared_ptr<CTerrainRect> terrain; //visible terrain
-	std::shared_ptr<CResDataBar> resdatabar;
+	std::shared_ptr<CTerrainRect> terrain;
+	std::shared_ptr<CMinimap> minimap;
 	std::shared_ptr<CHeroList> heroList;
 	std::shared_ptr<CTownList> townList;
 	std::shared_ptr<CInfoBar> infoBar;
+	std::shared_ptr<CGStatusBar> statusbar;
+	std::shared_ptr<CResDataBar> resdatabar;
 
 	std::shared_ptr<CAdvMapPanel> panelMain; // panel that holds all right-side buttons in normal view
 	std::shared_ptr<CAdvMapWorldViewPanel> panelWorldView; // panel that holds all buttons and other ui in world view
@@ -128,10 +131,7 @@ public:
 
 	std::shared_ptr<CAnimation> worldViewIcons;// images for world view overlay
 
-	const CSpell *spellBeingCasted; //nullptr if none
-
-	const CArmedInstance *selection; //currently selected town/hero
-
+private:
 	//functions bound to buttons
 	void fshowOverview();
 	void fworldViewBack();
@@ -148,21 +148,49 @@ public:
 	void fnextHero();
 	void fendTurn();
 
+	void setScrollingCursor(ui8 direction) const;
+	void selectionChanged();
+	bool isActive();
+	void adjustActiveness(bool aiTurnStart); //should be called every time at AI/human turn transition; blocks GUI during AI turn
+
+	const IShipyard * ourInaccessibleShipyard(const CGObjectInstance *obj) const; //checks if obj is our ashipyard and cursor is 0,0 -> returns shipyard or nullptr else
+	//button updates
+	void updateSleepWake(const CGHeroInstance *h);
+	void updateSpellbook(const CGHeroInstance *h);
+
+	void handleMapScrollingUpdate();
+	void handleSwipeUpdate();
+
+	void showMoveDetailsInStatusbar(const CGHeroInstance & hero, const CGPathNode & pathNode);
+
+	const CGObjectInstance *getActiveObject(const int3 &tile);
+
+	boost::optional<Point> keyToMoveDirection(const SDL_Keycode & key);
+
+	bool redrawOnNextFrame;
+public:
+	CAdvMapInt();
+
+	// CIntObject interface implementation
+
 	void activate() override;
 	void deactivate() override;
 
-	void show(SDL_Surface * to) override; //redraws terrain
-	void showAll(SDL_Surface * to) override; //shows and activates adv. map interface
+	void show(SDL_Surface * to) override;
+	void showAll(SDL_Surface * to) override;
+
+	void keyPressed(const SDL_Keycode & key) override;
+	void keyReleased(const SDL_Keycode & key) override;
+	void mouseMoved (const Point & cursorPosition) override;
+
+	// public interface
+
+	void requestRedrawMapOnNextFrame();
 
 	void select(const CArmedInstance *sel, bool centerView = true);
-	void selectionChanged();
 	void centerOn(int3 on, bool fade = false);
 	void centerOn(const CGObjectInstance *obj, bool fade = false);
 	int3 verifyPos(int3 ver);
-	void keyPressed(const SDL_Keycode & key) override;
-	void keyReleased(const SDL_Keycode & key) override;
-	void mouseMoved (const Point & cursorPosition) override;
-	bool isActive();
 
 	bool isHeroSleeping(const CGHeroInstance *hero);
 	void setHeroSleeping(const CGHeroInstance *hero, bool sleep);
@@ -171,34 +199,34 @@ public:
 	void setPlayer(PlayerColor Player);
 	void startHotSeatWait(PlayerColor Player);
 	void startTurn();
+	void initializeNewTurn();
 	void endingTurn();
 	void aiTurnStarted();
 
-	void adjustActiveness(bool aiTurnStart); //should be called every time at AI/human turn transition; blocks GUI during AI turn
 	void quickCombatLock(); //should be called when quick battle started
 	void quickCombatUnlock();
+
 	void tileLClicked(const int3 &mapPos);
 	void tileHovered(const int3 &mapPos);
 	void tileRClicked(const int3 &mapPos);
+
 	void enterCastingMode(const CSpell * sp);
 	void leaveCastingMode(bool cast = false, int3 dest = int3(-1, -1, -1));
 	const CGHeroInstance * curHero() const;
 	const CGTownInstance * curTown() const;
-	const IShipyard * ourInaccessibleShipyard(const CGObjectInstance *obj) const; //checks if obj is our ashipyard and cursor is 0,0 -> returns shipyard or nullptr else
-	//button updates
-	void updateSleepWake(const CGHeroInstance *h);
+	const CArmedInstance * curArmy() const;
+
 	void updateMoveHero(const CGHeroInstance *h, tribool hasPath = boost::logic::indeterminate);
-	void updateSpellbook(const CGHeroInstance *h);
 	void updateNextHero(const CGHeroInstance *h);
 
-	/// changes current adventure map mode; used to switch between default view and world view; scale is ignored if EAdvMapMode == NORMAL
-	void changeMode(EAdvMapMode newMode, float newScale = 0.36f);
+	/// returns area of screen covered by terrain (main game area)
+	Rect terrainAreaPixels() const;
 
-	void handleMapScrollingUpdate();
-	void handleSwipeUpdate();
+	/// returs visible section of game map, in tiles
+	Rect terrainAreaTiles() const;
 
-private:
-	void showMoveDetailsInStatusbar(const CGHeroInstance & hero, const CGPathNode & pathNode);
+	/// changes current adventure map mode; used to switch between default view and world view; scale is ignored if EAdvMapMode == NORMAL
+	void changeMode(EAdvMapMode newMode, float newScale);
 };
 
 extern std::shared_ptr<CAdvMapInt> adventureInt;

+ 0 - 2
client/adventureMap/CAdvMapPanel.cpp

@@ -74,8 +74,6 @@ CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons,
 	}
 }
 
-CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel() = default;
-
 void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOffset)
 {
 	assert(iconsData.size() == currentIcons.size());

+ 1 - 1
client/adventureMap/CAdvMapPanel.h

@@ -51,9 +51,9 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel
 	std::shared_ptr<CAnimation> icons;
 public:
 	CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color);
-	virtual ~CAdvMapWorldViewPanel();
 
 	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);
 };

+ 2 - 1
client/adventureMap/CAdventureOptions.h

@@ -16,7 +16,6 @@ class CButton;
 /// Adventure options dialog where you can view the world, dig, play the replay of the last turn,...
 class CAdventureOptions : public CWindowObject
 {
-public:
 	std::shared_ptr<CButton> exit;
 	std::shared_ptr<CButton> viewWorld;
 	std::shared_ptr<CButton> puzzle;
@@ -24,7 +23,9 @@ public:
 	std::shared_ptr<CButton> scenInfo;
 	/*std::shared_ptr<CButton> replay*/
 
+public:
 	CAdventureOptions();
+
 	static void showScenarioInfo();
 };
 

+ 4 - 3
client/adventureMap/CInGameConsole.h

@@ -22,12 +22,13 @@ private:
 	int maxDisplayedTexts; //hiw many texts can be displayed simultaneously
 
 	std::weak_ptr<IStatusBar> currentStatusBar;
-public:
 	std::string enteredText;
-	void show(SDL_Surface * to) override;
+
+public:
 	void print(const std::string &txt);
-	void keyPressed(const SDL_Keycode & key) override;
 
+	void show(SDL_Surface * to) override;
+	void keyPressed(const SDL_Keycode & key) override;
 	void textInputed(const std::string & enteredText) override;
 	void textEdited(const std::string & enteredText) override;
 

+ 10 - 11
client/adventureMap/CInfoBar.cpp

@@ -197,19 +197,18 @@ void CInfoBar::reset()
 void CInfoBar::showSelection()
 {
 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
-	if(adventureInt->selection)
+	if(adventureInt->curHero())
 	{
-		if(auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection))
-		{
-			showHeroSelection(hero);
-			return;
-		}
-		else if(auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection))
-		{
-			showTownSelection(town);
-			return;
-		}
+		showHeroSelection(adventureInt->curHero());
+		return;
 	}
+
+	if(adventureInt->curTown())
+	{
+		showTownSelection(adventureInt->curTown());
+		return;
+	}
+
 	showGameStatus();//FIXME: may be incorrect but shouldn't happen in general
 }
 

+ 9 - 15
client/adventureMap/CList.cpp

@@ -202,7 +202,7 @@ std::shared_ptr<CIntObject> CHeroList::CHeroItem::genSelection()
 
 void CHeroList::CHeroItem::select(bool on)
 {
-	if(on && adventureInt->selection != hero)
+	if(on && adventureInt->curHero() != hero)
 		adventureInt->select(hero);
 }
 
@@ -253,12 +253,9 @@ void CHeroList::update(const CGHeroInstance * hero)
 	//simplest solution for now: reset list and restore selection
 
 	listBox->resize(LOCPLINT->wanderingHeroes.size());
-	if (adventureInt->selection)
-	{
-		auto selectedHero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
-		if (selectedHero)
-			select(selectedHero);
-	}
+	if (adventureInt->curHero())
+		select(adventureInt->curHero());
+
 	CList::update();
 }
 
@@ -294,8 +291,8 @@ void CTownList::CTownItem::update()
 
 void CTownList::CTownItem::select(bool on)
 {
-	if (on && adventureInt->selection != town)
-			adventureInt->select(town);
+	if (on && adventureInt->curTown() != town)
+		adventureInt->select(town);
 }
 
 void CTownList::CTownItem::open()
@@ -328,12 +325,9 @@ void CTownList::update(const CGTownInstance *)
 	//simplest solution for now: reset list and restore selection
 
 	listBox->resize(LOCPLINT->towns.size());
-	if (adventureInt->selection)
-	{
-		auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection);
-		if (town)
-			select(town);
-	}
+	if (adventureInt->curTown())
+		select(adventureInt->curTown());
+
 	CList::update();
 }
 

+ 5 - 5
client/adventureMap/CMinimap.cpp

@@ -168,15 +168,15 @@ void CMinimap::showAll(SDL_Surface * to)
 		Canvas target(to);
 
 		int3 mapSizes = LOCPLINT->cb->getMapSize();
-		int3 tileCountOnScreen = adventureInt->terrain->tileCountOnScreen();
+		Rect screenArea = adventureInt->terrainAreaTiles();
 
 		//draw radar
 		Rect radar =
 		{
-			adventureInt->position.x * pos.w / mapSizes.x,
-			adventureInt->position.y * pos.h / mapSizes.y,
-			tileCountOnScreen.x * pos.w / mapSizes.x - 1,
-			tileCountOnScreen.y * pos.h / mapSizes.y - 1
+			screenArea.x * pos.w / mapSizes.x,
+			screenArea.y * pos.h / mapSizes.y,
+			screenArea.w * pos.w / mapSizes.x - 1,
+			screenArea.h * pos.h / mapSizes.y - 1
 		};
 
 		Canvas clippedTarget(target, pos);

+ 4 - 12
client/adventureMap/CResDataBar.cpp

@@ -13,7 +13,6 @@
 #include "../CGameInfo.h"
 #include "../CPlayerInterface.h"
 #include "../render/Colors.h"
-#include "../renderSDL/SDL_Extensions.h"
 #include "../gui/CGuiHandler.h"
 #include "../widgets/Images.h"
 
@@ -23,10 +22,6 @@
 
 #define ADVOPT (conf.go()->ac)
 
-void CResDataBar::clickRight(tribool down, bool previousState)
-{
-}
-
 CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist)
 {
 	pos.x += x;
@@ -70,8 +65,6 @@ CResDataBar::CResDataBar()
 
 }
 
-CResDataBar::~CResDataBar() = default;
-
 std::string CResDataBar::buildDateString()
 {
 	std::string pattern = "%s: %d, %s: %d, %s: %d";
@@ -96,14 +89,13 @@ void CResDataBar::draw(SDL_Surface * to)
 	graphics->fonts[FONT_SMALL]->renderTextLeft(to, buildDateString(), Colors::WHITE, Point(txtpos[7].first, txtpos[7].second));
 }
 
-void CResDataBar::show(SDL_Surface * to)
-{
-
-}
-
 void CResDataBar::showAll(SDL_Surface * to)
 {
 	CIntObject::showAll(to);
 	draw(to);
 }
 
+void CResDataBar::colorize(PlayerColor player)
+{
+	background->colorize(player);
+}

+ 4 - 5
client/adventureMap/CResDataBar.h

@@ -17,18 +17,17 @@ class CResDataBar : public CIntObject
 {
 	std::string buildDateString();
 
-public:
 	std::shared_ptr<CPicture> background;
 
 	std::vector<std::pair<int,int> > txtpos;
 
-	void clickRight(tribool down, bool previousState) override;
+
+	void draw(SDL_Surface * to);
+public:
 	CResDataBar();
 	CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist);
-	~CResDataBar();
 
-	void draw(SDL_Surface * to);
-	void show(SDL_Surface * to) override;
+	void colorize(PlayerColor player);
 	void showAll(SDL_Surface * to) override;
 };
 

+ 5 - 5
client/adventureMap/CTerrainRect.cpp

@@ -189,7 +189,7 @@ void CTerrainRect::hover(bool on)
 {
 	if (!on)
 	{
-		adventureInt->statusbar->clear();
+		GH.statusbar->clear();
 		CCS->curh->set(Cursor::Map::POINTER);
 	}
 	//Hoverable::hover(on);
@@ -381,17 +381,17 @@ int3 CTerrainRect::whichTileIsIt()
 	return whichTileIsIt(GH.getCursorPosition().x, GH.getCursorPosition().y);
 }
 
-int3 CTerrainRect::tileCountOnScreen()
+Rect CTerrainRect::visibleTilesArea()
 {
 	switch (adventureInt->mode)
 	{
 	default:
 		logGlobal->error("Unknown map mode %d", (int)adventureInt->mode);
-		return int3();
+		return Rect();
 	case EAdvMapMode::NORMAL:
-		return int3(tilesw, tilesh, 1);
+		return Rect(adventureInt->position.x, adventureInt->position.y, tilesw, tilesh);
 	case EAdvMapMode::WORLD_VIEW:
-		return int3((si32)(tilesw / adventureInt->worldViewScale), (si32)(tilesh / adventureInt->worldViewScale), 1);
+		return Rect(adventureInt->position.x, adventureInt->position.y, tilesw / adventureInt->worldViewScale, tilesh / adventureInt->worldViewScale);
 	}
 }
 

+ 1 - 1
client/adventureMap/CTerrainRect.h

@@ -63,7 +63,7 @@ public:
 	void showAnim(SDL_Surface * to);
 
 	/// @returns number of visible tiles on screen respecting current map scaling
-	int3 tileCountOnScreen();
+	Rect visibleTilesArea();
 
 	/// animates view by caching current surface and crossfading it with normal screen
 	void fadeFromCurrentView();

+ 2 - 2
client/battle/BattleInterface.cpp

@@ -132,10 +132,10 @@ BattleInterface::~BattleInterface()
 	CPlayerInterface::battleInt = nullptr;
 	givenCommand.cond.notify_all(); //that two lines should make any stacksController->getActiveStack() waiting thread to finish
 
-	if (adventureInt && adventureInt->selection)
+	if (adventureInt && adventureInt->curArmy())
 	{
 		//FIXME: this should be moved to adventureInt which should restore correct track based on selection/active player
-		const auto * terrain = LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType;
+		const auto * terrain = LOCPLINT->cb->getTile(adventureInt->curArmy()->visitablePos())->terType;
 		CCS->musich->playMusicFromSet("terrain", terrain->getJsonKey(), true, false);
 	}
 

+ 7 - 5
client/windows/InfoWindows.cpp

@@ -365,8 +365,10 @@ CRClickPopupInt::~CRClickPopupInt()
 
 Point CInfoBoxPopup::toScreen(Point p)
 {
-	vstd::abetween(p.x, adventureInt->terrain->pos.x + 100, adventureInt->terrain->pos.x + adventureInt->terrain->pos.w - 100);
-	vstd::abetween(p.y, adventureInt->terrain->pos.y + 100, adventureInt->terrain->pos.y + adventureInt->terrain->pos.h - 100);
+	auto bounds = adventureInt->terrainAreaPixels();
+
+	vstd::abetween(p.x, bounds.top() + 100, bounds.bottom() - 100);
+	vstd::abetween(p.y, bounds.left() + 100, bounds.right() - 100);
 
 	return p;
 }
@@ -375,7 +377,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town)
 	: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
 {
 	InfoAboutTown iah;
-	LOCPLINT->cb->getTownInfo(town, iah, adventureInt->selection); //todo: should this be nearest hero?
+	LOCPLINT->cb->getTownInfo(town, iah, adventureInt->curTown()); //todo: should this be nearest hero?
 
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	tooltip = std::make_shared<CTownTooltip>(Point(9, 10), iah);
@@ -385,7 +387,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero)
 	: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position))
 {
 	InfoAboutHero iah;
-	LOCPLINT->cb->getHeroInfo(hero, iah, adventureInt->selection);//todo: should this be nearest hero?
+	LOCPLINT->cb->getHeroInfo(hero, iah, adventureInt->curHero());//todo: should this be nearest hero?
 
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	tooltip = std::make_shared<CHeroTooltip>(Point(9, 10), iah);
@@ -404,7 +406,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr)
 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;
+		specific = adventureInt->curArmy();
 
 	if(nullptr == specific)
 	{