Bläddra i källkod

Initial part of dynamically-sized adventure map:

- removed no longer used CConfigHandler
- remove no longer use resolutions.json
- moved widget management from adventure map to a separate class
- adventure map layout is now loaded from config
Ivan Savenko 2 år sedan
förälder
incheckning
a015bf6507

+ 16 - 8
client/CMT.cpp

@@ -338,9 +338,6 @@ int main(int argc, char * argv[])
 	testFile("VIDEO/GOOD1A.SMK", "campaign movies");
 	testFile("SOUNDS/G1A.WAV", "campaign music"); //technically not a music but voiced intro sounds
 
-	conf.init();
-	logGlobal->info("Loading settings: %d ms", pomtime.getDiff());
-
 	srand ( (unsigned int)time(nullptr) );
 
 
@@ -659,10 +656,18 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
 	int renderWidth = 0, renderHeight = 0;
 	auto aspectRatio = (float)w / (float)h;
 	auto minDiff = 10.f;
-	for (const auto& pair : conf.guiOptions)
+
+	// TODO: CONFIGURABLE ADVMAP
+	static const std::vector<Point> supportedResolutions = {
+		{ 800, 600 }
+	};
+
+
+	for (const auto& pair : supportedResolutions)
 	{
-		int pWidth, pHeight;
-		std::tie(pWidth, pHeight) = pair.first;
+		int pWidth = pair.x;
+		int pHeight = pair.y;
+
 		/* filter out resolution which is larger than window */
 		if (pWidth > w || pHeight > h)
 		{
@@ -690,10 +695,13 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
 		// no matching resolution for upscaling - complain & fallback to default resolution.
 		logGlobal->error("Failed to match rendering resolution for %dx%d!", w, h);
 		Settings newRes = settings.write["video"]["screenRes"];
-		std::tie(w, h) = conf.guiOptions.begin()->first;
+
+		w = supportedResolutions.front().x;
+		h = supportedResolutions.front().y;
+
 		newRes["width"].Float() = w;
 		newRes["height"].Float() = h;
-		conf.SetResolution(w, h);
+
 		logGlobal->error("Falling back to %dx%d", w, h);
 		renderWidth = w;
 		renderHeight = h;

+ 2 - 2
client/CMakeLists.txt

@@ -2,8 +2,8 @@ set(client_SRCS
 	StdInc.cpp
 	../CCallback.cpp
 
-	adventureMap/CAdvMapPanel.cpp
 	adventureMap/CAdventureMapInterface.cpp
+	adventureMap/CAdventureMapWidget.cpp
 	adventureMap/CAdventureOptions.cpp
 	adventureMap/CInGameConsole.cpp
 	adventureMap/CInfoBar.cpp
@@ -129,8 +129,8 @@ set(client_SRCS
 set(client_HEADERS
 	StdInc.h
 
-	adventureMap/CAdvMapPanel.h
 	adventureMap/CAdventureMapInterface.h
+	adventureMap/CAdventureMapWidget.h
 	adventureMap/CAdventureOptions.h
 	adventureMap/CInGameConsole.h
 	adventureMap/CInfoBar.h

+ 0 - 1
client/CPlayerInterface.cpp

@@ -15,7 +15,6 @@
 #include "adventureMap/CAdventureMapInterface.h"
 #include "mapView/mapHandler.h"
 #include "adventureMap/CList.h"
-#include "adventureMap/CInfoBar.h"
 #include "battle/BattleInterface.h"
 #include "battle/BattleEffectsController.h"
 #include "battle/BattleFieldController.h"

+ 0 - 94
client/adventureMap/CAdvMapPanel.cpp

@@ -1,94 +0,0 @@
-/*
- * CAdvMapPanel.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-
-#include "StdInc.h"
-#include "CAdvMapPanel.h"
-
-#include "../widgets/Buttons.h"
-#include "../widgets/Images.h"
-#include "../render/CAnimation.h"
-#include "../render/IImage.h"
-#include "../gui/CGuiHandler.h"
-
-CAdvMapPanel::CAdvMapPanel(std::shared_ptr<IImage> bg, Point position)
-	: CIntObject()
-	, background(bg)
-{
-	defActions = 255;
-	recActions = 255;
-	pos.x += position.x;
-	pos.y += position.y;
-	if (bg)
-	{
-		pos.w = bg->width();
-		pos.h = bg->height();
-	}
-}
-
-void CAdvMapPanel::addChildColorableButton(std::shared_ptr<CButton> button)
-{
-	colorableButtons.push_back(button);
-	addChildToPanel(button, ACTIVATE | DEACTIVATE);
-}
-
-void CAdvMapPanel::setPlayerColor(const PlayerColor & clr)
-{
-	for(auto & button : colorableButtons)
-	{
-		button->setPlayerColor(clr);
-	}
-}
-
-void CAdvMapPanel::showAll(SDL_Surface * to)
-{
-	if(background)
-		background->draw(to, pos.x, pos.y);
-
-	CIntObject::showAll(to);
-}
-
-void CAdvMapPanel::addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions)
-{
-	otherObjects.push_back(obj);
-	obj->recActions |= actions | SHOWALL;
-	obj->recActions &= ~DISPOSE;
-	addChild(obj.get(), false);
-}
-
-CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color)
-	: CAdvMapPanel(bg, position), icons(_icons)
-{
-	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
-	int fillerHeight = bg ? spaceBottom - pos.y - pos.h : 0;
-
-	if(fillerHeight > 0)
-	{
-		backgroundFiller = std::make_shared<CFilledTexture>("DIBOXBCK", Rect(0, pos.h, pos.w, fillerHeight));
-	}
-}
-
-void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOffset)
-{
-	assert(iconsData.size() == currentIcons.size());
-
-	for(size_t idx = 0; idx < iconsData.size(); idx++)
-	{
-		const auto & data = iconsData.at(idx);
-		currentIcons[idx]->setFrame(data.first + indexOffset);
-	}
-}
-
-void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOffset)
-{
-	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
-	iconsData.push_back(data);
-	currentIcons.push_back(std::make_shared<CAnimImage>(icons, data.first + indexOffset, 0, data.second.x, data.second.y));
-}
-

+ 0 - 60
client/adventureMap/CAdvMapPanel.h

@@ -1,60 +0,0 @@
-/*
- * CAdvMapPanel.h, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#pragma once
-
-#include "../gui/CIntObject.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-class PlayerColor;
-VCMI_LIB_NAMESPACE_END
-
-class CAnimation;
-class CAnimImage;
-class CFilledTexture;
-class CButton;
-class IImage;
-
-/// simple panel that contains other displayable elements; used to separate groups of controls
-class CAdvMapPanel : public CIntObject
-{
-	std::vector<std::shared_ptr<CButton>> colorableButtons;
-	std::vector<std::shared_ptr<CIntObject>> otherObjects;
-	/// the surface passed to this obj will be freed in dtor
-	std::shared_ptr<IImage> background;
-public:
-	CAdvMapPanel(std::shared_ptr<IImage> bg, Point position);
-
-	void addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions = 0);
-	void addChildColorableButton(std::shared_ptr<CButton> button);
-	/// recolors all buttons to given player color
-	void setPlayerColor(const PlayerColor & clr);
-
-	void showAll(SDL_Surface * to) override;
-};
-
-/// specialized version of CAdvMapPanel that handles recolorable def-based pictures for world view info panel
-class CAdvMapWorldViewPanel : public CAdvMapPanel
-{
-	/// data that allows reconstruction of panel info icons
-	std::vector<std::pair<int, Point>> iconsData;
-	/// ptrs to child-pictures constructed from iconsData
-	std::vector<std::shared_ptr<CAnimImage>> currentIcons;
-	/// 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, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color);
-
-	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);
-};
-

+ 74 - 335
client/adventureMap/CAdventureMapInterface.cpp

@@ -1,5 +1,5 @@
 /*
- * CAdvMapInt.cpp, part of VCMI engine
+ * CAdventureMapInterface.cpp, part of VCMI engine
  *
  * Authors: listed in file AUTHORS in main folder
  *
@@ -10,14 +10,13 @@
 #include "StdInc.h"
 #include "CAdventureMapInterface.h"
 
-#include "CAdvMapPanel.h"
 #include "CAdventureOptions.h"
 #include "CInGameConsole.h"
 #include "CMinimap.h"
-#include "CResDataBar.h"
 #include "CList.h"
 #include "CInfoBar.h"
 #include "MapAudioPlayer.h"
+#include "CAdventureMapWidget.h"
 
 #include "../mapView/mapHandler.h"
 #include "../mapView/MapView.h"
@@ -32,6 +31,7 @@
 #include "../render/CAnimation.h"
 #include "../gui/CursorHandler.h"
 #include "../render/IImage.h"
+#include "../renderSDL/SDL_Extensions.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/Shortcut.h"
 #include "../widgets/TextControls.h"
@@ -49,171 +49,24 @@
 #include "../../lib/CPathfinder.h"
 #include "../../lib/mapping/CMap.h"
 
-#define ADVOPT (conf.go()->ac)
-
 std::shared_ptr<CAdventureMapInterface> adventureInt;
 
 CAdventureMapInterface::CAdventureMapInterface():
-	minimap(new CMinimap(Rect(ADVOPT.minimapX, ADVOPT.minimapY, ADVOPT.minimapW, ADVOPT.minimapH))),
-	statusbar(CGStatusBar::create(ADVOPT.statusbarX,ADVOPT.statusbarY,ADVOPT.statusbarG)),
-	heroList(new CHeroList(ADVOPT.hlistSize, Point(ADVOPT.hlistX, ADVOPT.hlistY), ADVOPT.hlistAU, ADVOPT.hlistAD)),
-	townList(new CTownList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD)),
-	infoBar(new CInfoBar(Point(ADVOPT.infoboxX, ADVOPT.infoboxY))),
-	resdatabar(new CResDataBar),
 	mapAudio(new MapAudioPlayer()),
-	terrain(new MapView(Point(ADVOPT.advmapX, ADVOPT.advmapY), Point(ADVOPT.advmapW, ADVOPT.advmapH))),
-	state(EGameState::NOT_INITIALIZED),
 	spellBeingCasted(nullptr),
-	activeMapPanel(nullptr),
 	scrollingCursorSet(false)
 {
+	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
 	pos.x = pos.y = 0;
 	pos.w = GH.screenDimensions().x;
 	pos.h = GH.screenDimensions().y;
 	strongInterest = true; // handle all mouse move events to prevent dead mouse move space in fullscreen mode
 
-	bg = IImage::createFromFile(ADVOPT.mainGraphic);
-	if(!ADVOPT.worldViewGraphic.empty())
-	{
-		bgWorldView = IImage::createFromFile(ADVOPT.worldViewGraphic);
-	}
-	else
-	{
-		bgWorldView = nullptr;
-		logGlobal->warn("ADVOPT.worldViewGraphic is empty => bitmap not loaded");
-	}
-	if (!bgWorldView)
-	{
-		logGlobal->warn("bgWorldView not defined in resolution config; fallback to VWorld.bmp");
-		bgWorldView = IImage::createFromFile("VWorld.bmp");
-	}
-
-	worldViewIcons = std::make_shared<CAnimation>("VwSymbol");//todo: customize with ADVOPT
-	worldViewIcons->preload();
-
-	for(int g = 0; g < ADVOPT.gemG.size(); ++g)
-	{
-		gems.push_back(std::make_shared<CAnimImage>(ADVOPT.gemG[g], 0, 0, ADVOPT.gemX[g], ADVOPT.gemY[g]));
-	}
-
-	auto makeButton = [&](int textID, std::function<void()> callback, config::ButtonInfo info, EShortcut key) -> std::shared_ptr<CButton>
-	{
-		auto button = std::make_shared<CButton>(Point(info.x, info.y), info.defName, CGI->generaltexth->zelp[textID], callback, key, info.playerColoured);
-		for(auto image : info.additionalDefs)
-			button->addImage(image);
-		return button;
-	};
-
-	kingOverview = makeButton(293, std::bind(&CAdventureMapInterface::fshowOverview,this),     ADVOPT.kingOverview, EShortcut::ADVENTURE_KINGDOM_OVERVIEW);
-	underground  = makeButton(294, std::bind(&CAdventureMapInterface::fswitchLevel,this),      ADVOPT.underground,  EShortcut::ADVENTURE_TOGGLE_MAP_LEVEL);
-	questlog     = makeButton(295, std::bind(&CAdventureMapInterface::fshowQuestlog,this),     ADVOPT.questlog,     EShortcut::ADVENTURE_QUEST_LOG);
-	sleepWake    = makeButton(296, std::bind(&CAdventureMapInterface::fsleepWake,this),        ADVOPT.sleepWake,    EShortcut::ADVENTURE_TOGGLE_SLEEP);
-	moveHero     = makeButton(297, std::bind(&CAdventureMapInterface::fmoveHero,this),         ADVOPT.moveHero,     EShortcut::ADVENTURE_MOVE_HERO);
-	spellbook    = makeButton(298, std::bind(&CAdventureMapInterface::fshowSpellbok,this),     ADVOPT.spellbook,    EShortcut::ADVENTURE_CAST_SPELL);
-	advOptions   = makeButton(299, std::bind(&CAdventureMapInterface::fadventureOPtions,this), ADVOPT.advOptions,   EShortcut::ADVENTURE_GAME_OPTIONS);
-	sysOptions   = makeButton(300, std::bind(&CAdventureMapInterface::fsystemOptions,this),    ADVOPT.sysOptions,   EShortcut::GLOBAL_OPTIONS);
-	nextHero     = makeButton(301, std::bind(&CAdventureMapInterface::fnextHero,this),         ADVOPT.nextHero,     EShortcut::ADVENTURE_NEXT_HERO);
-	endTurn      = makeButton(302, std::bind(&CAdventureMapInterface::fendTurn,this),          ADVOPT.endTurn,      EShortcut::ADVENTURE_END_TURN);
-
-	int panelSpaceBottom = GH.screenDimensions().y - resdatabar->pos.h - 4;
-
-	panelMain = std::make_shared<CAdvMapPanel>(nullptr, Point(0, 0));
-	// TODO correct drawing position
-	panelWorldView = std::make_shared<CAdvMapWorldViewPanel>(worldViewIcons, bgWorldView, Point(heroList->pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID);
-
-	panelMain->addChildColorableButton(kingOverview);
-	panelMain->addChildColorableButton(underground);
-	panelMain->addChildColorableButton(questlog);
-	panelMain->addChildColorableButton(sleepWake);
-	panelMain->addChildColorableButton(moveHero);
-	panelMain->addChildColorableButton(spellbook);
-	panelMain->addChildColorableButton(advOptions);
-	panelMain->addChildColorableButton(sysOptions);
-	panelMain->addChildColorableButton(nextHero);
-	panelMain->addChildColorableButton(endTurn);
-
-
-	// TODO move configs to resolutions.json, similarly to previous buttons
-	config::ButtonInfo worldViewBackConfig = config::ButtonInfo();
-	worldViewBackConfig.defName = "IOK6432.DEF";
-	worldViewBackConfig.x = GH.screenDimensions().x - 73;
-	worldViewBackConfig.y = 343 + 195;
-	worldViewBackConfig.playerColoured = false;
-	panelWorldView->addChildToPanel(
-		makeButton(288, std::bind(&CAdventureMapInterface::fworldViewBack,this), worldViewBackConfig, EShortcut::GLOBAL_CANCEL), ACTIVATE | DEACTIVATE);
-
-	config::ButtonInfo worldViewPuzzleConfig = config::ButtonInfo();
-	worldViewPuzzleConfig.defName = "VWPUZ.DEF";
-	worldViewPuzzleConfig.x = GH.screenDimensions().x - 188;
-	worldViewPuzzleConfig.y = 343 + 195;
-	worldViewPuzzleConfig.playerColoured = false;
-	panelWorldView->addChildToPanel( // no help text for this one
-		std::make_shared<CButton>(Point(worldViewPuzzleConfig.x, worldViewPuzzleConfig.y), worldViewPuzzleConfig.defName, std::pair<std::string, std::string>(),
-				std::bind(&CPlayerInterface::showPuzzleMap,LOCPLINT), EShortcut::ADVENTURE_VIEW_PUZZLE, worldViewPuzzleConfig.playerColoured), ACTIVATE | DEACTIVATE);
-
-	config::ButtonInfo worldViewScale1xConfig = config::ButtonInfo();
-	worldViewScale1xConfig.defName = "VWMAG1.DEF";
-	worldViewScale1xConfig.x = GH.screenDimensions().x - 191;
-	worldViewScale1xConfig.y = 23 + 195;
-	worldViewScale1xConfig.playerColoured = false;
-	panelWorldView->addChildToPanel( // help text is wrong for this button
-		makeButton(291, std::bind(&CAdventureMapInterface::fworldViewScale1x,this), worldViewScale1xConfig, EShortcut::SELECT_INDEX_1), ACTIVATE | DEACTIVATE);
-
-	config::ButtonInfo worldViewScale2xConfig = config::ButtonInfo();
-	worldViewScale2xConfig.defName = "VWMAG2.DEF";
-	worldViewScale2xConfig.x = GH.screenDimensions().x- 191 + 63;
-	worldViewScale2xConfig.y = 23 + 195;
-	worldViewScale2xConfig.playerColoured = false;
-	panelWorldView->addChildToPanel( // help text is wrong for this button
-		makeButton(291, std::bind(&CAdventureMapInterface::fworldViewScale2x,this), worldViewScale2xConfig, EShortcut::SELECT_INDEX_2), ACTIVATE | DEACTIVATE);
-
-	config::ButtonInfo worldViewScale4xConfig = config::ButtonInfo();
-	worldViewScale4xConfig.defName = "VWMAG4.DEF";
-	worldViewScale4xConfig.x = GH.screenDimensions().x- 191 + 126;
-	worldViewScale4xConfig.y = 23 + 195;
-	worldViewScale4xConfig.playerColoured = false;
-	panelWorldView->addChildToPanel( // help text is wrong for this button
-		makeButton(291, std::bind(&CAdventureMapInterface::fworldViewScale4x,this), worldViewScale4xConfig, EShortcut::SELECT_INDEX_4), ACTIVATE | DEACTIVATE);
-
-	config::ButtonInfo worldViewUndergroundConfig = config::ButtonInfo();
-	worldViewUndergroundConfig.defName = "IAM010.DEF";
-	worldViewUndergroundConfig.additionalDefs.push_back("IAM003.DEF");
-	worldViewUndergroundConfig.x = GH.screenDimensions().x - 115;
-	worldViewUndergroundConfig.y = 343 + 195;
-	worldViewUndergroundConfig.playerColoured = true;
-	worldViewUnderground = makeButton(294, std::bind(&CAdventureMapInterface::fswitchLevel,this), worldViewUndergroundConfig, EShortcut::ADVENTURE_TOGGLE_MAP_LEVEL);
-	panelWorldView->addChildColorableButton(worldViewUnderground);
-
-	onCurrentPlayerChanged(LOCPLINT->playerID);
-
-	int iconColorMultiplier = currentPlayerID.getNum() * 19;
-	int wvLeft = heroList->pos.x - 2; // TODO correct drawing position
-	//int wvTop = 195;
-	for (int i = 0; i < 5; ++i)
-	{
-		panelWorldView->addChildIcon(std::pair<int, Point>(i, Point(5, 58 + i * 20)), iconColorMultiplier);
-		panelWorldView->addChildToPanel(std::make_shared<CLabel>(wvLeft + 45, 263 + i * 20, EFonts::FONT_SMALL, ETextAlignment::TOPLEFT,
-												Colors::WHITE, CGI->generaltexth->allTexts[612 + i]));
-	}
-	for (int i = 0; i < 7; ++i)
-	{
-		panelWorldView->addChildIcon(std::pair<int, Point>(i +  5, Point(5, 182 + i * 20)), iconColorMultiplier);
-		panelWorldView->addChildIcon(std::pair<int, Point>(i + 12, Point(160, 182 + i * 20)), iconColorMultiplier);
-		panelWorldView->addChildToPanel(std::make_shared<CLabel>(wvLeft + 45, 387 + i * 20, EFonts::FONT_SMALL, ETextAlignment::TOPLEFT,
-												Colors::WHITE, CGI->generaltexth->allTexts[619 + i]));
-	}
-	panelWorldView->addChildToPanel(std::make_shared<CLabel>(wvLeft +   5, 367, EFonts::FONT_SMALL, ETextAlignment::TOPLEFT,
-											Colors::WHITE, CGI->generaltexth->allTexts[617]));
-	panelWorldView->addChildToPanel(std::make_shared<CLabel>(wvLeft + 45, 367, EFonts::FONT_SMALL, ETextAlignment::TOPLEFT,
-											Colors::WHITE, CGI->generaltexth->allTexts[618]));
-
-	activeMapPanel = panelMain;
-
+	widget = std::make_shared<CAdventureMapWidget>();
 	exitWorldView();
 
-	underground->block(!CGI->mh->getMap()->twoLevel);
-	questlog->block(!CGI->mh->getMap()->quests.size());
-	worldViewUnderground->block(!CGI->mh->getMap()->twoLevel);
+	widget->setOptionHasQuests(!CGI->mh->getMap()->quests.empty());
+	widget->setOptionHasUnderground(CGI->mh->getMap()->twoLevel);
 }
 
 void CAdventureMapInterface::fshowOverview()
@@ -253,18 +106,13 @@ void CAdventureMapInterface::fswitchLevel()
 	if (maxLevels < 2)
 		return;
 
-	terrain->onMapLevelSwitched();
+	widget->getMapView()->onMapLevelSwitched();
 }
 
 void CAdventureMapInterface::onMapViewMoved(const Rect & visibleArea, int mapLevel)
 {
-	underground->setIndex(mapLevel, true);
-	underground->redraw();
-
-	worldViewUnderground->setIndex(mapLevel, true);
-	worldViewUnderground->redraw();
-
-	minimap->onMapViewMoved(visibleArea, mapLevel);
+	widget->setOptionUndergroundLevel(mapLevel > 0);
+	widget->getMinimap()->onMapViewMoved(visibleArea, mapLevel);
 }
 
 void CAdventureMapInterface::onAudioResumed()
@@ -298,9 +146,6 @@ void CAdventureMapInterface::fsleepWake()
 
 	if (newSleep)
 		fnextHero();
-
-	// redraw to update the image of sleep/wake button
-	panelMain->redraw();
 }
 
 void CAdventureMapInterface::fmoveHero()
@@ -381,59 +226,48 @@ void CAdventureMapInterface::fendTurn()
 void CAdventureMapInterface::updateButtons()
 {
 	const auto * hero = LOCPLINT->localState->getCurrentHero();
-
-	sleepWake->block(!hero);
-	spellbook->block(!hero);
-	moveHero->block(!hero || !LOCPLINT->localState->hasPath(hero) || hero->movement == 0);
-
 	const auto * nextSuitableHero = LOCPLINT->localState->getNextWanderingHero(hero);
-	nextHero->block(nextSuitableHero == nullptr);
 
-	if(hero)
-	{
-		bool state = LOCPLINT->localState->isHeroSleeping(hero);
-		sleepWake->setIndex(state ? 1 : 0, true);
-		sleepWake->redraw();
-	}
+	widget->setOptionHeroSelected(hero != nullptr);
+	widget->setOptionHeroCanMove(hero && LOCPLINT->localState->hasPath(hero) && hero->movement != 0);
+	widget->setOptionHasNextHero(nextSuitableHero != nullptr);
+	widget->setOptionHeroSleeping(hero && LOCPLINT->localState->isHeroSleeping(hero));
 }
 
 void CAdventureMapInterface::onHeroMovementStarted(const CGHeroInstance * hero)
 {
-	infoBar->popAll();
-	infoBar->showSelection();
+	widget->getInfoBar()->popAll();
+	widget->getInfoBar()->showSelection();
 }
 
 void CAdventureMapInterface::onHeroChanged(const CGHeroInstance *h)
 {
-	heroList->update(h);
+	widget->getHeroList()->update(h);
 
-	if (h && h == LOCPLINT->localState->getCurrentHero() && !infoBar->showingComponents())
-		infoBar->showSelection();
+	if (h && h == LOCPLINT->localState->getCurrentHero() && !widget->getInfoBar()->showingComponents())
+		widget->getInfoBar()->showSelection();
 
 	updateButtons();
 }
 
 void CAdventureMapInterface::onTownChanged(const CGTownInstance * town)
 {
-	townList->update(town);
+	widget->getTownList()->update(town);
 
-	if (town && town == LOCPLINT->localState->getCurrentTown() && !infoBar->showingComponents())
-		infoBar->showSelection();
+	if (town && town == LOCPLINT->localState->getCurrentTown() && !widget->getInfoBar()->showingComponents())
+		widget->getInfoBar()->showSelection();
 }
 
 void CAdventureMapInterface::showInfoBoxMessage(const std::vector<Component> & components, std::string message, int timer)
 {
-	infoBar->pushComponents(components, message, timer);
+	widget->getInfoBar()->pushComponents(components, message, timer);
 }
 
 void CAdventureMapInterface::activate()
 {
 	CIntObject::activate();
-	if (!(active & KEYBOARD))
-		CIntObject::activate(KEYBOARD);
 
 	screenBuf = screen;
-	GH.statusbar = statusbar;
 	
 	if(LOCPLINT)
 	{
@@ -441,94 +275,28 @@ void CAdventureMapInterface::activate()
 		LOCPLINT->cingconsole->pos = this->pos;
 	}
 
-	if(state != EGameState::ENEMY_TURN && state != EGameState::HOTSEAT_WAIT)
-	{
-		assert(state == EGameState::MAKING_TURN);
-
-		activeMapPanel->activate();
-		if (state == EGameState::MAKING_TURN)
-		{
-			heroList->activate();
-			townList->activate();
-			infoBar->activate();
-		}
-		minimap->activate();
-		terrain->activate();
-		statusbar->activate();
-
-		GH.fakeMouseMove(); //to restore the cursor
-	}
+	GH.fakeMouseMove(); //to restore the cursor
 }
 
 void CAdventureMapInterface::deactivate()
 {
 	CIntObject::deactivate();
-
-	if(state != EGameState::ENEMY_TURN && state != EGameState::HOTSEAT_WAIT)
-	{
-		assert(state == EGameState::MAKING_TURN);
-
-		CCS->curh->set(Cursor::Map::POINTER);
-		activeMapPanel->deactivate();
-		if (state == EGameState::MAKING_TURN)
-		{
-			heroList->deactivate();
-			townList->deactivate();
-			infoBar->deactivate();
-		}
-		minimap->deactivate();
-		terrain->deactivate();
-		statusbar->deactivate();
-	}
+	CCS->curh->set(Cursor::Map::POINTER);
 }
 
 void CAdventureMapInterface::showAll(SDL_Surface * to)
 {
-	bg->draw(to, 0, 0);
-
-//	if(state != EGameState::MAKING_TURN)
-//		return;
-
-	heroList->showAll(to);
-	townList->showAll(to);
-	infoBar->showAll(to);
-
-	activeMapPanel->showAll(to);
-
-	minimap->showAll(to);
-	terrain->showAll(to);
-	show(to);
-
-	resdatabar->showAll(to);
-	statusbar->show(to);
+	CSDL_Ext::fillSurface(to, CSDL_Ext::toSDL(ColorRGBA(255, 0,255,255)));// FIXME: CONFIGURABLE ADVMAP - debug fill to detect any empty areas
+	CIntObject::showAll(to);
 	LOCPLINT->cingconsole->show(to);
 }
 
 void CAdventureMapInterface::show(SDL_Surface * to)
 {
-//	if(state != EGameState::MAKING_TURN)
-//		return;
-
 	handleMapScrollingUpdate();
 
-	for(int i = 0; i < 4; i++)
-	{
-		if(settings["session"]["spectate"].Bool())
-			gems[i]->setFrame(PlayerColor(1).getNum());
-		else
-			gems[i]->setFrame(LOCPLINT->playerID.getNum());
-	}
-
-	minimap->show(to);
-	terrain->show(to);
-
-	for(int i = 0; i < 4; i++)
-		gems[i]->showAll(to);
-
+	CIntObject::show(to);
 	LOCPLINT->cingconsole->show(to);
-
-	infoBar->show(to);
-	statusbar->showAll(to);
 }
 
 void CAdventureMapInterface::handleMapScrollingUpdate()
@@ -540,7 +308,7 @@ void CAdventureMapInterface::handleMapScrollingUpdate()
 	uint32_t scrollSpeedPixels = settings["adventure"]["scrollSpeedPixels"].Float();
 	uint32_t scrollDistance = scrollSpeedPixels * timePassed / 1000;
 
-	bool scrollingActive = !GH.isKeyboardCtrlDown() && isActive() && state == EGameState::MAKING_TURN;
+	bool scrollingActive = !GH.isKeyboardCtrlDown() && isActive() && widget->getState() == EGameState::MAKING_TURN;
 
 	Point cursorPosition = GH.getCursorPosition();
 	Point scrollDirection;
@@ -560,7 +328,7 @@ void CAdventureMapInterface::handleMapScrollingUpdate()
 	Point scrollDelta = scrollDirection * scrollDistance;
 
 	if (scrollingActive && scrollDelta != Point(0,0))
-		terrain->onMapScrolled(scrollDelta);
+		widget->getMapView()->onMapScrolled(scrollDelta);
 
 	if (scrollDelta == Point(0,0) && !scrollingCursorSet)
 		return;
@@ -599,17 +367,17 @@ void CAdventureMapInterface::handleMapScrollingUpdate()
 
 void CAdventureMapInterface::centerOnTile(int3 on)
 {
-	terrain->onCenteredTile(on);
+	widget->getMapView()->onCenteredTile(on);
 }
 
 void CAdventureMapInterface::centerOnObject(const CGObjectInstance * obj)
 {
-	terrain->onCenteredObject(obj);
+	widget->getMapView()->onCenteredObject(obj);
 }
 
 void CAdventureMapInterface::keyPressed(EShortcut key)
 {
-	if (state != EGameState::MAKING_TURN)
+	if (widget->getState() != EGameState::MAKING_TURN)
 		return;
 
 	//fake mouse use to trigger onTileHovered()
@@ -726,7 +494,7 @@ void CAdventureMapInterface::keyPressed(EShortcut key)
 	case EShortcut::ADVENTURE_NEXT_TOWN:
 			if(isActive() && !GH.isKeyboardCtrlDown()) //no ctrl, advmapint is on the top => switch to town
 			{
-				townList->selectNext();
+				widget->getTownList()->selectNext();
 			}
 			return;
 		}
@@ -778,7 +546,7 @@ void CAdventureMapInterface::onSelectionChanged(const CArmedInstance *sel)
 {
 	assert(sel);
 
-	infoBar->popAll();
+	widget->getInfoBar()->popAll();
 	mapAudio->onSelectionChanged(sel);
 	bool centerView = !settings["session"]["autoSkip"].Bool();
 
@@ -789,25 +557,25 @@ void CAdventureMapInterface::onSelectionChanged(const CArmedInstance *sel)
 	{
 		auto town = dynamic_cast<const CGTownInstance*>(sel);
 
-		infoBar->showTownSelection(town);
-		townList->select(town);
-		heroList->select(nullptr);
+		widget->getInfoBar()->showTownSelection(town);
+		widget->getTownList()->select(town);
+		widget->getHeroList()->select(nullptr);
 		onHeroChanged(nullptr);
 	}
 	else //hero selected
 	{
 		auto hero = dynamic_cast<const CGHeroInstance*>(sel);
 
-		infoBar->showHeroSelection(hero);
-		heroList->select(hero);
-		townList->select(nullptr);
+		widget->getInfoBar()->showHeroSelection(hero);
+		widget->getHeroList()->select(hero);
+		widget->getTownList()->select(nullptr);
 
 		LOCPLINT->localState->verifyPath(hero);
 		onHeroChanged(hero);
 	}
 	updateButtons();
-	townList->redraw();
-	heroList->redraw();
+	widget->getHeroList()->redraw();
+	widget->getTownList()->redraw();
 }
 
 bool CAdventureMapInterface::isActive()
@@ -818,15 +586,15 @@ bool CAdventureMapInterface::isActive()
 void CAdventureMapInterface::onMapTilesChanged(boost::optional<std::unordered_set<int3>> positions)
 {
 	if (positions)
-		minimap->updateTiles(*positions);
+		widget->getMinimap()->updateTiles(*positions);
 	else
-		minimap->update();
+		widget->getMinimap()->update();
 }
 
 void CAdventureMapInterface::onHotseatWaitStarted(PlayerColor playerID)
 {
 	onCurrentPlayerChanged(playerID);
-	state = EGameState::HOTSEAT_WAIT;
+	widget->setState(EGameState::HOTSEAT_WAIT);
 }
 
 void CAdventureMapInterface::onEnemyTurnStarted(PlayerColor playerID)
@@ -836,10 +604,10 @@ void CAdventureMapInterface::onEnemyTurnStarted(PlayerColor playerID)
 
 	adjustActiveness(true);
 	mapAudio->onEnemyTurnStarted();
-	minimap->setAIRadar(true);
-	infoBar->startEnemyTurn(LOCPLINT->cb->getCurrentPlayer());
-	minimap->showAll(screen);//force refresh on inactive object
-	infoBar->showAll(screen);//force refresh on inactive object
+	widget->getMinimap()->setAIRadar(true);
+	widget->getInfoBar()->startEnemyTurn(LOCPLINT->cb->getCurrentPlayer());
+	widget->getMinimap()->showAll(screen);//force refresh on inactive object
+	widget->getInfoBar()->showAll(screen);//force refresh on inactive object
 }
 
 void CAdventureMapInterface::adjustActiveness(bool aiTurnStart)
@@ -850,9 +618,9 @@ void CAdventureMapInterface::adjustActiveness(bool aiTurnStart)
 		deactivate();
 
 	if (aiTurnStart)
-		state = EGameState::ENEMY_TURN;
+		widget->setState(EGameState::ENEMY_TURN);
 	else
-		state = EGameState::MAKING_TURN;
+		widget->setState(EGameState::MAKING_TURN);
 
 	if(wasActive)
 		activate();
@@ -866,29 +634,24 @@ void CAdventureMapInterface::onCurrentPlayerChanged(PlayerColor playerID)
 		return;
 
 	currentPlayerID = playerID;
-	bg->playerColored(currentPlayerID);
-
-	panelMain->setPlayerColor(currentPlayerID);
-	panelWorldView->setPlayerColor(currentPlayerID);
-	panelWorldView->recolorIcons(currentPlayerID, currentPlayerID.getNum() * 19);
-	resdatabar->colorize(currentPlayerID);
+	widget->setPlayer(playerID);
 }
 
 void CAdventureMapInterface::onPlayerTurnStarted(PlayerColor playerID)
 {
 	onCurrentPlayerChanged(playerID);
 
-	state = EGameState::MAKING_TURN;
+	widget->setState(EGameState::MAKING_TURN);
 	if(LOCPLINT->cb->getCurrentPlayer() == LOCPLINT->playerID
 		|| settings["session"]["spectate"].Bool())
 	{
 		adjustActiveness(false);
-		minimap->setAIRadar(false);
-		infoBar->showSelection();
+		widget->getMinimap()->setAIRadar(false);
+		widget->getInfoBar()->showSelection();
 	}
 
-	heroList->update();
-	townList->update();
+	widget->getHeroList()->update();
+	widget->getTownList()->update();
 
 	const CGHeroInstance * heroToSelect = nullptr;
 
@@ -917,7 +680,7 @@ void CAdventureMapInterface::onPlayerTurnStarted(PlayerColor playerID)
 	}
 
 	//show new day animation and sound on infobar
-	infoBar->showDate();
+	widget->getInfoBar()->showDate();
 
 	onHeroChanged(nullptr);
 	showAll(screen);
@@ -959,7 +722,7 @@ const CGObjectInstance* CAdventureMapInterface::getActiveObject(const int3 &mapP
 
 void CAdventureMapInterface::onTileLeftClicked(const int3 &mapPos)
 {
-	if(state != EGameState::MAKING_TURN)
+	if(widget->getState() == EGameState::MAKING_TURN)
 		return;
 
 	//FIXME: this line breaks H3 behavior for Dimension Door
@@ -1050,7 +813,7 @@ void CAdventureMapInterface::onTileLeftClicked(const int3 &mapPos)
 
 void CAdventureMapInterface::onTileHovered(const int3 &mapPos)
 {
-	if(state != EGameState::MAKING_TURN)
+	if(widget->getState() != EGameState::MAKING_TURN)
 		return;
 
 	//may occur just at the start of game (fake move before full intiialization)
@@ -1060,7 +823,7 @@ void CAdventureMapInterface::onTileHovered(const int3 &mapPos)
 	if(!LOCPLINT->cb->isVisible(mapPos))
 	{
 		CCS->curh->set(Cursor::Map::POINTER);
-		statusbar->clear();
+		GH.statusbar->clear();
 		return;
 	}
 	auto objRelations = PlayerRelations::ALLIES;
@@ -1070,12 +833,12 @@ void CAdventureMapInterface::onTileHovered(const int3 &mapPos)
 		objRelations = LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, objAtTile->tempOwner);
 		std::string text = LOCPLINT->localState->getCurrentHero() ? objAtTile->getHoverText(LOCPLINT->localState->getCurrentHero()) : objAtTile->getHoverText(LOCPLINT->playerID);
 		boost::replace_all(text,"\n"," ");
-		statusbar->write(text);
+		GH.statusbar->write(text);
 	}
 	else
 	{
 		std::string hlp = CGI->mh->getTerrainDescr(mapPos, false);
-		statusbar->write(hlp);
+		GH.statusbar->write(hlp);
 	}
 
 	if(spellBeingCasted)
@@ -1212,12 +975,12 @@ void CAdventureMapInterface::showMoveDetailsInStatusbar(const CGHeroInstance & h
 	boost::replace_first(result, "%POINTS", std::to_string(movementPointsLastTurnCost));
 	boost::replace_first(result, "%REMAINING", std::to_string(remainingPointsAfterMove));
 
-	statusbar->write(result);
+	GH.statusbar->write(result);
 }
 
 void CAdventureMapInterface::onTileRightClicked(const int3 &mapPos)
 {
-	if(state != EGameState::MAKING_TURN)
+	if(widget->getState() != EGameState::MAKING_TURN)
 		return;
 
 	if(spellBeingCasted)
@@ -1255,17 +1018,14 @@ void CAdventureMapInterface::enterCastingMode(const CSpell * sp)
 	Settings config = settings.write["session"]["showSpellRange"];
 	config->Bool() = true;
 
-	deactivate();
-	terrain->activate();
-	GH.fakeMouseMove();
+	widget->setState(EGameState::CASTING_SPELL);
 }
 
 void CAdventureMapInterface::exitCastingMode()
 {
 	assert(spellBeingCasted);
 	spellBeingCasted = nullptr;
-	terrain->deactivate();
-	activate();
+	widget->setState(EGameState::MAKING_TURN);
 
 	Settings config = settings.write["session"]["showSpellRange"];
 	config->Bool() = false;
@@ -1286,7 +1046,7 @@ void CAdventureMapInterface::leaveCastingMode(const int3 & dest)
 
 Rect CAdventureMapInterface::terrainAreaPixels() const
 {
-	return terrain->pos;
+	return widget->getMapView()->pos;
 }
 
 const IShipyard * CAdventureMapInterface::ourInaccessibleShipyard(const CGObjectInstance *obj) const
@@ -1303,35 +1063,14 @@ const IShipyard * CAdventureMapInterface::ourInaccessibleShipyard(const CGObject
 
 void CAdventureMapInterface::exitWorldView()
 {
-	state = EGameState::MAKING_TURN;
-
-	panelMain->activate();
-	panelWorldView->deactivate();
-	activeMapPanel = panelMain;
-
-	townList->activate();
-	heroList->activate();
-	infoBar->activate();
-
-	redraw();
-	terrain->onViewMapActivated();
+	widget->setState(EGameState::MAKING_TURN);
+	widget->getMapView()->onViewMapActivated();
 }
 
 void CAdventureMapInterface::openWorldView(int tileSize)
 {
-	state = EGameState::WORLD_VIEW;
-	panelMain->deactivate();
-	panelWorldView->activate();
-
-	activeMapPanel = panelWorldView;
-
-	townList->deactivate();
-	heroList->deactivate();
-	infoBar->showSelection(); // to prevent new day animation interfering world view mode
-	infoBar->deactivate();
-
-	redraw();
-	terrain->onViewWorldActivated(tileSize);
+	widget->setState(EGameState::WORLD_VIEW);
+	widget->getMapView()->onViewWorldActivated(tileSize);
 }
 
 void CAdventureMapInterface::openWorldView()
@@ -1342,5 +1081,5 @@ void CAdventureMapInterface::openWorldView()
 void CAdventureMapInterface::openWorldView(const std::vector<ObjectPosInfo>& objectPositions, bool showTerrain)
 {
 	openWorldView(11);
-	terrain->onViewSpellActivated(11, objectPositions, showTerrain);
+	widget->getMapView()->onViewSpellActivated(11, objectPositions, showTerrain);
 }

+ 3 - 42
client/adventureMap/CAdventureMapInterface.h

@@ -1,5 +1,5 @@
 /*
- * CAdvMapInt.h, part of VCMI engine
+ * CAdventureMapInterface.h, part of VCMI engine
  *
  * Authors: listed in file AUTHORS in main folder
  *
@@ -29,6 +29,7 @@ class CButton;
 class IImage;
 class CAnimImage;
 class CGStatusBar;
+class CAdventureMapWidget;
 class CAdvMapPanel;
 class CAdvMapWorldViewPanel;
 class CAnimation;
@@ -48,17 +49,6 @@ struct MapDrawingInfo;
 class CAdventureMapInterface : public CIntObject
 {
 private:
-	enum class EGameState
-	{
-		NOT_INITIALIZED,
-		HOTSEAT_WAIT,
-		MAKING_TURN,
-		ENEMY_TURN,
-		WORLD_VIEW
-	};
-
-	EGameState state;
-
 	/// currently acting player
 	PlayerColor currentPlayerID;
 
@@ -67,37 +57,8 @@ private:
 
 	const CSpell *spellBeingCasted; //nullptr if none
 
-	std::vector<std::shared_ptr<CAnimImage>> gems;
-
-	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> 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<MapView> 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
-	std::shared_ptr<CAdvMapPanel> activeMapPanel; // currently active panel (either main or world view, depending on current mode)
-
-	std::shared_ptr<CAnimation> worldViewIcons;// images for world view overlay
-
 	std::shared_ptr<MapAudioPlayer> mapAudio;
+	std::shared_ptr<CAdventureMapWidget> widget;
 
 private:
 	//functions bound to buttons

+ 390 - 0
client/adventureMap/CAdventureMapWidget.cpp

@@ -0,0 +1,390 @@
+/*
+ * CAdventureMapWidget.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#include "StdInc.h"
+#include "CAdventureMapWidget.h"
+
+#include "CInfoBar.h"
+#include "CList.h"
+#include "CMinimap.h"
+#include "CResDataBar.h"
+
+#include "../gui/CGuiHandler.h"
+#include "../mapView/MapView.h"
+#include "../render/CAnimation.h"
+#include "../render/IImage.h"
+#include "../widgets/Buttons.h"
+#include "../widgets/Images.h"
+#include "../widgets/TextControls.h"
+
+#include "../CPlayerInterface.h"
+#include "../PlayerLocalState.h"
+
+#include "../../lib/StringConstants.h"
+#include "../../lib/filesystem/ResourceID.h"
+
+CAdventureMapWidget::CAdventureMapWidget()
+	: state(EGameState::NOT_INITIALIZED)
+{
+	pos.w = 800;
+	pos.h = 600;
+	REGISTER_BUILDER("adventureInfobar",         &CAdventureMapWidget::buildInfobox         );
+	REGISTER_BUILDER("adventureMapImage",        &CAdventureMapWidget::buildMapImage        );
+	REGISTER_BUILDER("adventureMapButton",       &CAdventureMapWidget::buildMapButton       );
+	REGISTER_BUILDER("adventureMapContainer",    &CAdventureMapWidget::buildMapContainer    );
+	REGISTER_BUILDER("adventureMapGameArea",     &CAdventureMapWidget::buildMapGameArea     );
+	REGISTER_BUILDER("adventureMapHeroList",     &CAdventureMapWidget::buildMapHeroList     );
+	REGISTER_BUILDER("adventureMapIcon",         &CAdventureMapWidget::buildMapIcon         );
+	REGISTER_BUILDER("adventureMapTownList",     &CAdventureMapWidget::buildMapTownList     );
+	REGISTER_BUILDER("adventureMinimap",         &CAdventureMapWidget::buildMinimap         );
+	REGISTER_BUILDER("adventureResourceDateBar", &CAdventureMapWidget::buildResourceDateBar );
+	REGISTER_BUILDER("adventureStatusBar",       &CAdventureMapWidget::buildStatusBar       );
+
+	const JsonNode config(ResourceID("config/widgets/adventureMap.json"));
+
+	for(const auto & entry : config["options"]["imagesPlayerColored"].Vector())
+	{
+		ResourceID resourceName(entry.String(), EResType::IMAGE);
+		playerColorerImages.push_back(resourceName.getName());
+	}
+
+	build(config);
+}
+
+Rect CAdventureMapWidget::readSourceArea(const JsonNode & source, const JsonNode & sourceCommon)
+{
+	const auto & input = source.isNull() ? sourceCommon : source;
+
+	return readArea(input, Rect(Point(0, 0), Point(800, 600)));
+}
+
+Rect CAdventureMapWidget::readTargetArea(const JsonNode & source)
+{
+	if(subwidgetSizes.empty())
+		return readArea(source, pos);
+	return readArea(source, subwidgetSizes.back());
+}
+
+Rect CAdventureMapWidget::readArea(const JsonNode & source, const Rect & boundingBox)
+{
+	const auto & object = source.Struct();
+
+	if(object.count("left") + object.count("width") + object.count("right") != 2)
+		logGlobal->error("Invalid area definition in widget! Unable to load width!");
+
+	if(object.count("top") + object.count("height") + object.count("bottom") != 2)
+		logGlobal->error("Invalid area definition in widget! Unable to load height!");
+
+	int left = source["left"].Integer();
+	int width = source["width"].Integer();
+	int right = source["right"].Integer();
+
+	int top = source["top"].Integer();
+	int height = source["height"].Integer();
+	int bottom = source["bottom"].Integer();
+
+	Point topLeft(left, top);
+	Point dimensions(width, height);
+
+	if(source["left"].isNull())
+		topLeft.x = boundingBox.w - right - width;
+
+	if(source["width"].isNull())
+		dimensions.x = boundingBox.w - right - left;
+
+	if(source["top"].isNull())
+		topLeft.y = boundingBox.h - bottom - height;
+
+	if(source["height"].isNull())
+		dimensions.y = boundingBox.h - bottom - top;
+
+	return Rect(topLeft + boundingBox.topLeft(), dimensions);
+}
+
+std::shared_ptr<IImage> CAdventureMapWidget::loadImage(const std::string & name)
+{
+	ResourceID resource(name, EResType::IMAGE);
+
+	if(images.count(resource.getName()) == 0)
+		images[resource.getName()] = IImage::createFromFile(resource.getName());
+	;
+
+	return images[resource.getName()];
+}
+
+std::shared_ptr<CAnimation> CAdventureMapWidget::loadAnimation(const std::string & name)
+{
+	ResourceID resource(name, EResType::ANIMATION);
+
+	if(animations.count(resource.getName()) == 0)
+		animations[resource.getName()] = std::make_shared<CAnimation>(resource.getName());
+
+	return animations[resource.getName()];
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildInfobox(const JsonNode & input)
+{
+	Rect area = readTargetArea(input["area"]);
+	return std::make_shared<CInfoBar>(area);
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildMapImage(const JsonNode & input)
+{
+	Rect targetArea = readTargetArea(input["area"]);
+	Rect sourceArea = readSourceArea(input["sourceArea"], input["area"]);
+	std::string image = input["image"].String();
+
+	return std::make_shared<CFilledTexture>(loadImage(image), targetArea, sourceArea);
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildMapButton(const JsonNode & input)
+{
+	auto position = readTargetArea(input["area"]);
+	auto image = input["image"].String();
+	auto help = readHintText(input["help"]);
+	return std::make_shared<CButton>(position.topLeft(), image, help);
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildMapContainer(const JsonNode & input)
+{
+	auto position = readTargetArea(input["area"]);
+	auto result = std::make_shared<CAdventureMapContainerWidget>();
+
+	result->moveBy(position.topLeft());
+	subwidgetSizes.push_back(position);
+	for(const auto & entry : input["items"].Vector())
+	{
+		result->ownedChildren.push_back(buildWidget(entry));
+		result->addChild(result->ownedChildren.back().get(), true);
+	}
+	subwidgetSizes.pop_back();
+
+	return result;
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildMapGameArea(const JsonNode & input)
+{
+	Rect area = readTargetArea(input["area"]);
+	return std::make_shared<MapView>(area.topLeft(), area.dimensions());
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildMapHeroList(const JsonNode & input)
+{
+	Rect area = readTargetArea(input["area"]);
+	Rect item = readTargetArea(input["item"]);
+
+	Point itemOffset(input["itemsOffset"]["x"].Integer(), input["itemsOffset"]["y"].Integer());
+	int itemsCount = input["itemsCount"].Integer();
+
+	auto result = std::make_shared<CHeroList>(itemsCount, area.topLeft() + item.topLeft(), itemOffset, LOCPLINT->localState->getWanderingHeroes().size());
+
+	subwidgetSizes.push_back(area);
+
+	if(!input["scrollUp"].isNull())
+		result->setScrollUpButton(std::dynamic_pointer_cast<CButton>(buildMapButton(input["scrollUp"])));
+
+	if(!input["scrollDown"].isNull())
+		result->setScrollDownButton(std::dynamic_pointer_cast<CButton>(buildMapButton(input["scrollDown"])));
+
+	subwidgetSizes.pop_back();
+
+	return result;
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildMapIcon(const JsonNode & input)
+{
+	Rect area = readTargetArea(input["area"]);
+	size_t index = input["index"].Integer();
+	size_t perPlayer = input["perPlayer"].Integer();
+	std::string image = input["image"].String();
+
+	return std::make_shared<CAdventureMapIcon>(area.topLeft(), loadAnimation(image), index, perPlayer);
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildMapTownList(const JsonNode & input)
+{
+	Rect area = readTargetArea(input["area"]);
+	Rect item = readTargetArea(input["item"]);
+
+	Point itemOffset(input["itemsOffset"]["x"].Integer(), input["itemsOffset"]["y"].Integer());
+	int itemsCount = input["itemsCount"].Integer();
+
+	auto result = std::make_shared<CTownList>(itemsCount, area.topLeft() + item.topLeft(), itemOffset, LOCPLINT->localState->getOwnedTowns().size());
+
+	subwidgetSizes.push_back(area);
+
+	if(!input["scrollUp"].isNull())
+		result->setScrollUpButton(std::dynamic_pointer_cast<CButton>(buildMapButton(input["scrollUp"])));
+
+	if(!input["scrollDown"].isNull())
+		result->setScrollDownButton(std::dynamic_pointer_cast<CButton>(buildMapButton(input["scrollDown"])));
+
+	subwidgetSizes.pop_back();
+
+	return result;
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildMinimap(const JsonNode & input)
+{
+	Rect area = readTargetArea(input["area"]);
+	return std::make_shared<CMinimap>(area);
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildResourceDateBar(const JsonNode & input)
+{
+	Rect area = readTargetArea(input["area"]);
+	std::string image = input["image"].String();
+
+	auto result = std::make_shared<CResDataBar>(image, area.topLeft());
+
+	for(auto i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
+	{
+		const auto & node = input[GameConstants::RESOURCE_NAMES[i]];
+
+		if(node.isNull())
+			continue;
+
+		result->setResourcePosition(GameResID(i), Point(node["x"].Integer(), node["y"].Integer()));
+	}
+
+	result->setDatePosition(Point(input["date"]["x"].Integer(), input["date"]["y"].Integer()));
+
+	return result;
+}
+
+std::shared_ptr<CIntObject> CAdventureMapWidget::buildStatusBar(const JsonNode & input)
+{
+	Rect area = readTargetArea(input["area"]);
+	std::string image = input["image"].String();
+
+	auto background = std::make_shared<CFilledTexture>(image, area);
+
+	return CGStatusBar::create(background);
+}
+
+std::shared_ptr<CHeroList> CAdventureMapWidget::getHeroList()
+{
+	return widget<CHeroList>("heroList");
+}
+
+std::shared_ptr<CTownList> CAdventureMapWidget::getTownList()
+{
+	return widget<CTownList>("townList");
+}
+
+std::shared_ptr<CMinimap> CAdventureMapWidget::getMinimap()
+{
+	return widget<CMinimap>("minimap");
+}
+
+std::shared_ptr<MapView> CAdventureMapWidget::getMapView()
+{
+	return widget<MapView>("mapView");
+}
+
+std::shared_ptr<CInfoBar> CAdventureMapWidget::getInfoBar()
+{
+	return widget<CInfoBar>("infoBar");
+}
+
+void CAdventureMapWidget::setPlayer(const PlayerColor & player)
+{
+	setPlayerChildren(this, player);
+}
+
+void CAdventureMapWidget::setPlayerChildren(CIntObject * widget, const PlayerColor & player)
+{
+	for(auto & entry : widget->children)
+	{
+		auto container = dynamic_cast<CAdventureMapContainerWidget *>(entry);
+		auto icon = dynamic_cast<CAdventureMapIcon *>(entry);
+		auto button = dynamic_cast<CButton *>(entry);
+
+		if(button)
+			button->setPlayerColor(player);
+
+		if(icon)
+			icon->setPlayer(player);
+
+		if(container)
+			setPlayerChildren(container, player);
+	}
+
+	for(const auto & entry : playerColorerImages)
+	{
+		if(images.count(entry))
+			images[entry]->playerColored(player);
+	}
+
+	redraw();
+}
+
+void CAdventureMapWidget::setState(EGameState newState)
+{
+	state = newState;
+
+	if(newState == EGameState::WORLD_VIEW)
+		widget<CIntObject>("worldViewContainer")->enable();
+	else
+		widget<CIntObject>("worldViewContainer")->disable();
+}
+
+EGameState CAdventureMapWidget::getState()
+{
+	return state;
+}
+
+void CAdventureMapWidget::setOptionHasQuests(bool on)
+{
+
+}
+
+void CAdventureMapWidget::setOptionHasUnderground(bool on)
+{
+
+}
+
+void CAdventureMapWidget::setOptionUndergroundLevel(bool on)
+{
+
+}
+
+void CAdventureMapWidget::setOptionHeroSleeping(bool on)
+{
+
+}
+
+void CAdventureMapWidget::setOptionHeroSelected(bool on)
+{
+
+}
+
+void CAdventureMapWidget::setOptionHeroCanMove(bool on)
+{
+
+}
+
+void CAdventureMapWidget::setOptionHasNextHero(bool on)
+{
+
+}
+
+CAdventureMapIcon::CAdventureMapIcon(const Point & position, std::shared_ptr<CAnimation> animation, size_t index, size_t iconsPerPlayer)
+	: index(index)
+	, iconsPerPlayer(iconsPerPlayer)
+{
+	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
+	pos += position;
+	image = std::make_shared<CAnimImage>(animation, index);
+}
+
+void CAdventureMapIcon::setPlayer(const PlayerColor & player)
+{
+	image->setFrame(index + player.getNum() * iconsPerPlayer);
+}

+ 105 - 0
client/adventureMap/CAdventureMapWidget.h

@@ -0,0 +1,105 @@
+/*
+ * CAdventureMapWidget.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "../gui/InterfaceObjectConfigurable.h"
+
+class CHeroList;
+class CTownList;
+class CMinimap;
+class MapView;
+class CInfoBar;
+class IImage;
+
+enum class EGameState
+{
+	NOT_INITIALIZED,
+	HOTSEAT_WAIT,
+	MAKING_TURN,
+	ENEMY_TURN,
+	CASTING_SPELL,
+	WORLD_VIEW
+};
+
+/// Internal class of AdventureMapInterface that contains actual UI elements
+class CAdventureMapWidget : public InterfaceObjectConfigurable
+{
+	EGameState state;
+	/// temporary stack of sizes of currently building widgets
+	std::vector<Rect> subwidgetSizes;
+
+	/// list of images on which player-colored palette will be applied
+	std::vector<std::string> playerColorerImages;
+
+	/// list of named images shared between widgets
+	std::map<std::string, std::shared_ptr<IImage>> images;
+	std::map<std::string, std::shared_ptr<CAnimation>> animations;
+
+	Rect readTargetArea(const JsonNode & source);
+	Rect readSourceArea(const JsonNode & source, const JsonNode & sourceCommon);
+	Rect readArea(const JsonNode & source, const Rect & boundingBox);
+
+	std::shared_ptr<IImage> loadImage(const std::string & name);
+	std::shared_ptr<CAnimation> loadAnimation(const std::string & name);
+
+	std::shared_ptr<CIntObject> buildInfobox(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildMapImage(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildMapButton(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildMapContainer(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildMapGameArea(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildMapHeroList(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildMapIcon(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildMapTownList(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildMinimap(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildResourceDateBar(const JsonNode & input);
+	std::shared_ptr<CIntObject> buildStatusBar(const JsonNode & input);
+
+	void setPlayerChildren(CIntObject * widget, const PlayerColor & player);
+public:
+	CAdventureMapWidget();
+
+	std::shared_ptr<CHeroList> getHeroList();
+	std::shared_ptr<CTownList> getTownList();
+	std::shared_ptr<CMinimap> getMinimap();
+	std::shared_ptr<MapView> getMapView();
+	std::shared_ptr<CInfoBar> getInfoBar();
+
+	void setPlayer(const PlayerColor & player);
+	void setState(EGameState newState);
+	EGameState getState();
+
+	void setOptionHasQuests(bool on);
+	void setOptionHasUnderground(bool on);
+	void setOptionUndergroundLevel(bool on);
+	void setOptionHeroSleeping(bool on);
+	void setOptionHeroSelected(bool on);
+	void setOptionHeroCanMove(bool on);
+	void setOptionHasNextHero(bool on);
+};
+
+/// Small helper class that provides ownership for shared_ptr's of child elements
+class CAdventureMapContainerWidget : public CIntObject
+{
+	friend class CAdventureMapWidget;
+	std::vector<std::shared_ptr<CIntObject>> ownedChildren;
+};
+
+/// Small helper class that provides player-colorable icon using animation file
+class CAdventureMapIcon : public CIntObject
+{
+	std::shared_ptr<CAnimImage> image;
+
+	size_t index;
+	size_t iconsPerPlayer;
+public:
+	CAdventureMapIcon(const Point & position, std::shared_ptr<CAnimation> image, size_t index, size_t iconsPerPlayer);
+
+	void setPlayer(const PlayerColor & player);
+};

+ 1 - 1
client/adventureMap/CInGameConsole.cpp

@@ -83,7 +83,7 @@ void CInGameConsole::print(const std::string & txt)
 	// boost::unique_lock scope
 	{
 		boost::unique_lock<boost::mutex> lock(texts_mx);
-		int lineLen = conf.go()->ac.outputLineLength;
+		int lineLen = 60; //FIXME: CONFIGURABLE ADVMAP
 
 		if(txt.size() < lineLen)
 		{

+ 31 - 17
client/adventureMap/CList.cpp

@@ -81,24 +81,33 @@ void CList::CListItem::onSelect(bool on)
 	redraw();
 }
 
-CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create)
+CList::CList(int Size, Point position)
 	: CIntObject(0, position),
 	size(Size),
 	selected(nullptr)
 {
-	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
-	scrollUp = std::make_shared<CButton>(Point(0, 0), btnUp, CGI->generaltexth->zelp[helpUp]);
-	scrollDown = std::make_shared<CButton>(Point(0, scrollUp->pos.h + 32*(int)size), btnDown, CGI->generaltexth->zelp[helpDown]);
 
-	listBox = std::make_shared<CListBox>(create, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount);
+}
 
-	//assign callback only after list was created
-	scrollUp->addCallback(std::bind(&CListBox::moveToPrev, listBox));
-	scrollDown->addCallback(std::bind(&CListBox::moveToNext, listBox));
+void CList::createList(Point itemOffset, size_t listAmount)
+{
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	listBox = std::make_shared<CListBox>(std::bind(&CList::createItem, this, _1), Point(0, 0), itemOffset, size, listAmount);
+}
 
+void CList::setScrollUpButton(std::shared_ptr<CButton> button)
+{
+	scrollUp = button;
+	scrollUp->addCallback(std::bind(&CListBox::moveToPrev, listBox));
 	scrollUp->addCallback(std::bind(&CList::update, this));
-	scrollDown->addCallback(std::bind(&CList::update, this));
+	update();
+}
 
+void CList::setScrollDownButton(std::shared_ptr<CButton> button)
+{
+	scrollDown = button;
+	scrollDown->addCallback(std::bind(&CList::update, this));
+	scrollDown->addCallback(std::bind(&CListBox::moveToNext, listBox));
 	update();
 }
 
@@ -107,8 +116,11 @@ void CList::update()
 	bool onTop = listBox->getPos() == 0;
 	bool onBottom = listBox->getPos() + size >= listBox->size();
 
-	scrollUp->block(onTop);
-	scrollDown->block(onBottom);
+	if (scrollUp)
+		scrollUp->block(onTop);
+
+	if (scrollDown)
+		scrollDown->block(onBottom);
 }
 
 void CList::select(std::shared_ptr<CListItem> which)
@@ -223,16 +235,17 @@ std::string CHeroList::CHeroItem::getHoverText()
 	return boost::str(boost::format(CGI->generaltexth->allTexts[15]) % hero->getNameTranslated() % hero->type->heroClass->getNameTranslated());
 }
 
-std::shared_ptr<CIntObject> CHeroList::createHeroItem(size_t index)
+std::shared_ptr<CIntObject> CHeroList::createItem(size_t index)
 {
 	if (LOCPLINT->localState->getWanderingHeroes().size() > index)
 		return std::make_shared<CHeroItem>(this, LOCPLINT->localState->getWanderingHero(index));
 	return std::make_shared<CEmptyHeroItem>();
 }
 
-CHeroList::CHeroList(int size, Point position, std::string btnUp, std::string btnDown):
-	CList(size, position, btnUp, btnDown, LOCPLINT->localState->getWanderingHeroes().size(), 303, 304, std::bind(&CHeroList::createHeroItem, this, _1))
+CHeroList::CHeroList(int size, Point position, Point itemOffset, size_t listAmount)
+	: CList(size, position)
 {
+	createList(itemOffset, listAmount);
 }
 
 void CHeroList::select(const CGHeroInstance * hero)
@@ -261,7 +274,7 @@ void CHeroList::update(const CGHeroInstance * hero)
 	CList::update();
 }
 
-std::shared_ptr<CIntObject> CTownList::createTownItem(size_t index)
+std::shared_ptr<CIntObject> CTownList::createItem(size_t index)
 {
 	if (LOCPLINT->localState->getOwnedTowns().size() > index)
 		return std::make_shared<CTownItem>(this, LOCPLINT->localState->getOwnedTown(index));
@@ -312,9 +325,10 @@ std::string CTownList::CTownItem::getHoverText()
 	return town->getObjectName();
 }
 
-CTownList::CTownList(int size, Point position, std::string btnUp, std::string btnDown):
-	CList(size, position, btnUp, btnDown, LOCPLINT->localState->getOwnedTowns().size(),  306, 307, std::bind(&CTownList::createTownItem, this, _1))
+CTownList::CTownList(int size, Point position, Point itemOffset, size_t listAmount)
+	: CList(size, position)
 {
+	createList(itemOffset, listAmount);
 }
 
 void CTownList::select(const CGTownInstance * town)

+ 19 - 29
client/adventureMap/CList.h

@@ -53,23 +53,9 @@ protected:
 		virtual std::string getHoverText()=0;
 	};
 
-	std::shared_ptr<CListBox> listBox;
+private:
 	const size_t size;
 
-	/**
-	 * @brief CList - protected constructor
-	 * @param size - maximal amount of visible at once items
-	 * @param position - cordinates
-	 * @param btnUp - path to image to use as top button
-	 * @param btnDown - path to image to use as bottom button
-	 * @param listAmount - amount of items in the list
-	 * @param helpUp - index in zelp.txt for button help tooltip
-	 * @param helpDown - index in zelp.txt for button help tooltip
-	 * @param create - function for creating items in listbox
-	 * @param destroy - function for deleting items in listbox
-	 */
-	CList(int size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create);
-
 	//for selection\deselection
 	std::shared_ptr<CListItem> selected;
 	void select(std::shared_ptr<CListItem> which);
@@ -78,8 +64,14 @@ protected:
 	std::shared_ptr<CButton> scrollUp;
 	std::shared_ptr<CButton> scrollDown;
 
-	/// should be called when list is invalidated
-	void update();
+protected:
+	std::shared_ptr<CListBox> listBox;
+
+	CList(int size, Point position);
+
+	void createList(Point itemOffset, size_t listAmount);
+
+	virtual std::shared_ptr<CIntObject> createItem(size_t index) = 0;
 
 public:
 	/// functions that will be called when selection changes
@@ -88,6 +80,12 @@ public:
 	/// return index of currently selected element
 	int getSelectedIndex();
 
+	void setScrollUpButton(std::shared_ptr<CButton> button);
+	void setScrollDownButton(std::shared_ptr<CButton> button);
+
+	/// should be called when list is invalidated
+	void update();
+
 	/// set of methods to switch selection
 	void selectIndex(int which);
 	void selectNext();
@@ -125,13 +123,9 @@ class CHeroList	: public CList
 		std::string getHoverText() override;
 	};
 
-	std::shared_ptr<CIntObject> createHeroItem(size_t index);
+	std::shared_ptr<CIntObject> createItem(size_t index);
 public:
-	/**
-	 * @brief CHeroList
-	 * @param size, position, btnUp, btnDown @see CList::CList
-	 */
-	CHeroList(int size, Point position, std::string btnUp, std::string btnDown);
+	CHeroList(int size, Point position, Point itemOffset, size_t listAmount);
 
 	/// Select specific hero and scroll if needed
 	void select(const CGHeroInstance * hero = nullptr);
@@ -159,13 +153,9 @@ class CTownList	: public CList
 		std::string getHoverText() override;
 	};
 
-	std::shared_ptr<CIntObject> createTownItem(size_t index);
+	std::shared_ptr<CIntObject> createItem(size_t index) override;
 public:
-	/**
-	 * @brief CTownList
-	 * @param size, position, btnUp, btnDown @see CList::CList
-	 */
-	CTownList(int size, Point position, std::string btnUp, std::string btnDown);
+	CTownList(int size, Point position, Point itemOffset, size_t listAmount);
 
 	/// Select specific town and scroll if needed
 	void select(const CGTownInstance * town = nullptr);

+ 25 - 33
client/adventureMap/CResDataBar.cpp

@@ -19,50 +19,40 @@
 #include "../../CCallback.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/CGeneralTextHandler.h"
+#include "../../lib/ResourceSet.h"
 
-#define ADVOPT (conf.go()->ac)
-
-CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist)
+CResDataBar::CResDataBar(const std::string & imageName, const Point & position)
 {
-	pos.x += x;
-	pos.y += y;
+	pos.x += position.x;
+	pos.y += position.y;
+
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
-	background = std::make_shared<CPicture>(defname, 0, 0);
+	background = std::make_shared<CPicture>(imageName, 0, 0);
 	background->colorize(LOCPLINT->playerID);
 
 	pos.w = background->pos.w;
 	pos.h = background->pos.h;
 
-	txtpos.resize(8);
-	for (int i = 0; i < 8 ; i++)
-	{
-		txtpos[i].first = pos.x + offx + resdist*i;
-		txtpos[i].second = pos.y + offy;
-	}
-	txtpos[7].first = txtpos[6].first + datedist;
 	addUsedEvents(RCLICK);
 }
 
-CResDataBar::CResDataBar()
+CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist):
+	CResDataBar(defname, Point(x,y))
 {
-	pos.x += ADVOPT.resdatabarX;
-	pos.y += ADVOPT.resdatabarY;
+	for (int i = 0; i < 7 ; i++)
+		resourcePositions[GameResID(i)] = Point( offx + resdist*i, offy );
 
-	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
-	background = std::make_shared<CPicture>(ADVOPT.resdatabarG, 0, 0);
-	background->colorize(LOCPLINT->playerID);
-
-	pos.w = background->pos.w;
-	pos.h = background->pos.h;
+	datePosition = resourcePositions[EGameResID::GOLD] + Point(datedist, 0);
+}
 
-	txtpos.resize(8);
-	for (int i = 0; i < 8 ; i++)
-	{
-		txtpos[i].first = pos.x + ADVOPT.resOffsetX + ADVOPT.resDist*i;
-		txtpos[i].second = pos.y + ADVOPT.resOffsetY;
-	}
-	txtpos[7].first = txtpos[6].first + ADVOPT.resDateDist;
+void CResDataBar::setDatePosition(const Point & position)
+{
+	datePosition = position;
+}
 
+void CResDataBar::setResourcePosition(const GameResID & resource, const Point & position)
+{
+	resourcePositions[resource] = position;
 }
 
 std::string CResDataBar::buildDateString()
@@ -80,13 +70,15 @@ std::string CResDataBar::buildDateString()
 void CResDataBar::draw(SDL_Surface * to)
 {
 	//TODO: all this should be labels, but they require proper text update on change
-	for (GameResID i=EGameResID::WOOD; i <= GameResID(EGameResID::GOLD); ++i)
+	for (auto & entry : resourcePositions)
 	{
-		std::string text = std::to_string(LOCPLINT->cb->getResourceAmount(i));
+		std::string text = std::to_string(LOCPLINT->cb->getResourceAmount(entry.first));
 
-		graphics->fonts[FONT_SMALL]->renderTextLeft(to, text, Colors::WHITE, Point(txtpos[i].first, txtpos[i].second));
+		graphics->fonts[FONT_SMALL]->renderTextLeft(to, text, Colors::WHITE, pos.topLeft() + entry.second);
 	}
-	graphics->fonts[FONT_SMALL]->renderTextLeft(to, buildDateString(), Colors::WHITE, Point(txtpos[7].first, txtpos[7].second));
+
+	if (datePosition)
+		graphics->fonts[FONT_SMALL]->renderTextLeft(to, buildDateString(), Colors::WHITE, pos.topLeft() + *datePosition);
 }
 
 void CResDataBar::showAll(SDL_Surface * to)

+ 13 - 3
client/adventureMap/CResDataBar.h

@@ -11,6 +11,9 @@
 
 #include "../gui/CIntObject.h"
 
+enum class EGameResID : int8_t;
+using GameResID = Identifier<EGameResID>;
+
 /// Resources bar which shows information about how many gold, crystals,... you have
 /// Current date is displayed too
 class CResDataBar : public CIntObject
@@ -19,14 +22,21 @@ class CResDataBar : public CIntObject
 
 	std::shared_ptr<CPicture> background;
 
-	std::vector<std::pair<int,int> > txtpos;
-
+	std::map<GameResID, Point> resourcePositions;
+	std::optional<Point> datePosition;
 
 	void draw(SDL_Surface * to);
 public:
-	CResDataBar();
+
+	/// For dynamically-sized UI windows, e.g. adventure map interface
+	CResDataBar(const std::string & imageName, const Point & position);
+
+	/// For fixed-size UI windows, e.g. CastleInterface
 	CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist);
 
