1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

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
This commit is contained in:
Ivan Savenko
2023-04-26 15:44:10 +03:00
parent cb8201876b
commit a015bf6507
28 changed files with 1335 additions and 884 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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"

View File

@@ -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));
}

View File

@@ -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);
};

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
};

View File

@@ -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)
{

View File

@@ -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)
{
}
void CList::createList(Point itemOffset, size_t listAmount)
{
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>(std::bind(&CList::createItem, this, _1), Point(0, 0), itemOffset, size, listAmount);
}
listBox = std::make_shared<CListBox>(create, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount);
//assign callback only after list was created
void CList::setScrollUpButton(std::shared_ptr<CButton> button)
{
scrollUp = button;
scrollUp->addCallback(std::bind(&CListBox::moveToPrev, listBox));
scrollDown->addCallback(std::bind(&CListBox::moveToNext, 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)

View File

@@ -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);

View File

@@ -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);
datePosition = resourcePositions[EGameResID::GOLD] + Point(datedist, 0);
}
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 + 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)

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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 }
}
]
}

View File

@@ -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"
}
]
},
]
}
]
}

View File

@@ -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

View File

@@ -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

View File

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