+	void setDatePosition(const Point & position);
+	void setResourcePosition(const GameResID & resource, const Point & position);
+
 	void colorize(PlayerColor player);
 	void showAll(SDL_Surface * to) override;
 };

+ 2 - 0
client/gui/InterfaceObjectConfigurable.cpp

@@ -174,6 +174,8 @@ EFonts InterfaceObjectConfigurable::readFont(const JsonNode & config) const
 			return EFonts::FONT_SMALL;
 		if(config.String() == "tiny")
 			return EFonts::FONT_TINY;
+		if(config.String() == "calisto")
+			return EFonts::FONT_CALLI;
 	}
 	logGlobal->debug("Uknown font attribute");
 	return EFonts::FONT_TIMES;

+ 0 - 6
client/widgets/Buttons.h

@@ -16,13 +16,7 @@
 #include <SDL_pixels.h>
 
 VCMI_LIB_NAMESPACE_BEGIN
-
-namespace config
-{
-struct ButtonInfo;
-}
 class Rect;
-
 VCMI_LIB_NAMESPACE_END
 
 struct SDL_Surface;

+ 11 - 1
client/widgets/Images.cpp

@@ -109,6 +109,16 @@ void CPicture::colorize(PlayerColor player)
 CFilledTexture::CFilledTexture(std::string imageName, Rect position):
     CIntObject(0, position.topLeft()),
 	texture(IImage::createFromFile(imageName))
+{
+	pos.w = position.w;
+	pos.h = position.h;
+	imageArea = Rect(Point(), texture->dimensions());
+}
+
+CFilledTexture::CFilledTexture(std::shared_ptr<IImage> image, Rect position, Rect imageArea)
+	: CIntObject(0, position.topLeft())
+	, texture(image)
+	, imageArea(imageArea)
 {
 	pos.w = position.w;
 	pos.h = position.h;
@@ -121,7 +131,7 @@ void CFilledTexture::showAll(SDL_Surface *to)
 	for (int y=pos.top(); y < pos.bottom(); y+= texture->height())
 	{
 		for (int x=pos.left(); x < pos.right(); x+=texture->width())
-			texture->draw(to, x, y);
+			texture->draw(to, x, y, &imageArea);
 	}
 }
 

+ 2 - 0
client/widgets/Images.h

@@ -69,9 +69,11 @@ public:
 class CFilledTexture : public CIntObject
 {
 	std::shared_ptr<IImage> texture;
+	Rect imageArea;
 
 public:
 	CFilledTexture(std::string imageName, Rect position);
+	CFilledTexture(std::shared_ptr<IImage> image, Rect position, Rect imageArea);
 
 	void showAll(SDL_Surface *to) override;
 };

+ 4 - 3
client/widgets/TextControls.cpp

@@ -399,7 +399,7 @@ void CGStatusBar::clear()
 	write({});
 }
 
-CGStatusBar::CGStatusBar(std::shared_ptr<CPicture> background_, EFonts Font, ETextAlignment Align, const SDL_Color & Color)
+CGStatusBar::CGStatusBar(std::shared_ptr<CIntObject> background_, EFonts Font, ETextAlignment Align, const SDL_Color & Color)
 	: CLabel(background_->pos.x, background_->pos.y, Font, Align, Color, "")
 	, enteringText(false)
 {
@@ -419,14 +419,15 @@ CGStatusBar::CGStatusBar(int x, int y, std::string name, int maxw)
 	addUsedEvents(LCLICK);
 
 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
-	background = std::make_shared<CPicture>(name);
+	auto backgroundImage = std::make_shared<CPicture>(name);
+	background = backgroundImage;
 	pos = background->pos;
 
 	if((unsigned)maxw < (unsigned)pos.w) //(insigned)-1 > than any correct value of pos.w
 	{
 		//execution of this block when maxw is incorrect breaks text centralization (issue #3151)
 		vstd::amin(pos.w, maxw);
-		background->srcRect = Rect(0, 0, maxw, pos.h);
+		backgroundImage->srcRect = Rect(0, 0, maxw, pos.h);
 	}
 	autoRedraw = false;
 }

+ 2 - 2
client/widgets/TextControls.h

@@ -45,7 +45,7 @@ protected:
 	Point getBorderSize() override;
 	virtual std::string visibleText();
 
-	std::shared_ptr<CPicture> background;
+	std::shared_ptr<CIntObject> background;
 	std::string text;
 	bool autoRedraw;  //whether control will redraw itself on setTxt
 
@@ -127,7 +127,7 @@ class CGStatusBar : public CLabel, public std::enable_shared_from_this<CGStatusB
 
 	void init();
 
-	CGStatusBar(std::shared_ptr<CPicture> background_, EFonts Font = FONT_SMALL, ETextAlignment Align = ETextAlignment::CENTER, const SDL_Color & Color = Colors::WHITE);
+	CGStatusBar(std::shared_ptr<CIntObject> background_, EFonts Font = FONT_SMALL, ETextAlignment Align = ETextAlignment::CENTER, const SDL_Color & Color = Colors::WHITE);
 	CGStatusBar(int x, int y, std::string name, int maxw = -1);
 
 	//make CLabel API private

+ 4 - 1
client/windows/CCastleInterface.cpp

@@ -1200,7 +1200,10 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
 	statusbar = CGStatusBar::create(statusbarBackground);
 	resdatabar = std::make_shared<CResDataBar>("ARESBAR", 3, 575, 32, 2, 85, 85);
 
-	townlist = std::make_shared<CTownList>(3, Point(744, 414), "IAM014", "IAM015");
+	townlist = std::make_shared<CTownList>(3, Point(745, 430), Point(0, 32), LOCPLINT->localState->getOwnedTowns().size() );
+	townlist->setScrollUpButton( std::make_shared<CButton>( Point(744, 414), "IAM014", CButton::tooltipLocalized("core.help.306")));
+	townlist->setScrollDownButton( std::make_shared<CButton>( Point(744, 526), "IAM015", CButton::tooltipLocalized("core.help.307")));
+
 	if(from)
 		townlist->select(from);
 

+ 13 - 10
client/windows/CKingdomInterface.cpp

@@ -39,6 +39,9 @@
 #include "../../lib/mapObjects/CGTownInstance.h"
 #include "../../lib/mapObjects/MiscObjects.h"
 
+static const std::string OVERVIEW_BACKGROUND = "OvCast.pcx";
+static const size_t OVERVIEW_SIZE = 4;
+
 InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr<IInfoBoxData> Data):
 	size(Size),
 	infoPos(Pos),
@@ -468,10 +471,10 @@ void InfoBoxCustom::prepareMessage(std::string & text, std::shared_ptr<CComponen
 }
 
 CKingdomInterface::CKingdomInterface()
-	: CWindowObject(PLAYER_COLORED | BORDERED, conf.go()->ac.overviewBg)
+	: CWindowObject(PLAYER_COLORED | BORDERED, OVERVIEW_BACKGROUND)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
-	ui32 footerPos = conf.go()->ac.overviewSize * 116;
+	ui32 footerPos = OVERVIEW_SIZE * 116;
 
 	tabArea = std::make_shared<CTabbedInt>(std::bind(&CKingdomInterface::createMainTab, this, _1), Point(4,4));
 
@@ -486,7 +489,7 @@ CKingdomInterface::CKingdomInterface()
 
 void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInstance * > &ownedObjects)
 {
-	ui32 footerPos = conf.go()->ac.overviewSize * 116;
+	ui32 footerPos = OVERVIEW_SIZE * 116;
 	size_t dwellSize = (footerPos - 64)/57;
 
 	//Map used to determine image number for several objects
@@ -550,7 +553,7 @@ std::shared_ptr<CIntObject> CKingdomInterface::createOwnedObject(size_t index)
 
 std::shared_ptr<CIntObject> CKingdomInterface::createMainTab(size_t index)
 {
-	size_t size = conf.go()->ac.overviewSize;
+	size_t size = OVERVIEW_SIZE;
 	switch(index)
 	{
 	case 0:
@@ -564,7 +567,7 @@ std::shared_ptr<CIntObject> CKingdomInterface::createMainTab(size_t index)
 
 void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstance *> & ownedObjects)
 {
-	ui32 footerPos = conf.go()->ac.overviewSize * 116;
+	ui32 footerPos = OVERVIEW_SIZE * 116;
 	TResources minesCount(GameConstants::RESOURCE_QUANTITY, 0);
 	int totalIncome=0;
 
@@ -610,7 +613,7 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
 
 void CKingdomInterface::generateButtons()
 {
-	ui32 footerPos = conf.go()->ac.overviewSize * 116;
+	ui32 footerPos = OVERVIEW_SIZE * 116;
 
 	//Main control buttons
 	btnHeroes = std::make_shared<CButton>(Point(748, 28+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->overview[11], CGI->generaltexth->overview[6]),
@@ -689,7 +692,7 @@ CKingdHeroList::CKingdHeroList(size_t maxSize)
 	skillsLabel = std::make_shared<CLabel>(500, 10, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->overview[1]);
 
 	ui32 townCount = LOCPLINT->cb->howManyHeroes(false);
-	ui32 size = conf.go()->ac.overviewSize*116 + 19;
+	ui32 size = OVERVIEW_SIZE*116 + 19;
 	heroes = std::make_shared<CListBox>(std::bind(&CKingdHeroList::createHeroItem, this, _1),
 		Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size));
 }
@@ -705,7 +708,7 @@ void CKingdHeroList::updateGarrisons()
 
 std::shared_ptr<CIntObject> CKingdHeroList::createHeroItem(size_t index)
 {
-	ui32 picCount = conf.go()->ac.overviewPics;
+	ui32 picCount = 4; // OVSLOT contains 4 images
 	size_t heroesCount = LOCPLINT->cb->howManyHeroes(false);
 
 	if(index < heroesCount)
@@ -730,7 +733,7 @@ CKingdTownList::CKingdTownList(size_t maxSize)
 	visitHeroLabel = std::make_shared<CLabel>(608, 10, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->overview[5]);
 
 	ui32 townCount = LOCPLINT->cb->howManyTowns();
-	ui32 size = conf.go()->ac.overviewSize*116 + 19;
+	ui32 size = OVERVIEW_SIZE*116 + 19;
 	towns = std::make_shared<CListBox>(std::bind(&CKingdTownList::createTownItem, this, _1),
 		Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size));
 }
@@ -756,7 +759,7 @@ void CKingdTownList::updateGarrisons()
 
 std::shared_ptr<CIntObject> CKingdTownList::createTownItem(size_t index)
 {
-	ui32 picCount = conf.go()->ac.overviewPics;
+	ui32 picCount = 4; // OVSLOT contains 4 images
 	size_t townsCount = LOCPLINT->cb->howManyTowns();
 
 	if(index < townsCount)

+ 6 - 3
client/windows/settings/GeneralOptionsTab.cpp

@@ -243,10 +243,13 @@ void GeneralOptionsTab::fillSelectableResolutions()
 {
 	selectableResolutions.clear();
 
-	for(const auto & it : conf.guiOptions)
-	{
-		const Point dimensions(it.first.first, it.first.second);
+	// TODO: CONFIGURABLE ADVMAP
+	static const std::vector<Point> supportedResolutions = {
+		{ 800, 600 }
+	};
 
+	for(const auto & dimensions : supportedResolutions)
+	{
 		if(isResolutionSupported(dimensions))
 			selectableResolutions.push_back(dimensions);
 	}

+ 0 - 33
config/resolutions.json

@@ -1,33 +0,0 @@
-{
-	"GUISettings":
-	[
-		{
-			"resolution": { "x": 800, "y": 600 },
-			"InGameConsole": { "maxInputPerLine": 60, "maxOutputPerLine": 60 },
-			"AdvMap": { "x": 7, "y": 7, "width": 594, "height": 546, "smoothMove": 1, "puzzleSepia": 1, "objectFading" : 1, "screenFading" : 1 },
-			"InfoBox": { "x": 605, "y": 389 },
-			"gem0": { "x": 6, "y": 508, "graphic": "agemLL.def" },
-			"gem1": { "x": 556, "y": 508, "graphic": "agemLR.def" },
-			"gem2": { "x": 6, "y": 6, "graphic": "agemUL.def" },
-			"gem3": { "x": 556, "y": 6, "graphic": "agemUR.def" },
-			"background": "AdvMap.bmp",
-			"backgroundWorldView": "VWorld.bmp",
-			"HeroList": { "size": 5, "x": 609, "y": 196, "movePoints": "IMOBIL.DEF", "manaPoints": "IMANA.DEF", "arrowUp": "IAM012.DEF", "arrowDown": "IAM013.DEF" },
-			"TownList": { "size": 5, "x": 747, "y": 196, "arrowUp": "IAM014.DEF", "arrowDown": "IAM015.DEF" },
-			"Minimap": { "width": 144, "height": 144, "x": 630, "y": 26 },
-			"Overview": { "pics": 4, "size": 4, "graphic": "OvCast.pcx" },
-			"Statusbar": { "x": 7, "y": 556, "graphic": "AdRollvr.bmp" },
-			"ResDataBar": { "x": 3, "y": 575, "graphic": "ARESBAR.bmp", "offsetX": 32, "offsetY": 2, "resSpace": 85, "resDateSpace": 85 },
-			"ButtonKingdomOv": { "x": 679, "y": 196, "graphic": "IAM002.DEF", "playerColoured": 1 },
-			"ButtonUnderground": { "x": 711, "y": 196, "graphic": "IAM010.DEF", "playerColoured": 1, "additionalDefs": [ "IAM003.DEF" ] },
-			"ButtonQuestLog": { "x": 679, "y": 228, "graphic": "IAM004.DEF", "playerColoured": 1 },
-			"ButtonSleepWake": { "x": 711, "y": 228, "graphic": "IAM005.DEF", "playerColoured": 1, "additionalDefs":["IAM011.DEF"] },
-			"ButtonMoveHero": { "x": 679, "y": 260, "graphic": "IAM006.DEF", "playerColoured": 1 },
-			"ButtonSpellbook": { "x": 711, "y": 260, "graphic": "IAM007.DEF", "playerColoured": 1 },
-			"ButtonAdvOptions": { "x": 679, "y": 292, "graphic": "IAM008.DEF", "playerColoured": 1 },
-			"ButtonSysOptions": { "x": 711, "y": 292, "graphic": "IAM009.DEF", "playerColoured": 1 },
-			"ButtonNextHero": { "x": 679, "y": 324, "graphic": "IAM000.DEF", "playerColoured": 1 },
-			"ButtonEndTurn": { "x": 679, "y": 356, "graphic": "IAM001.DEF", "playerColoured": 1 }
-		}
-	]
-}

+ 612 - 0
config/widgets/adventureMap.json

@@ -0,0 +1,612 @@
+{
+	"options" : {
+
+		// player-colored images used for background
+		"imagesPlayerColored" : [ "AdvMap.pcx" ],
+
+		// widgets that are only visible in world view mode
+		"worldViewWidgets" : [ "worldViewContainer" ],
+		
+		// widgets that are only visible in game view mode
+		"gameViewWidgets" : [ "townListContainer", "heroListContainer", "buttonsContainer", "infobox" ],
+		
+		// widgets that should be drawn on top of game area
+		// NOTE: semi-transparency is not supported, only fully transparent/fully opaque
+		"overlayWidgets" : [ "gemTopLeft", "gemTopRight", "gemBottomLeft", "gemBottomRight" ]
+	},
+
+	"items":
+	[
+		// GEMS - set of images with different image for each player
+		{
+			"type": "adventureMapIcon",
+			"name" : "gemTopLeft",
+			"image" : "agemUL.def",
+			"index" : 0,
+			"perPlayer" : 1,
+			"area" : { "left": 7, "top" : 7, "width" : 46, "height" : 46 }
+		},
+		{
+			"type": "adventureMapIcon",
+			"name" : "gemTopRight",
+			"image" : "agemUR.def",
+			"index" : 0,
+			"perPlayer" : 1,
+			"area" : { "right": 198, "top" : 7, "width" : 46, "height" : 46 }
+		},
+		{
+			"type": "adventureMapIcon",
+			"name" : "gemBottomLeft",
+			"image" : "agemLL.def",
+			"index" : 0,
+			"perPlayer" : 1,
+			"area" : { "left": 7, "bottom" : 46, "width" : 46, "height" : 46 }
+		},
+		{
+			"type": "adventureMapIcon",
+			"name" : "gemBottomRight",
+			"image" : "agemLR.def",
+			"index" : 0,
+			"perPlayer" : 1,
+			"area" : { "right": 198, "bottom" : 46, "width" : 46, "height" : 46 }
+		},
+
+		// Background sections
+		{
+			"type": "adventureMapImage",
+			"name" : "backgroundTopLeft",
+			"image" : "AdvMap.pcx",
+			"area" : { "left": 0, "top" : 0, "width" : 7, "height" : 7 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name" : "backgroundBottomLeft",
+			"image" : "AdvMap.pcx",
+			"area" : { "left": 0, "bottom" : 0, "width" : 7, "height" : 46 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name" : "backgroundTopRight",
+			"image" : "AdvMap.pcx",
+			"area" : { "right": 0, "top" : 0, "width" : 199, "height" : 196 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name" : "backgroundBottomRight",
+			"image" : "AdvMap.pcx",
+			"area" : { "bottom": 0, "right" : 0, "width" : 199, "height" : 211 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name": "sideBorderLeft",
+			"image" : "AdvMap.pcx",
+			"area": { "top": 7, "left" : 0, "bottom" : 46, "width" : 7 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name": "sideBorderTop",
+			"image" : "AdvMap.pcx",
+			"area": { "top": 0, "left" : 7, "right" : 199, "height" : 7 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name": "sideBorderBottom",
+			"image" : "AdvMap.pcx",
+			"area": { "bottom": 0, "right" : 199, "left" : 0, "height" : 47 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name": "heroListBorderLeft",
+			"image" : "AdvMap.pcx",
+			"area": { "top": 196, "bottom" : 210, "right" : 192, "width" : 7 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name": "heroListBorderRight",
+			"image" : "AdvMap.pcx",
+			"area": { "top": 196, "bottom" : 210, "right" : 122, "width" : 3 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name": "townListBorderLeft",
+			"image" : "AdvMap.pcx",
+			"area": { "top": 196, "bottom" : 210, "right" : 54, "width" : 3 }
+		},
+		{
+			"type": "adventureMapImage",
+			"name": "townListBorderRight",
+			"image" : "AdvMap.pcx",
+			"area": { "top": 196, "bottom" : 210, "right" : 0, "width" : 3 }
+		},
+		
+		// Game area
+		{
+			"type": "adventureMapGameArea",
+			"name": "mapView",
+			"area": { "top": 7, "bottom" : 47, "left" : 7, "right" : 199 }
+		},
+		
+		// Minimap
+		{
+			"type": "adventureMinimap",
+			"name": "minimap",
+			"area": { "top": 26, "right" : 26, "width" : 144, "height" : 144 }
+		},
+
+		// Adventure map buttons
+		{
+			"type": "adventureMapContainer",
+			"name" : "buttonsContainer",
+			"area": { "top": 196, "right" : 57, "width" : 64, "height" : 192 },
+			"items" : [
+				{
+					"type" : "adventureMapButton",
+					"name" : "buttonKingdomOverview",
+					"image" : "IAM002.DEF",
+					"help" : "core.help.293",
+					"area": { "top" : 0, "left": 0, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonUnderground",
+					"image" : "IAM010.DEF",
+					"help" : "core.help.294",
+					"area": { "top" : 0, "left": 32, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonSurface",
+					"image" : "IAM003.DEF",
+					"help" : "core.help.294",
+					"area": { "top" : 0, "left": 32, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonQuestLog",
+					"image" : "IAM004.DEF",
+					"help" : "core.help.295",
+					"area": { "top" : 32, "left": 0, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonSleep",
+					"image" : "IAM005.DEF",
+					"help" : "core.help.296",
+					"area": { "top" : 32, "left": 32, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonWake",
+					"image" : "IAM011.DEF",
+					"help" : "core.help.296",
+					"area": { "top" : 32, "left": 32, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonMove",
+					"image" : "IAM006.DEF",
+					"help" : "core.help.297",
+					"area": { "top" : 64, "left": 0, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonCast",
+					"image" : "IAM007.DEF",
+					"help" : "core.help.298",
+					"area": { "top" : 64, "left": 32, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonAdventureOptions",
+					"image" : "IAM008.DEF",
+					"help" : "core.help.299",
+					"area": { "top" : 96, "left": 0, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonSystemOptions",
+					"image" : "IAM009.DEF",
+					"help" : "core.help.300",
+					"area": { "top" : 96, "left": 32, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonNextHero",
+					"image" : "IAM000.DEF",
+					"help" : "core.help.301",
+					"area": { "top" : 128, "left": 0, "width" : 64, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "buttonEndTurn",
+					"image" : "IAM001.DEF",
+					"help" : "core.help.302",
+					"area": { "top" : 160, "left": 0, "width" : 64, "height" : 32 }
+				}
+			]
+		},
+		// Hero List
+		{
+			"type": "adventureMapHeroList",
+			"name" : "heroList",
+			"area": { "top": 196, "right" : 127, "width" : 64, "height" : 192 },
+			"scrollUp" : {
+				"type": "adventureMapButton",
+				"name": "heroListScrollUp",
+				"image" : "IAM012.DEF",
+				"help" : "core.help.303",
+				"area": { "top" : 0, "left": 0, "width" : 64, "height" : 16 }
+			},
+			"scrollDown" : {
+				"type": "adventureMapButton",
+				"name": "heroListScrollDown",
+				"image" : "IAM013.DEF",
+				"help" : "core.help.304",
+				"area": { "top" : 176, "left": 0, "width" : 64, "height" : 16 }
+			},
+			"item" : { "top" :  16, "left": 1, "width" : 62, "height" : 32 },
+			"itemsOffset" : { "x" : 0, "y" : 32 },
+			"itemsCount" : 5
+		},
+		
+		// Town List
+		{
+			"type": "adventureMapTownList",
+			"name" : "townList",
+			"area": { "top": 196, "right" : 5, "width" : 48, "height" : 192 },
+			"scrollUp" : {
+				"type": "adventureMapButton",
+				"name": "townListScrollUp",
+				"image" : "IAM014.DEF",
+				"help" : "core.help.306",
+				"area": { "top" : 0, "left": 0, "width" : 48, "height" : 16 }
+			},
+			"scrollDown" : {
+				"type": "adventureMapButton",
+				"name": "townListScrollDown",
+				"image" : "IAM015.DEF",
+				"help" : "core.help.307",
+				"area": { "top" : 176, "left": 0, "width" : 48, "height" : 16 }
+			},
+			"item" : { "top" :  16, "left": 0, "width" : 48, "height" : 32 },
+			"itemsOffset" : { "x" : 0, "y" : 32 },
+			"itemsCount" : 5
+		},
+		
+		// Infobar
+		{
+			"type": "adventureInfobar",
+			"name": "infoBar",
+			"area": { "bottom": 44, "right" : 19, "width" : 175, "height" : 168 }
+		},
+		// Status bar
+		{
+			"type": "adventureStatusBar",
+			"name": "statusBar",
+			"image" : "DiBoxBck.pcx",
+			"area": { "left": 8, "bottom" : 26, "right" : 199, "height" : 18 }
+		},
+		// Resource & Data bar
+		{
+			"type": "adventureResourceDateBar",
+			"name": "resourceDataBar",
+			"image" : "AResBar.pcx",
+			"area": { "bottom" : 3, "right" : 3, "height" : 22, "width" : 794 },
+			
+			"wood"    : { "x" :  36, "y" : 2 },
+			"mercury" : { "x" : 120, "y" : 2 },
+			"ore"     : { "x" : 204, "y" : 2 },
+			"sulfur"  : { "x" : 288, "y" : 2 },
+			"crystal" : { "x" : 372, "y" : 2 },
+			"gems"    : { "x" : 456, "y" : 2 },
+			"gold"    : { "x" : 540, "y" : 2 },
+			"date"    : { "x" : 615, "y" : 2 }
+		},
+		// World view mode widgets
+		{
+			"type": "adventureMapContainer",
+			"name" : "worldViewContainer",
+			"area": { "top": 195, "right" : 4, "width" : 190, "height" : 381 },
+			"items" : [
+				{
+					"type": "adventureMapImage",
+					"name": "worldViewBackground",
+					"image" : "VWorld.pcx",
+					"area": { "top" : 0, "left": 0, "width" : 48, "height" : 192 },
+					"areaSource": { "left" : 0, "right" : 0, "top" : 0, "bottom" : 0 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "worldViewZoom1",
+					"image" : "VWMAG1.DEF",
+					"area": { "top" : 23, "left": 1, "width" : 60, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "worldViewZoom2",
+					"image" : "VWMAG2.DEF",
+					"area": { "top" : 23, "left": 64, "width" : 60, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "worldViewZoom4",
+					"image" : "VWMAG4.DEF",
+					"area": { "top" : 23, "left": 1, "width" : 60, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "worldViewSurface",
+					"image" : "IAM003.DEF",
+					"area": { "top" : 79, "left": 343, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "worldViewPuzzle",
+					"image" : "VWPUZ.DEF",
+					"area": { "top" : 343, "left": 5, "width" : 66, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "worldViewUnderground",
+					"image" : "IAM010.DEF",
+					"area": { "top" : 343, "left": 79, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapButton",
+					"name": "worldViewExit",
+					"image" : "IOK6432.DEF",
+					"area": { "top" : 343, "left": 117, "width" : 66, "height" : 32 }
+				},
+				// World view - objects icons
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconTown",
+					"image" : "VwSymbol.def",
+					"index" : 0,
+					"perPlayer" : 19,
+					"area": { "top" : 66, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconHero",
+					"image" : "VwSymbol.def",
+					"index" : 1,
+					"perPlayer" : 19,
+					"area": { "top" : 86, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconArtifact",
+					"image" : "VwSymbol.def",
+					"index" : 2,
+					"perPlayer" : 19,
+					"area": { "top" : 106, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconTeleporter",
+					"image" : "VwSymbol.def",
+					"index" : 3,
+					"perPlayer" : 19,
+					"area": { "top" : 126, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconGate",
+					"image" : "VwSymbol.def",
+					"index" : 4,
+					"perPlayer" : 19,
+					"area": { "top" : 146, "left": 12, "width" : 32, "height" : 32 }
+				},
+				
+				// World view - mines icons
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineWood",
+					"image" : "VwSymbol.def",
+					"index" : 5,
+					"perPlayer" : 19,
+					"area": { "top" : 190, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineMercury",
+					"image" : "VwSymbol.def",
+					"index" : 6,
+					"perPlayer" : 19,
+					"area": { "top" : 210, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconOre",
+					"image" : "VwSymbol.def",
+					"index" : 7,
+					"perPlayer" : 19,
+					"area": { "top" : 230, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineSulfur",
+					"image" : "VwSymbol.def",
+					"index" : 8,
+					"perPlayer" : 19,
+					"area": { "top" : 250, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineCrystal",
+					"image" : "VwSymbol.def",
+					"index" : 9,
+					"perPlayer" : 19,
+					"area": { "top" : 270, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineGems",
+					"image" : "VwSymbol.def",
+					"index" : 10,
+					"perPlayer" : 19,
+					"area": { "top" : 290, "left": 12, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineGold",
+					"image" : "VwSymbol.def",
+					"index" : 11,
+					"perPlayer" : 19,
+					"area": { "top" : 310, "left": 12, "width" : 32, "height" : 32 }
+				},
+				
+				// World view - resources icons
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineWood",
+					"image" : "VwSymbol.def",
+					"index" : 12,
+					"perPlayer" : 19,
+					"area": { "top" : 190, "left": 160, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineMercury",
+					"image" : "VwSymbol.def",
+					"index" : 13,
+					"perPlayer" : 19,
+					"area": { "top" : 210, "left": 160, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconOre",
+					"image" : "VwSymbol.def",
+					"index" : 14,
+					"perPlayer" : 19,
+					"area": { "top" : 230, "left": 160, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineSulfur",
+					"image" : "VwSymbol.def",
+					"index" : 15,
+					"perPlayer" : 19,
+					"area": { "top" : 250, "left": 160, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineCrystal",
+					"image" : "VwSymbol.def",
+					"index" : 16,
+					"perPlayer" : 19,
+					"area": { "top" : 270, "left": 160, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineGems",
+					"image" : "VwSymbol.def",
+					"index" : 17,
+					"perPlayer" : 19,
+					"area": { "top" : 290, "left": 160, "width" : 32, "height" : 32 }
+				},
+				{
+					"type": "adventureMapIcon",
+					"name": "worldViewIconMineGold",
+					"image" : "VwSymbol.def",
+					"index" : 18,
+					"perPlayer" : 19,
+					"area": { "top" : 310, "left": 160, "width" : 32, "height" : 32 }
+				},
+
+				{
+					"name": "worldViewLabelTitle",
+					"type": "label",
+					"font": "big",
+					"alignment": "center",
+					"color": "yellow",
+					"position": {"x": 100, "y": 10},
+					"text": "core.genrltxt.611"
+				},
+				{
+					"name": "worldViewLabelMine",
+					"type": "label",
+					"font": "calisto",
+					"alignment": "center",
+					"color": "yellow",
+					"position": {"x": 10, "y": 175},
+					"text": "core.genrltxt.617"
+				},
+				{
+					"name": "worldViewLabelResource",
+					"type": "label",
+					"font": "calisto",
+					"alignment": "center",
+					"color": "yellow",
+					"position": {"x": 185, "y": 185},
+					"text": "core.genrltxt.618"
+				},
+				{
+					"name": "worldViewLabelsObjects",
+					"type": "labelGroup",
+					"font": "calisto",
+					"alignment": "left",
+					"color": "white",
+					"items":
+					[
+						{
+							"position": {"x": 45, "y": 70},
+							"text": "core.genrltxt.612"
+						},
+						{
+							"position": {"x": 45, "y": 90},
+							"text": "core.genrltxt.613"
+						},
+						{
+							"position": {"x": 45, "y": 110},
+							"text": "core.genrltxt.614"
+						},
+						{
+							"position": {"x": 45, "y": 130},
+							"text": "core.genrltxt.615"
+						},
+						{
+							"position": {"x": 45, "y": 150},
+							"text": "core.genrltxt.616"
+						}
+					]
+				},
+				{
+					"name": "worldViewLabelsResources",
+					"type": "labelGroup",
+					"font": "calisto",
+					"alignment": "center",
+					"color": "white",
+					"items":
+					[
+						{
+							"position": {"x": 100, "y": 200},
+							"text": "core.genrltxt.619"
+						},
+						{
+							"position": {"x": 100, "y": 220},
+							"text": "core.genrltxt.620"
+						},
+						{
+							"position": {"x": 100, "y": 240},
+							"text": "core.genrltxt.621"
+						},
+						{
+							"position": {"x": 100, "y": 260},
+							"text": "core.genrltxt.622"
+						},
+						{
+							"position": {"x": 100, "y": 280},
+							"text": "core.genrltxt.623"
+						},
+						{
+							"position": {"x": 100, "y": 300},
+							"text": "core.genrltxt.624"
+						}
+					]
+				},
+			]
+		}
+	]
+}

+ 0 - 120
lib/CConfigHandler.cpp

@@ -17,10 +17,7 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-using namespace config;
-
 SettingsStorage settings;
-CConfigHandler conf;
 
 template<typename Accessor>
 SettingsStorage::NodeAccessor<Accessor>::NodeAccessor(SettingsStorage & _parent, std::vector<std::string> _path):
@@ -178,123 +175,6 @@ JsonNode & Settings::operator[](const std::string & value)
 {
 	return node[value];
 }
-//
-// template DLL_LINKAGE struct SettingsStorage::NodeAccessor<SettingsListener>;
-// template DLL_LINKAGE struct SettingsStorage::NodeAccessor<Settings>;
-
-static void setButton(ButtonInfo &button, const JsonNode &g)
-{
-	button.x = static_cast<int>(g["x"].Float());
-	button.y = static_cast<int>(g["y"].Float());
-	button.playerColoured = g["playerColoured"].Float();
-	button.defName = g["graphic"].String();
-
-	if (!g["additionalDefs"].isNull()) {
-		const JsonVector &defs_vec = g["additionalDefs"].Vector();
-
-		for(const JsonNode &def : defs_vec) {
-			button.additionalDefs.push_back(def.String());
-		}
-	}
-}
-
-static void setGem(AdventureMapConfig &ac, const int gem, const JsonNode &g)
-{
-	ac.gemX[gem] = static_cast<int>(g["x"].Float());
-	ac.gemY[gem] = static_cast<int>(g["y"].Float());
-	ac.gemG.push_back(g["graphic"].String());
-}
-
-CConfigHandler::CConfigHandler()
-	: current(nullptr)
-{
-}
-
-void config::CConfigHandler::init()
-{
-	/* Read resolutions. */
-	const JsonNode config(ResourceID("config/resolutions.json"));
-	const JsonVector &guisettings_vec = config["GUISettings"].Vector();
-
-	for(const JsonNode &g : guisettings_vec)
-	{
-		std::pair<int, int> curRes(static_cast<int>(g["resolution"]["x"].Float()), static_cast<int>(g["resolution"]["y"].Float()));
-		GUIOptions *current = &conf.guiOptions[curRes];
-
-		current->ac.inputLineLength =  static_cast<int>(g["InGameConsole"]["maxInputPerLine"].Float());
-		current->ac.outputLineLength = static_cast<int>(g["InGameConsole"]["maxOutputPerLine"].Float());
-
-		current->ac.advmapX = static_cast<int>(g["AdvMap"]["x"].Float());
-		current->ac.advmapY = static_cast<int>(g["AdvMap"]["y"].Float());
-		current->ac.advmapW = static_cast<int>(g["AdvMap"]["width"].Float());
-		current->ac.advmapH = static_cast<int>(g["AdvMap"]["height"].Float());
-		current->ac.smoothMove = g["AdvMap"]["smoothMove"].Float();
-		current->ac.puzzleSepia = g["AdvMap"]["puzzleSepia"].Float();
-		current->ac.screenFading = g["AdvMap"]["screenFading"].isNull() ? true : g["AdvMap"]["screenFading"].Float(); // enabled by default
-		current->ac.objectFading = g["AdvMap"]["objectFading"].isNull() ? true : g["AdvMap"]["objectFading"].Float();
-
-		current->ac.infoboxX = static_cast<int>(g["InfoBox"]["x"].Float());
-		current->ac.infoboxY = static_cast<int>(g["InfoBox"]["y"].Float());
-
-		setGem(current->ac, 0, g["gem0"]);
-		setGem(current->ac, 1, g["gem1"]);
-		setGem(current->ac, 2, g["gem2"]);
-		setGem(current->ac, 3, g["gem3"]);
-
-		current->ac.mainGraphic = g["background"].String();
-		current->ac.worldViewGraphic = g["backgroundWorldView"].String();
-
-		current->ac.hlistX =    static_cast<int>(g["HeroList"]["x"].Float());
-		current->ac.hlistY =    static_cast<int>(g["HeroList"]["y"].Float());
-		current->ac.hlistSize = static_cast<int>(g["HeroList"]["size"].Float());
-		current->ac.hlistMB = g["HeroList"]["movePoints"].String();
-		current->ac.hlistMN = g["HeroList"]["manaPoints"].String();
-		current->ac.hlistAU = g["HeroList"]["arrowUp"].String();
-		current->ac.hlistAD = g["HeroList"]["arrowDown"].String();
-
-		current->ac.tlistX =    static_cast<int>(g["TownList"]["x"].Float());
-		current->ac.tlistY =    static_cast<int>(g["TownList"]["y"].Float());
-		current->ac.tlistSize = static_cast<int>(g["TownList"]["size"].Float());
-		current->ac.tlistAU = g["TownList"]["arrowUp"].String();
-		current->ac.tlistAD = g["TownList"]["arrowDown"].String();
-
-		current->ac.minimapW = static_cast<int>(g["Minimap"]["width"].Float());
-		current->ac.minimapH = static_cast<int>(g["Minimap"]["height"].Float());
-		current->ac.minimapX = static_cast<int>(g["Minimap"]["x"].Float());
-		current->ac.minimapY = static_cast<int>(g["Minimap"]["y"].Float());
-
-		current->ac.overviewPics = static_cast<int>(g["Overview"]["pics"].Float());
-		current->ac.overviewSize = static_cast<int>(g["Overview"]["size"].Float());
-		current->ac.overviewBg = g["Overview"]["graphic"].String();
-
-		current->ac.statusbarX = static_cast<int>(g["Statusbar"]["x"].Float());
-		current->ac.statusbarY = static_cast<int>(g["Statusbar"]["y"].Float());
-		current->ac.statusbarG = g["Statusbar"]["graphic"].String();
-
-		current->ac.resdatabarX = static_cast<int>(g["ResDataBar"]["x"].Float());
-		current->ac.resdatabarY = static_cast<int>(g["ResDataBar"]["y"].Float());
-		current->ac.resOffsetX =  static_cast<int>(g["ResDataBar"]["offsetX"].Float());
-		current->ac.resOffsetY =  static_cast<int>(g["ResDataBar"]["offsetY"].Float());
-		current->ac.resDist =     static_cast<int>(g["ResDataBar"]["resSpace"].Float());
-		current->ac.resDateDist = static_cast<int>(g["ResDataBar"]["resDateSpace"].Float());
-		current->ac.resdatabarG = g["ResDataBar"]["graphic"].String();
-
-		setButton(current->ac.kingOverview, g["ButtonKingdomOv"]);
-		setButton(current->ac.underground, g["ButtonUnderground"]);
-		setButton(current->ac.questlog, g["ButtonQuestLog"]);
-		setButton(current->ac.sleepWake, g["ButtonSleepWake"]);
-		setButton(current->ac.moveHero, g["ButtonMoveHero"]);
-		setButton(current->ac.spellbook, g["ButtonSpellbook"]);
-		setButton(current->ac.advOptions, g["ButtonAdvOptions"]);
-		setButton(current->ac.sysOptions, g["ButtonSysOptions"]);
-		setButton(current->ac.nextHero, g["ButtonNextHero"]);
-		setButton(current->ac.endTurn, g["ButtonEndTurn"]);
-	}
-
-	const JsonNode& screenRes = settings["video"]["screenRes"];
-
-	SetResolution(static_cast<int>(screenRes["width"].Float()), static_cast<int>(screenRes["height"].Float()));
-}
 
 // Force instantiation of the SettingsStorage::NodeAccessor class template.
 // That way method definitions can sit in the cpp file

+ 0 - 77
lib/CConfigHandler.h

@@ -112,83 +112,6 @@ public:
 	friend class SettingsStorage;
 };
 
-namespace config
-{
-	struct DLL_LINKAGE ButtonInfo
-	{
-		std::string defName;
-		std::vector<std::string> additionalDefs;
-		int x, y; //position on the screen
-		bool playerColoured; //if true button will be colored to main player's color (works properly only for appropriate 8bpp graphics)
-	};
-	/// Struct which holds data about position of several GUI elements at the adventure map screen
-	struct DLL_LINKAGE AdventureMapConfig
-	{
-		//minimap properties
-		int minimapX, minimapY, minimapW, minimapH;
-		//statusbar
-		int statusbarX, statusbarY; //pos
-		std::string statusbarG; //graphic name
-		//resdatabar
-		int resdatabarX, resdatabarY, resDist, resDateDist, resOffsetX, resOffsetY; //pos
-		std::string resdatabarG; //graphic name
-		//infobox
-		int infoboxX, infoboxY;
-		//advmap
-		int advmapX, advmapY, advmapW, advmapH;
-		bool smoothMove;
-		bool puzzleSepia;
-		bool screenFading;
-		bool objectFading;
-		//general properties
-		std::string mainGraphic;
-		std::string worldViewGraphic;
-		//buttons
-		ButtonInfo kingOverview, underground, questlog,	sleepWake, moveHero, spellbook,	advOptions,
-			sysOptions,	nextHero, endTurn;
-		//hero list
-		int hlistX, hlistY, hlistSize;
-		std::string hlistMB, hlistMN, hlistAU, hlistAD;
-		//town list
-		int tlistX, tlistY, tlistSize;
-		std::string tlistAU, tlistAD;
-		//gems
-		int gemX[4], gemY[4];
-		std::vector<std::string> gemG;
-		//in-game console
-		int inputLineLength, outputLineLength;
-		//kingdom overview
-		int overviewPics, overviewSize; //pic count in def and count of visible slots
-		std::string overviewBg; //background name
-	};
-	struct DLL_LINKAGE GUIOptions
-	{
-		AdventureMapConfig ac;
-	};
-	/// Handles adventure map screen settings
-	class DLL_LINKAGE CConfigHandler
-	{
-		GUIOptions *current; // pointer to current gui options
-
-	public:
-		using GuiOptionsMap = std::map<std::pair<int, int>, GUIOptions>;
-		GuiOptionsMap guiOptions;
-		void init();
-		CConfigHandler();
-
-		GUIOptions *go() { return current; };
-		void SetResolution(int x, int y)
-		{
-			std::pair<int,int> index(x, y);
-			if (guiOptions.count(index) == 0)
-				current = nullptr;
-			else
-				current = &guiOptions.at(index);
-		}
-	};
-}
-
 extern DLL_LINKAGE SettingsStorage settings;
-extern DLL_LINKAGE config::CConfigHandler conf;
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 3
mapeditor/mainwindow.cpp

@@ -191,9 +191,6 @@ MainWindow::MainWindow(QWidget* parent) :
 		QApplication::quit();
 	}
 
-	conf.init();
-	logGlobal->info("Loading settings");
-
 	loadTranslation();
 
 	ui->setupUi(this);