1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

Merge pull request #1571 from IvanSavenko/advmap_elements_refactoring

Advmap elements refactoring
This commit is contained in:
Ivan Savenko 2023-02-14 12:53:23 +02:00 committed by GitHub
commit 64ddd75cdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 852 additions and 818 deletions

View File

@ -13,6 +13,10 @@
#include "adventureMap/CAdvMapInt.h"
#include "adventureMap/mapHandler.h"
#include "adventureMap/CList.h"
#include "adventureMap/CTerrainRect.h"
#include "adventureMap/CInfoBar.h"
#include "adventureMap/CMinimap.h"
#include "battle/BattleInterface.h"
#include "battle/BattleEffectsController.h"
#include "battle/BattleFieldController.h"
@ -199,8 +203,7 @@ void CPlayerInterface::yourTurn()
autosaveCount %= 5;
}
if (adventureInt->player != playerID)
adventureInt->setPlayer(playerID);
adventureInt->setPlayer(playerID);
if (CSH->howManyPlayerInterfaces() > 1) //hot seat message
{
@ -251,10 +254,13 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
return;
}
adventureInt->minimap->updateTile(hero->convertToVisitablePos(details.start));
adventureInt->minimap->updateTile(hero->convertToVisitablePos(details.end));
bool directlyAttackingCreature =
details.attackedFrom
&& adventureInt->terrain.currentPath //in case if movement has been canceled in the meantime and path was already erased
&& adventureInt->terrain.currentPath->nodes.size() == 3;//FIXME should be 2 but works nevertheless...
&& adventureInt->terrain->currentPath //in case if movement has been canceled in the meantime and path was already erased
&& adventureInt->terrain->currentPath->nodes.size() == 3;//FIXME should be 2 but works nevertheless...
if(makingTurn && hero->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
{
@ -264,10 +270,10 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
if(details.result == TryMoveHero::TELEPORTATION)
{
if(adventureInt->terrain.currentPath)
if(adventureInt->terrain->currentPath)
{
assert(adventureInt->terrain.currentPath->nodes.size() >= 2);
std::vector<CGPathNode>::const_iterator nodesIt = adventureInt->terrain.currentPath->nodes.end() - 1;
assert(adventureInt->terrain->currentPath->nodes.size() >= 2);
std::vector<CGPathNode>::const_iterator nodesIt = adventureInt->terrain->currentPath->nodes.end() - 1;
if((nodesIt)->coord == hero->convertToVisitablePos(details.start)
&& (nodesIt - 1)->coord == hero->convertToVisitablePos(details.end))
@ -283,8 +289,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
}
}
adventureInt->centerOn(hero, true); //actualizing screen pos
adventureInt->minimap.redraw();
adventureInt->heroList.update(hero);
adventureInt->minimap->redraw();
adventureInt->heroList->update(hero);
return; //teleport - no fancy moving animation
//TODO: smooth disappear / appear effect
}
@ -294,7 +300,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
{
eraseCurrentPathOf(hero, false);
}
else if(adventureInt->terrain.currentPath && hero->pos == details.end) //&& hero is moving
else if(adventureInt->terrain->currentPath && hero->pos == details.end) //&& hero is moving
{
if(details.start != details.end) //so we don't touch path when revisiting with spacebar
removeLastNodeFromPath(hero);
@ -306,7 +312,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
hero->isStanding = true;
stillMoveHero.setn(STOP_MOVE);
GH.totalRedraw();
adventureInt->heroList.update(hero);
adventureInt->heroList->update(hero);
return;
}
@ -330,8 +336,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
}
adventureInt->centerOn(hero); //actualizing screen pos
adventureInt->minimap.redraw();
adventureInt->heroList.redraw();
adventureInt->minimap->redraw();
adventureInt->heroList->redraw();
initMovement(details, hero, hp);
@ -353,7 +359,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
#ifndef VCMI_ANDROID
// currently android doesn't seem to be able to handle all these full redraws here, so let's disable it so at least it looks less choppy;
// most likely this is connected with the way that this manual animation+framerate handling is solved
adventureInt->updateScreen = true;
adventureInt->requestRedrawMapOnNextFrame();
#endif
//evil returns here ...
@ -367,8 +373,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
hero->isStanding = true;
//move finished
adventureInt->minimap.redraw();
adventureInt->heroList.update(hero);
adventureInt->minimap->redraw();
adventureInt->heroList->update(hero);
//check if user cancelled movement
{
@ -431,7 +437,7 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
wanderingHeroes -= hero;
adventureInt->heroList.update(hero);
adventureInt->heroList->update(hero);
if (makingTurn && newSelection)
adventureInt->select(newSelection, true);
else if (adventureInt->selection == hero)
@ -455,7 +461,7 @@ void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
wanderingHeroes.push_back(hero);
adventureInt->heroList.update(hero);
adventureInt->heroList->update(hero);
}
void CPlayerInterface::openTownWindow(const CGTownInstance * town)
{
@ -474,10 +480,10 @@ int3 CPlayerInterface::repairScreenPos(int3 pos)
pos.x = -CGI->mh->frameW;
if (pos.y<-CGI->mh->frameH)
pos.y = -CGI->mh->frameH;
if (pos.x>CGI->mh->sizes.x - adventureInt->terrain.tilesw + CGI->mh->frameW)
pos.x = CGI->mh->sizes.x - adventureInt->terrain.tilesw + CGI->mh->frameW;
if (pos.y>CGI->mh->sizes.y - adventureInt->terrain.tilesh + CGI->mh->frameH)
pos.y = CGI->mh->sizes.y - adventureInt->terrain.tilesh + CGI->mh->frameH;
if (pos.x>CGI->mh->sizes.x - adventureInt->terrain->tilesw + CGI->mh->frameW)
pos.x = CGI->mh->sizes.x - adventureInt->terrain->tilesw + CGI->mh->frameW;
if (pos.y>CGI->mh->sizes.y - adventureInt->terrain->tilesh + CGI->mh->frameH)
pos.y = CGI->mh->sizes.y - adventureInt->terrain->tilesh + CGI->mh->frameH;
return pos;
}
@ -485,7 +491,7 @@ void CPlayerInterface::activateForSpectator()
{
adventureInt->state = CAdvMapInt::INGAME;
adventureInt->activate();
adventureInt->minimap.activate();
adventureInt->minimap->activate();
}
void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val)
@ -515,13 +521,13 @@ void CPlayerInterface::heroManaPointsChanged(const CGHeroInstance * hero)
EVENT_HANDLER_CALLED_BY_CLIENT;
updateInfo(hero);
if (makingTurn && hero->tempOwner == playerID)
adventureInt->heroList.update(hero);
adventureInt->heroList->update(hero);
}
void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
if (makingTurn && hero->tempOwner == playerID)
adventureInt->heroList.update(hero);
adventureInt->heroList->update(hero);
}
void CPlayerInterface::receivedResource()
{
@ -572,7 +578,7 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
if (town->visitingHero->tempOwner == playerID && !vstd::contains(wanderingHeroes,town->visitingHero)) // our hero
wanderingHeroes.push_back(town->visitingHero);
}
adventureInt->heroList.update();
adventureInt->heroList->update();
adventureInt->updateNextHero(nullptr);
if(castleInt)
@ -678,7 +684,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID build
}
}
}
adventureInt->townList.update(town);
adventureInt->townList->update(town);
}
void CPlayerInterface::battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
@ -1036,7 +1042,7 @@ void CPlayerInterface::showComp(const Component &comp, std::string message)
waitWhileDialog(); //Fix for mantis #98
CCS->soundh->playSoundFromSet(CCS->soundh->pickupSounds);
adventureInt->infoBar.showComponent(comp, message);
adventureInt->infoBar->showComponent(comp, message);
}
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<Component> & components, int soundID)
@ -1194,7 +1200,7 @@ void CPlayerInterface::tileRevealed(const std::unordered_set<int3, ShashInt3> &p
EVENT_HANDLER_CALLED_BY_CLIENT;
//FIXME: wait for dialog? Magi hut/eye would benefit from this but may break other areas
for (auto & po : pos)
adventureInt->minimap.showTile(po);
adventureInt->minimap->updateTile(po);
if (!pos.empty())
GH.totalRedraw();
}
@ -1203,7 +1209,7 @@ void CPlayerInterface::tileHidden(const std::unordered_set<int3, ShashInt3> &pos
{
EVENT_HANDLER_CALLED_BY_CLIENT;
for (auto & po : pos)
adventureInt->minimap.hideTile(po);
adventureInt->minimap->updateTile(po);
if (!pos.empty())
GH.totalRedraw();
}
@ -1332,7 +1338,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
EVENT_HANDLER_CALLED_BY_CLIENT;
auto onEnd = [=](){ cb->selectionMade(0, queryID); };
if (stillMoveHero.get() == DURING_MOVE && adventureInt->terrain.currentPath && adventureInt->terrain.currentPath->nodes.size() > 1) //to ignore calls on passing through garrisons
if (stillMoveHero.get() == DURING_MOVE && adventureInt->terrain->currentPath && adventureInt->terrain->currentPath->nodes.size() > 1) //to ignore calls on passing through garrisons
{
onEnd();
return;
@ -1409,7 +1415,7 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
for(auto & po : pos)
{
if(cb->isVisible(po))
adventureInt->minimap.showTile(po);
adventureInt->minimap->updateTile(po);
}
if(obj->ID == Obj::TOWN)
{
@ -1418,8 +1424,8 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
else
towns -= obj;
adventureInt->townList.update();
adventureInt->minimap.update();
adventureInt->townList->update();
adventureInt->minimap->update();
}
assert(cb->getTownsInfo().size() == towns.size());
}
@ -1524,6 +1530,12 @@ void CPlayerInterface::objectRemoved(const CGObjectInstance * obj)
}
}
void CPlayerInterface::objectRemovedAfter()
{
EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->minimap->update();
}
void CPlayerInterface::playerBlocked(int reason, bool start)
{
if(reason == PlayerBlocked::EReason::UPCOMING_BATTLE)
@ -1575,23 +1587,13 @@ void CPlayerInterface::update()
dialogs.pop_front();
}
//in some conditions we may receive calls before selection is initialized - we must ignore them
if(adventureInt && GH.topInt() == adventureInt
&& (!adventureInt->selection && !settings["session"]["spectate"].Bool()))
{
return;
}
assert(adventureInt);
assert(adventureInt->selection);
// Handles mouse and key input
GH.updateTime();
GH.handleEvents();
if (!adventureInt || adventureInt->isActive())
GH.simpleRedraw();
else if((adventureInt->swipeEnabled && adventureInt->swipeMovementRequested) || (adventureInt->scrollingDir && GH.isKeyboardCtrlDown()))
GH.totalRedraw(); //player forces map scrolling though interface is disabled
else
GH.simpleRedraw();
GH.simpleRedraw();
}
int CPlayerInterface::getLastIndex( std::string namePrefix)
@ -1712,8 +1714,8 @@ void CPlayerInterface::movementPxStep( const TryMoveHero &details, int i, const
}
}
adventureInt->terrain.moveX = (32 - i) * (heroImageNewX - heroImageOldX) / 32;
adventureInt->terrain.moveY = (32 - i) * (heroImageNewY - heroImageOldY) / 32;
adventureInt->terrain->moveX = (32 - i) * (heroImageNewX - heroImageOldX) / 32;
adventureInt->terrain->moveY = (32 - i) * (heroImageNewY - heroImageOldY) / 32;
}
void CPlayerInterface::finishMovement( const TryMoveHero &details, const int3 &hp, const CGHeroInstance * ho )
@ -1851,7 +1853,7 @@ void CPlayerInterface::showPuzzleMap()
void CPlayerInterface::viewWorldMap()
{
adventureInt->changeMode(EAdvMapMode::WORLD_VIEW);
adventureInt->changeMode(EAdvMapMode::WORLD_VIEW, 0.36F);
}
void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellID)
@ -1891,14 +1893,14 @@ void CPlayerInterface::eraseCurrentPathOf(const CGHeroInstance * ho, bool checkF
assert(ho == adventureInt->selection);
paths.erase(ho);
adventureInt->terrain.currentPath = nullptr;
adventureInt->terrain->currentPath = nullptr;
adventureInt->updateMoveHero(ho, false);
}
void CPlayerInterface::removeLastNodeFromPath(const CGHeroInstance *ho)
{
adventureInt->terrain.currentPath->nodes.erase(adventureInt->terrain.currentPath->nodes.end()-1);
if (adventureInt->terrain.currentPath->nodes.size() < 2) //if it was the last one, remove entire path and path with only one tile is not a real path
adventureInt->terrain->currentPath->nodes.erase(adventureInt->terrain->currentPath->nodes.end()-1);
if (adventureInt->terrain->currentPath->nodes.size() < 2) //if it was the last one, remove entire path and path with only one tile is not a real path
eraseCurrentPathOf(ho);
}
@ -1928,10 +1930,8 @@ CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
void CPlayerInterface::acceptTurn()
{
bool centerView = true;
if (settings["session"]["autoSkip"].Bool())
{
centerView = false;
while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
iw->close();
}
@ -1943,44 +1943,7 @@ void CPlayerInterface::acceptTurn()
adventureInt->startTurn();
}
adventureInt->heroList.update();
adventureInt->townList.update();
const CGHeroInstance * heroToSelect = nullptr;
// find first non-sleeping hero
for (auto hero : wanderingHeroes)
{
if (boost::range::find(sleepingHeroes, hero) == sleepingHeroes.end())
{
heroToSelect = hero;
break;
}
}
//select first hero if available.
if (heroToSelect != nullptr)
{
adventureInt->select(heroToSelect, centerView);
}
else if (towns.size())
adventureInt->select(towns.front(), centerView);
else
adventureInt->select(wanderingHeroes.front());
//show new day animation and sound on infobar
adventureInt->infoBar.showDate();
adventureInt->updateNextHero(nullptr);
adventureInt->showAll(screen);
if(settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown())
{
if(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
iw->close();
adventureInt->fendTurn();
}
adventureInt->initializeNewTurn();
// warn player if he has no town
if (cb->howManyTowns() == 0)
@ -2049,7 +2012,7 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance * h)
void CPlayerInterface::updateInfo(const CGObjectInstance * specific)
{
adventureInt->infoBar.showSelection();
adventureInt->infoBar->showSelection();
}
void CPlayerInterface::battleNewRoundFirst( int round )
@ -2160,14 +2123,14 @@ void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al)
void CPlayerInterface::artifactPut(const ArtifactLocation &al)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->infoBar.showSelection();
adventureInt->infoBar->showSelection();
askToAssembleArtifact(al);
}
void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->infoBar.showSelection();
adventureInt->infoBar->showSelection();
for(auto isa : GH.listInt)
{
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
@ -2181,7 +2144,7 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->infoBar.showSelection();
adventureInt->infoBar->showSelection();
for(auto isa : GH.listInt)
{
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
@ -2202,7 +2165,7 @@ void CPlayerInterface::artifactPossibleAssembling(const ArtifactLocation & dst)
void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->infoBar.showSelection();
adventureInt->infoBar->showSelection();
for(auto isa : GH.listInt)
{
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
@ -2214,7 +2177,7 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->infoBar.showSelection();
adventureInt->infoBar->showSelection();
for(auto isa : GH.listInt)
{
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
@ -2233,7 +2196,7 @@ void CPlayerInterface::playerStartsTurn(PlayerColor player)
}
else
{
adventureInt->infoBar.showSelection();
adventureInt->infoBar->showSelection();
while (GH.listInt.front() != adventureInt && !dynamic_cast<CInfoWindow*>(GH.listInt.front().get())) //don't remove dialogs that expect query answer
GH.popInts(1);
}

View File

@ -176,6 +176,7 @@ public:
void centerView (int3 pos, int focusTime) override;
void objectPropertyChanged(const SetObjectProperty * sop) override;
void objectRemoved(const CGObjectInstance *obj) override;
void objectRemovedAfter() override;
void playerBlocked(int reason, bool start) override;
void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface

View File

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

View File

@ -429,6 +429,8 @@ void ApplyFirstClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
void ApplyClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
{
cl.invalidatePaths();
for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++)
i->second->objectRemovedAfter();
}
void ApplyFirstClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)

View File

@ -13,6 +13,11 @@
#include "CAdvMapPanel.h"
#include "CAdventureOptions.h"
#include "CInGameConsole.h"
#include "CMinimap.h"
#include "CResDataBar.h"
#include "CTerrainRect.h"
#include "CList.h"
#include "CInfoBar.h"
#include "mapHandler.h"
#include "../windows/CKingdomInterface.h"
@ -47,7 +52,7 @@
std::shared_ptr<CAdvMapInt> adventureInt;
static void setScrollingCursor(ui8 direction)
void CAdvMapInt::setScrollingCursor(ui8 direction) const
{
if(direction & CAdvMapInt::RIGHT)
{
@ -76,13 +81,16 @@ static void setScrollingCursor(ui8 direction)
CAdvMapInt::CAdvMapInt():
mode(EAdvMapMode::NORMAL),
worldViewScale(0.0f), //actual init later in changeMode
minimap(Rect(ADVOPT.minimapX, ADVOPT.minimapY, ADVOPT.minimapW, ADVOPT.minimapH)),
minimap(new CMinimap(Rect(ADVOPT.minimapX, ADVOPT.minimapY, ADVOPT.minimapW, ADVOPT.minimapH))),
statusbar(CGStatusBar::create(ADVOPT.statusbarX,ADVOPT.statusbarY,ADVOPT.statusbarG)),
heroList(ADVOPT.hlistSize, Point(ADVOPT.hlistX, ADVOPT.hlistY), ADVOPT.hlistAU, ADVOPT.hlistAD),
townList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD),
infoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192)), state(NA),
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(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192))),
resdatabar(new CResDataBar),
terrain(new CTerrainRect),
state(NA),
spellBeingCasted(nullptr), position(int3(0, 0, 0)), selection(nullptr),
updateScreen(false), anim(0), animValHitCount(0), heroAnim(0), heroAnimValHitCount(0),
redrawOnNextFrame(false), anim(0), animValHitCount(0), heroAnim(0), heroAnimValHitCount(0),
activeMapPanel(nullptr), duringAITurn(false), scrollingDir(0), scrollingState(false),
swipeEnabled(settings["general"]["swipe"].Bool()), swipeMovementRequested(false),
swipeTargetPosition(int3(-1, -1, -1))
@ -91,7 +99,7 @@ CAdvMapInt::CAdvMapInt():
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
townList.onSelect = std::bind(&CAdvMapInt::selectionChanged,this);
townList->onSelect = std::bind(&CAdvMapInt::selectionChanged,this);
bg = IImage::createFromFile(ADVOPT.mainGraphic);
if(!ADVOPT.worldViewGraphic.empty())
{
@ -135,11 +143,11 @@ CAdvMapInt::CAdvMapInt():
nextHero = makeButton(301, std::bind(&CAdvMapInt::fnextHero,this), ADVOPT.nextHero, SDLK_h);
endTurn = makeButton(302, std::bind(&CAdvMapInt::fendTurn,this), ADVOPT.endTurn, SDLK_e);
int panelSpaceBottom = GH.screenDimensions().y - resdatabar.pos.h - 4;
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);
panelWorldView = std::make_shared<CAdvMapWorldViewPanel>(worldViewIcons, bgWorldView, Point(heroList->pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID);
panelMain->addChildColorableButton(kingOverview);
panelMain->addChildColorableButton(underground);
@ -207,7 +215,7 @@ CAdvMapInt::CAdvMapInt():
setPlayer(LOCPLINT->playerID);
int iconColorMultiplier = player.getNum() * 19;
int wvLeft = heroList.pos.x - 2; // TODO correct drawing position
int wvLeft = heroList->pos.x - 2; // TODO correct drawing position
//int wvTop = 195;
for (int i = 0; i < 5; ++i)
{
@ -229,7 +237,7 @@ CAdvMapInt::CAdvMapInt():
activeMapPanel = panelMain;
changeMode(EAdvMapMode::NORMAL);
changeMode(EAdvMapMode::NORMAL, 0.36F);
underground->block(!CGI->mh->map->twoLevel);
questlog->block(!CGI->mh->map->quests.size());
@ -245,7 +253,7 @@ void CAdvMapInt::fshowOverview()
void CAdvMapInt::fworldViewBack()
{
changeMode(EAdvMapMode::NORMAL);
changeMode(EAdvMapMode::NORMAL, 0.36F);
CGI->mh->discardWorldViewCache();
auto hero = curHero();
@ -256,17 +264,17 @@ void CAdvMapInt::fworldViewBack()
void CAdvMapInt::fworldViewScale1x()
{
// TODO set corresponding scale button to "selected" mode
changeMode(EAdvMapMode::WORLD_VIEW, 0.22f);
changeMode(EAdvMapMode::WORLD_VIEW, 0.22f); // 7 pixels per tile
}
void CAdvMapInt::fworldViewScale2x()
{
changeMode(EAdvMapMode::WORLD_VIEW, 0.36f);
changeMode(EAdvMapMode::WORLD_VIEW, 0.36f); // 11 pixels per tile
}
void CAdvMapInt::fworldViewScale4x()
{
changeMode(EAdvMapMode::WORLD_VIEW, 0.5f);
changeMode(EAdvMapMode::WORLD_VIEW, 0.5f); // 16 pixels per tile
}
void CAdvMapInt::fswitchLevel()
@ -284,11 +292,11 @@ void CAdvMapInt::fswitchLevel()
worldViewUnderground->setIndex(position.z, true);
worldViewUnderground->redraw();
updateScreen = true;
minimap.setLevel(position.z);
redrawOnNextFrame = true;
minimap->setLevel(position.z);
if (mode == EAdvMapMode::WORLD_VIEW)
terrain.redraw();
terrain->redraw();
}
void CAdvMapInt::fshowQuestlog()
{
@ -315,10 +323,10 @@ void CAdvMapInt::fsleepWake()
void CAdvMapInt::fmoveHero()
{
const CGHeroInstance *h = curHero();
if (!h || !terrain.currentPath || !CGI->mh->canStartHeroMovement())
if (!h || !terrain->currentPath || !CGI->mh->canStartHeroMovement())
return;
LOCPLINT->moveHero(h, *terrain.currentPath);
LOCPLINT->moveHero(h, *terrain->currentPath);
}
void CAdvMapInt::fshowSpellbok()
@ -461,12 +469,12 @@ void CAdvMapInt::activate()
activeMapPanel->activate();
if (mode == EAdvMapMode::NORMAL)
{
heroList.activate();
townList.activate();
infoBar.activate();
heroList->activate();
townList->activate();
infoBar->activate();
}
minimap.activate();
terrain.activate();
minimap->activate();
terrain->activate();
statusbar->activate();
GH.fakeMouseMove(); //to restore the cursor
@ -485,12 +493,12 @@ void CAdvMapInt::deactivate()
activeMapPanel->deactivate();
if (mode == EAdvMapMode::NORMAL)
{
heroList.deactivate();
townList.deactivate();
infoBar.deactivate();
heroList->deactivate();
townList->deactivate();
infoBar->deactivate();
}
minimap.deactivate();
terrain.deactivate();
minimap->deactivate();
terrain->deactivate();
statusbar->deactivate();
}
}
@ -506,23 +514,23 @@ void CAdvMapInt::showAll(SDL_Surface * to)
{
case EAdvMapMode::NORMAL:
heroList.showAll(to);
townList.showAll(to);
infoBar.showAll(to);
heroList->showAll(to);
townList->showAll(to);
infoBar->showAll(to);
break;
case EAdvMapMode::WORLD_VIEW:
terrain.showAll(to);
terrain->showAll(to);
break;
}
activeMapPanel->showAll(to);
updateScreen = true;
minimap.showAll(to);
redrawOnNextFrame = true;
minimap->showAll(to);
show(to);
resdatabar.showAll(to);
resdatabar->showAll(to);
statusbar->show(to);
@ -562,7 +570,7 @@ void CAdvMapInt::show(SDL_Surface * to)
CGI->mh->updateWater();
animValHitCount = 0;
++anim;
updateScreen = true;
redrawOnNextFrame = true;
}
if(swipeEnabled)
@ -583,7 +591,7 @@ void CAdvMapInt::show(SDL_Surface * to)
else
gems[i]->setFrame(LOCPLINT->playerID.getNum());
}
if(updateScreen)
if(redrawOnNextFrame)
{
int3 betterPos = LOCPLINT->repairScreenPos(position);
if (betterPos != position)
@ -592,20 +600,20 @@ void CAdvMapInt::show(SDL_Surface * to)
position = betterPos;
}
terrain.show(to);
terrain->show(to);
for(int i = 0; i < 4; i++)
gems[i]->showAll(to);
updateScreen=false;
redrawOnNextFrame=false;
LOCPLINT->cingconsole->show(to);
}
else if (terrain.needsAnimUpdate())
else
{
terrain.showAnim(to);
terrain->showAnim(to);
for(int i = 0; i < 4; i++)
gems[i]->showAll(to);
}
infoBar.show(to);
infoBar->show(to);
statusbar->showAll(to);
}
@ -613,8 +621,7 @@ void CAdvMapInt::handleMapScrollingUpdate()
{
int scrollSpeed = static_cast<int>(settings["adventure"]["scrollSpeed"].Float());
//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
if((animValHitCount % (4 / scrollSpeed)) == 0
&& GH.isKeyboardCtrlDown())
if((animValHitCount % (4 / scrollSpeed)) == 0)
{
if((scrollingDir & LEFT) && (position.x > -CGI->mh->frameW))
position.x--;
@ -632,10 +639,10 @@ void CAdvMapInt::handleMapScrollingUpdate()
{
setScrollingCursor(scrollingDir);
scrollingState = true;
updateScreen = true;
minimap.redraw();
redrawOnNextFrame = true;
minimap->redraw();
if(mode == EAdvMapMode::WORLD_VIEW)
terrain.redraw();
terrain->redraw();
}
else if(scrollingState)
{
@ -653,15 +660,15 @@ void CAdvMapInt::handleSwipeUpdate()
position.x = fixedPos.x;
position.y = fixedPos.y;
CCS->curh->set(Cursor::Map::POINTER);
updateScreen = true;
minimap.redraw();
redrawOnNextFrame = true;
minimap->redraw();
swipeMovementRequested = false;
}
}
void CAdvMapInt::selectionChanged()
{
const CGTownInstance *to = LOCPLINT->towns[townList.getSelectedIndex()];
const CGTownInstance *to = LOCPLINT->towns[townList->getSelectedIndex()];
if (selection != to)
select(to);
}
@ -672,7 +679,7 @@ void CAdvMapInt::centerOn(int3 on, bool fade)
if (fade)
{
terrain.fadeFromCurrentView();
terrain->fadeFromCurrentView();
}
switch (mode)
@ -692,17 +699,17 @@ void CAdvMapInt::centerOn(int3 on, bool fade)
on = LOCPLINT->repairScreenPos(on);
position = on;
updateScreen=true;
redrawOnNextFrame=true;
underground->setIndex(on.z,true); //change underground switch button image
underground->redraw();
worldViewUnderground->setIndex(on.z, true);
worldViewUnderground->redraw();
if (switchedLevels)
minimap.setLevel(position.z);
minimap.redraw();
minimap->setLevel(position.z);
minimap->redraw();
if (mode == EAdvMapMode::WORLD_VIEW)
terrain.redraw();
terrain->redraw();
}
void CAdvMapInt::centerOn(const CGObjectInstance * obj, bool fade)
@ -853,7 +860,7 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
}
else if(isActive()) //no ctrl, advmapint is on the top => switch to town
{
townList.selectNext();
townList->selectNext();
}
return;
}
@ -869,11 +876,14 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
(direction->y<0 ? UP : 0) |
(direction->y>0 ? DOWN : 0) ;
scrollingDir |= Dir;
//ctrl makes arrow move screen, not hero
if(GH.isKeyboardCtrlDown())
{
scrollingDir |= Dir;
return;
}
if(!h || !isActive())
return;
@ -888,11 +898,11 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
}
CGPath &path = LOCPLINT->paths[h];
terrain.currentPath = &path;
terrain->currentPath = &path;
int3 dst = h->visitablePos() + int3(direction->x, direction->y, 0);
if(dst != verifyPos(dst) || !LOCPLINT->cb->getPathsInfo(h)->getPath(path, dst))
{
terrain.currentPath = nullptr;
terrain->currentPath = nullptr;
return;
}
@ -928,13 +938,6 @@ boost::optional<Point> CAdvMapInt::keyToMoveDirection(const SDL_Keycode & key)
return boost::none;
}
void CAdvMapInt::handleRightClick(std::string text, tribool down)
{
if(down)
{
CRClickPopup::createAndPush(text);
}
}
int3 CAdvMapInt::verifyPos(int3 ver)
{
if (ver.x<0)
@ -967,14 +970,14 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
if(centerView)
centerOn(sel);
terrain.currentPath = nullptr;
terrain->currentPath = nullptr;
if(sel->ID==Obj::TOWN)
{
auto town = dynamic_cast<const CGTownInstance*>(sel);
infoBar.showTownSelection(town);
townList.select(town);
heroList.select(nullptr);
infoBar->showTownSelection(town);
townList->select(town);
heroList->select(nullptr);
updateSleepWake(nullptr);
updateMoveHero(nullptr);
@ -984,18 +987,18 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
{
auto hero = dynamic_cast<const CGHeroInstance*>(sel);
infoBar.showHeroSelection(hero);
heroList.select(hero);
townList.select(nullptr);
infoBar->showHeroSelection(hero);
heroList->select(hero);
townList->select(nullptr);
terrain.currentPath = LOCPLINT->getAndVerifyPath(hero);
terrain->currentPath = LOCPLINT->getAndVerifyPath(hero);
updateSleepWake(hero);
updateMoveHero(hero);
updateSpellbook(hero);
}
townList.redraw();
heroList.redraw();
townList->redraw();
heroList->redraw();
}
void CAdvMapInt::mouseMoved( const Point & cursorPosition )
@ -1056,13 +1059,16 @@ void CAdvMapInt::startHotSeatWait(PlayerColor Player)
void CAdvMapInt::setPlayer(PlayerColor Player)
{
if (Player == player)
return;
player = Player;
bg->playerColored(player);
panelMain->setPlayerColor(player);
panelWorldView->setPlayerColor(player);
panelWorldView->recolorIcons(player, player.getNum() * 19);
resdatabar.background->colorize(player);
resdatabar->colorize(player);
}
void CAdvMapInt::startTurn()
@ -1072,7 +1078,51 @@ void CAdvMapInt::startTurn()
|| settings["session"]["spectate"].Bool())
{
adjustActiveness(false);
minimap.setAIRadar(false);
minimap->setAIRadar(false);
}
}
void CAdvMapInt::initializeNewTurn()
{
heroList->update();
townList->update();
const CGHeroInstance * heroToSelect = nullptr;
// find first non-sleeping hero
for (auto hero : LOCPLINT->wanderingHeroes)
{
if (boost::range::find(LOCPLINT->sleepingHeroes, hero) == LOCPLINT->sleepingHeroes.end())
{
heroToSelect = hero;
break;
}
}
bool centerView = !settings["session"]["autoSkip"].Bool();
//select first hero if available.
if (heroToSelect != nullptr)
{
select(heroToSelect, centerView);
}
else if (LOCPLINT->towns.size())
select(LOCPLINT->towns.front(), centerView);
else
select(LOCPLINT->wanderingHeroes.front());
//show new day animation and sound on infobar
infoBar->showDate();
updateNextHero(nullptr);
showAll(screen);
if(settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown())
{
if(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
iw->close();
endingTurn();
}
}
@ -1137,7 +1187,7 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
bool isHero = false;
if(selection->ID != Obj::HERO) //hero is not selected (presumably town)
{
assert(!terrain.currentPath); //path can be active only when hero is selected
assert(!terrain->currentPath); //path can be active only when hero is selected
if(selection == topBlocking) //selected town clicked
LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(topBlocking));
else if(canSelect)
@ -1160,10 +1210,10 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
}
else //still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise
{
if(terrain.currentPath && terrain.currentPath->endPos() == mapPos)//we'll be moving
if(terrain->currentPath && terrain->currentPath->endPos() == mapPos)//we'll be moving
{
if(CGI->mh->canStartHeroMovement())
LOCPLINT->moveHero(currentHero, *terrain.currentPath);
LOCPLINT->moveHero(currentHero, *terrain->currentPath);
return;
}
else //remove old path and find a new one if we clicked on accessible tile
@ -1175,7 +1225,7 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
path = newpath;
if(path.nodes.size())
terrain.currentPath = &path;
terrain->currentPath = &path;
else
LOCPLINT->eraseCurrentPathOf(currentHero);
@ -1274,7 +1324,7 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
if(GH.isKeyboardAltDown() && pathNode->reachable()) //overwrite status bar text with movement info
{
ShowMoveDetailsInStatusbar(*hero, *pathNode);
showMoveDetailsInStatusbar(*hero, *pathNode);
}
int turns = pathNode->turns;
@ -1340,7 +1390,7 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
}
}
void CAdvMapInt::ShowMoveDetailsInStatusbar(const CGHeroInstance & hero, const CGPathNode & pathNode)
void CAdvMapInt::showMoveDetailsInStatusbar(const CGHeroInstance & hero, const CGPathNode & pathNode)
{
const int maxMovementPointsAtStartOfLastTurn = pathNode.turns > 0 ? hero.maxMovePoints(pathNode.layer == EPathfindingLayer::LAND) : hero.movement;
const int movementPointsLastTurnCost = maxMovementPointsAtStartOfLastTurn - pathNode.moveRemains;
@ -1393,7 +1443,7 @@ void CAdvMapInt::enterCastingMode(const CSpell * sp)
spellBeingCasted = sp;
deactivate();
terrain.activate();
terrain->activate();
GH.fakeMouseMove();
}
@ -1402,7 +1452,7 @@ void CAdvMapInt::leaveCastingMode(bool cast, int3 dest)
assert(spellBeingCasted);
SpellID id = spellBeingCasted->id;
spellBeingCasted = nullptr;
terrain.deactivate();
terrain->deactivate();
activate();
if(cast)
@ -1414,7 +1464,7 @@ void CAdvMapInt::leaveCastingMode(bool cast, int3 dest)
const CGHeroInstance * CAdvMapInt::curHero() const
{
if(selection && selection->ID == Obj::HERO)
return static_cast<const CGHeroInstance *>(selection);
return dynamic_cast<const CGHeroInstance *>(selection);
else
return nullptr;
}
@ -1422,11 +1472,29 @@ const CGHeroInstance * CAdvMapInt::curHero() const
const CGTownInstance * CAdvMapInt::curTown() const
{
if(selection && selection->ID == Obj::TOWN)
return static_cast<const CGTownInstance *>(selection);
return dynamic_cast<const CGTownInstance *>(selection);
else
return nullptr;
}
const CArmedInstance * CAdvMapInt::curArmy() const
{
if (selection)
return dynamic_cast<const CArmedInstance *>(selection);
else
return nullptr;
}
Rect CAdvMapInt::terrainAreaPixels() const
{
return terrain->pos;
}
Rect CAdvMapInt::terrainAreaTiles() const
{
return terrain->visibleTilesArea();
}
const IShipyard * CAdvMapInt::ourInaccessibleShipyard(const CGObjectInstance *obj) const
{
const IShipyard *ret = IShipyard::castFrom(obj);
@ -1446,9 +1514,9 @@ void CAdvMapInt::aiTurnStarted()
adjustActiveness(true);
CCS->musich->playMusicFromSet("enemy-turn", true, false);
adventureInt->minimap.setAIRadar(true);
adventureInt->infoBar.startEnemyTurn(LOCPLINT->cb->getCurrentPlayer());
adventureInt->infoBar.showAll(screen);//force refresh on inactive object
adventureInt->minimap->setAIRadar(true);
adventureInt->infoBar->startEnemyTurn(LOCPLINT->cb->getCurrentPlayer());
adventureInt->infoBar->showAll(screen);//force refresh on inactive object
}
void CAdvMapInt::adjustActiveness(bool aiTurnStart)
@ -1487,9 +1555,9 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale)
panelWorldView->deactivate();
activeMapPanel = panelMain;
townList.activate();
heroList.activate();
infoBar.activate();
townList->activate();
heroList->activate();
infoBar->activate();
worldViewOptions.clear();
@ -1500,10 +1568,10 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale)
activeMapPanel = panelWorldView;
townList.deactivate();
heroList.deactivate();
infoBar.showSelection(); // to prevent new day animation interfering world view mode
infoBar.deactivate();
townList->deactivate();
heroList->deactivate();
infoBar->showSelection(); // to prevent new day animation interfering world view mode
infoBar->deactivate();
break;
}
@ -1536,3 +1604,7 @@ void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
info.additionalIcons = &iconPositions;
}
void CAdvMapInt::requestRedrawMapOnNextFrame()
{
redrawOnNextFrame = true;
}

View File

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

View File

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

View File

@ -51,9 +51,9 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel
std::shared_ptr<CAnimation> icons;
public:
CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color);
virtual ~CAdvMapWorldViewPanel();
void addChildIcon(std::pair<int, Point> data, int indexOffset);
/// recreates all pictures from given def to recolor them according to current player color
void recolorIcons(const PlayerColor & color, int indexOffset);
};

View File

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

View File

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

View File

@ -17,6 +17,7 @@
#include "../widgets/Images.h"
#include "../widgets/TextControls.h"
#include "../widgets/MiscWidgets.h"
#include "../windows/InfoWindows.h"
#include "../CGameInfo.h"
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
@ -196,19 +197,18 @@ void CInfoBar::reset()
void CInfoBar::showSelection()
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
if(adventureInt->selection)
if(adventureInt->curHero())
{
if(auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection))
{
showHeroSelection(hero);
return;
}
else if(auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection))
{
showTownSelection(town);
return;
}
showHeroSelection(adventureInt->curHero());
return;
}
if(adventureInt->curTown())
{
showTownSelection(adventureInt->curTown());
return;
}
showGameStatus();//FIXME: may be incorrect but shouldn't happen in general
}
@ -234,7 +234,8 @@ void CInfoBar::clickLeft(tribool down, bool previousState)
void CInfoBar::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(CGI->generaltexth->allTexts[109], down);
if (down)
CRClickPopup::createAndPush(CGI->generaltexth->allTexts[109]);
}
void CInfoBar::hover(bool on)

View File

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

View File

@ -12,6 +12,7 @@
#include "CMinimap.h"
#include "CAdvMapInt.h"
#include "CTerrainRect.h"
#include "../widgets/Images.h"
#include "../CGameInfo.h"
@ -19,6 +20,7 @@
#include "../gui/CGuiHandler.h"
#include "../render/Colors.h"
#include "../renderSDL/SDL_PixelAccess.h"
#include "../windows/InfoWindows.h"
#include "../../CCallback.h"
#include "../../lib/CGeneralTextHandler.h"
@ -26,159 +28,65 @@
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapping/CMapDefines.h"
#include <SDL_surface.h>
const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos)
ColorRGBA CMinimapInstance::getTileColor(const int3 & pos) const
{
const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
// if tile is not visible it will be black on minimap
if(!tile)
return Colors::BLACK;
return CSDL_Ext::fromSDL(Colors::BLACK);
// if object at tile is owned - it will be colored as its owner
for (const CGObjectInstance *obj : tile->blockingObjects)
{
//heroes will be blitted later
switch (obj->ID)
{
case Obj::HERO:
case Obj::PRISON:
continue;
}
PlayerColor player = obj->getOwner();
if(player == PlayerColor::NEUTRAL)
return *graphics->neutralColor;
else
return CSDL_Ext::fromSDL(*graphics->neutralColor);
if (player < PlayerColor::PLAYER_LIMIT)
return graphics->playerColors[player.getNum()];
return CSDL_Ext::fromSDL(graphics->playerColors[player.getNum()]);
}
// else - use terrain color (blocked version or normal)
const auto & colorPair = parent->colors.find(tile->terType->getId())->second;
if (tile->blocked && (!tile->visitable))
return colorPair.second;
return tile->terType->minimapBlocked;
else
return colorPair.first;
}
void CMinimapInstance::tileToPixels (const int3 &tile, int &x, int &y, int toX, int toY)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
double stepX = double(pos.w) / mapSizes.x;
double stepY = double(pos.h) / mapSizes.y;
x = static_cast<int>(toX + stepX * tile.x);
y = static_cast<int>(toY + stepY * tile.y);
}
void CMinimapInstance::blitTileWithColor(const SDL_Color &color, const int3 &tile, SDL_Surface *to, int toX, int toY)
{
//coordinates of rectangle on minimap representing this tile
// begin - first to blit, end - first NOT to blit
int xBegin, yBegin, xEnd, yEnd;
tileToPixels (tile, xBegin, yBegin, toX, toY);
tileToPixels (int3 (tile.x + 1, tile.y + 1, tile.z), xEnd, yEnd, toX, toY);
for (int y=yBegin; y<yEnd; y++)
{
uint8_t *ptr = (uint8_t*)to->pixels + y * to->pitch + xBegin * minimap->format->BytesPerPixel;
for (int x=xBegin; x<xEnd; x++)
ColorPutter<4, 1>::PutColor(ptr, color);
}
return tile->terType->minimapUnblocked;
}
void CMinimapInstance::refreshTile(const int3 &tile)
{
blitTileWithColor(getTileColor(int3(tile.x, tile.y, level)), tile, minimap, 0, 0);
if (level == tile.z)
minimap->drawPoint(Point(tile.x, tile.y), getTileColor(tile));
}
void CMinimapInstance::drawScaled(int level)
void CMinimapInstance::redrawMinimap()
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
//size of one map tile on our minimap
double stepX = double(pos.w) / mapSizes.x;
double stepY = double(pos.h) / mapSizes.y;
double currY = 0;
for (int y=0; y<mapSizes.y; y++, currY += stepY)
{
double currX = 0;
for (int x=0; x<mapSizes.x; x++, currX += stepX)
{
const SDL_Color &color = getTileColor(int3(x,y,level));
//coordinates of rectangle on minimap representing this tile
// begin - first to blit, end - first NOT to blit
int xBegin = static_cast<int>(currX);
int yBegin = static_cast<int>(currY);
int xEnd = static_cast<int>(currX + stepX);
int yEnd = static_cast<int>(currY + stepY);
for (int y=yBegin; y<yEnd; y++)
{
uint8_t *ptr = (uint8_t*)minimap->pixels + y * minimap->pitch + xBegin * minimap->format->BytesPerPixel;
for (int x=xBegin; x<xEnd; x++)
ColorPutter<4, 1>::PutColor(ptr, color);
}
}
}
for (int y = 0; y < mapSizes.y; ++y)
for (int x = 0; x < mapSizes.x; ++x)
minimap->drawPoint(Point(x, y), getTileColor(int3(x, y, level)));
}
CMinimapInstance::CMinimapInstance(CMinimap *Parent, int Level):
parent(Parent),
minimap(CSDL_Ext::createSurfaceWithBpp<4>(parent->pos.w, parent->pos.h)),
minimap(new Canvas(Point(LOCPLINT->cb->getMapSize().x, LOCPLINT->cb->getMapSize().y))),
level(Level)
{
pos.w = parent->pos.w;
pos.h = parent->pos.h;
drawScaled(level);
}
CMinimapInstance::~CMinimapInstance()
{
SDL_FreeSurface(minimap);
redrawMinimap();
}
void CMinimapInstance::showAll(SDL_Surface * to)
{
blitAtLoc(minimap, 0, 0, to);
//draw heroes
std::vector <const CGHeroInstance *> heroes = LOCPLINT->cb->getHeroesInfo(false); //TODO: do we really need separate function for drawing heroes?
for(auto & hero : heroes)
{
int3 position = hero->visitablePos();
if(position.z == level)
{
const SDL_Color & color = graphics->playerColors[hero->getOwner().getNum()];
blitTileWithColor(color, position, to, pos.x, pos.y);
}
}
}
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors()
{
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > ret;
for(const auto & terrain : CGI->terrainTypeHandler->objects)
{
SDL_Color normal = CSDL_Ext::toSDL(terrain->minimapUnblocked);
SDL_Color blocked = CSDL_Ext::toSDL(terrain->minimapBlocked);
ret[terrain->getId()] = std::make_pair(normal, blocked);
}
return ret;
Canvas target(to);
target.draw(*minimap, pos.topLeft(), pos.dimensions());
}
CMinimap::CMinimap(const Rect & position)
: CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()),
level(0),
colors(loadColors())
level(0)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
pos.w = position.w;
@ -188,21 +96,36 @@ CMinimap::CMinimap(const Rect & position)
aiShield->disable();
}
int3 CMinimap::translateMousePosition()
int3 CMinimap::pixelToTile(const Point & cursorPos) const
{
// 0 = top-left corner, 1 = bottom-right corner
double dx = double(GH.getCursorPosition().x - pos.x) / pos.w;
double dy = double(GH.getCursorPosition().y - pos.y) / pos.h;
double dx = static_cast<double>(cursorPos.x) / pos.w;
double dy = static_cast<double>(cursorPos.y) / pos.h;
int3 mapSizes = LOCPLINT->cb->getMapSize();
int3 tile ((si32)(mapSizes.x * dx), (si32)(mapSizes.y * dy), level);
return tile;
int tileX(std::round(mapSizes.x * dx));
int tileY(std::round(mapSizes.y * dy));
return int3(tileX, tileY, level);
}
Point CMinimap::tileToPixels(const int3 &tile) const
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
double stepX = static_cast<double>(pos.w) / mapSizes.x;
double stepY = static_cast<double>(pos.h) / mapSizes.y;
int x = static_cast<int>(stepX * tile.x);
int y = static_cast<int>(stepY * tile.y);
return Point(x,y);
}
void CMinimap::moveAdvMapSelection()
{
int3 newLocation = translateMousePosition();
int3 newLocation = pixelToTile(GH.getCursorPosition() - pos.topLeft());
adventureInt->centerOn(newLocation);
if (!(adventureInt->active & GENERAL))
@ -219,7 +142,8 @@ void CMinimap::clickLeft(tribool down, bool previousState)
void CMinimap::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(CGI->generaltexth->zelp[291].second, down);
if (down)
CRClickPopup::createAndPush(CGI->generaltexth->zelp[291].second);
}
void CMinimap::hover(bool on)
@ -241,33 +165,22 @@ void CMinimap::showAll(SDL_Surface * to)
CIntObject::showAll(to);
if(minimap)
{
Canvas target(to);
int3 mapSizes = LOCPLINT->cb->getMapSize();
int3 tileCountOnScreen = adventureInt->terrain.tileCountOnScreen();
Rect screenArea = adventureInt->terrainAreaTiles();
//draw radar
Rect oldClip;
Rect radar =
{
si16(adventureInt->position.x * pos.w / mapSizes.x + pos.x),
si16(adventureInt->position.y * pos.h / mapSizes.y + pos.y),
ui16(tileCountOnScreen.x * pos.w / mapSizes.x),
ui16(tileCountOnScreen.y * pos.h / mapSizes.y)
screenArea.x * pos.w / mapSizes.x,
screenArea.y * pos.h / mapSizes.y,
screenArea.w * pos.w / mapSizes.x - 1,
screenArea.h * pos.h / mapSizes.y - 1
};
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
{
// adjusts radar so that it doesn't go out of map in world view mode (since there's no frame)
radar.x = std::min<int>(std::max(pos.x, radar.x), pos.x + pos.w - radar.w);
radar.y = std::min<int>(std::max(pos.y, radar.y), pos.y + pos.h - radar.h);
if(radar.x < pos.x && radar.y < pos.y)
return; // whole map is visible at once, no point in redrawing border
}
CSDL_Ext::getClipRect(to, oldClip);
CSDL_Ext::setClipRect(to, pos);
CSDL_Ext::drawDashedBorder(to, radar, Colors::PURPLE);
CSDL_Ext::setClipRect(to, oldClip);
Canvas clippedTarget(target, pos);
clippedTarget.drawBorderDashed(radar, CSDL_Ext::fromSDL(Colors::PURPLE));
}
}
@ -283,6 +196,9 @@ void CMinimap::update()
void CMinimap::setLevel(int newLevel)
{
if (level == newLevel)
return;
level = newLevel;
update();
}
@ -299,18 +215,13 @@ void CMinimap::setAIRadar(bool on)
aiShield->disable();
update();
}
// this my happen during AI turn when this interface is inactive
// this may happen during AI turn when this interface is inactive
// force redraw in order to properly update interface
GH.totalRedraw();
}
void CMinimap::hideTile(const int3 &pos)
{
if(minimap)
minimap->refreshTile(pos);
}
void CMinimap::showTile(const int3 &pos)
void CMinimap::updateTile(const int3 &pos)
{
if(minimap)
minimap->refreshTile(pos);

View File

@ -11,67 +11,63 @@
#include "../gui/CIntObject.h"
#include "../../lib/GameConstants.h"
#include "../render/Canvas.h"
VCMI_LIB_NAMESPACE_BEGIN
class ColorRGBA;
VCMI_LIB_NAMESPACE_END
struct SDL_Color;
class CMinimap;
class CMinimapInstance : public CIntObject
{
CMinimap * parent;
SDL_Surface * minimap;
std::unique_ptr<Canvas> minimap;
int level;
//get color of selected tile on minimap
const SDL_Color & getTileColor(const int3 & pos);
ColorRGBA getTileColor(const int3 & pos) const;
void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface * to, int x, int y);
//draw minimap already scaled.
//result is not antialiased. Will result in "missing" pixels on huge maps (>144)
void drawScaled(int level);
void redrawMinimap();
public:
CMinimapInstance(CMinimap * parent, int level);
~CMinimapInstance();
void showAll(SDL_Surface * to) override;
void tileToPixels (const int3 & tile, int & x, int & y, int toX = 0, int toY = 0);
void refreshTile(const int3 & pos);
};
/// Minimap which is displayed at the right upper corner of adventure map
class CMinimap : public CIntObject
{
protected:
std::shared_ptr<CPicture> aiShield; //the graphic displayed during AI turn
std::shared_ptr<CMinimapInstance> minimap;
int level;
//to initialize colors
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > loadColors();
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void hover (bool on) override;
void mouseMoved (const Point & cursorPosition) override;
/// relocates center of adventure map screen to currently hovered tile
void moveAdvMapSelection();
protected:
/// computes coordinates of tile below cursor pos
int3 pixelToTile(const Point & cursorPos) const;
/// computes position of tile within minimap instance
Point tileToPixels(const int3 & position) const;
public:
// terrainID -> (normal color, blocked color)
const std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > colors;
CMinimap(const Rect & position);
explicit CMinimap(const Rect & position);
//should be called to invalidate whole map - different player or level
int3 translateMousePosition();
void update();
void setLevel(int level);
void setAIRadar(bool on);
void showAll(SDL_Surface * to) override;
void hideTile(const int3 &pos); //puts FoW
void showTile(const int3 &pos); //removes FoW
void updateTile(const int3 &pos);
};

View File

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

View File

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

View File

@ -189,7 +189,7 @@ void CTerrainRect::hover(bool on)
{
if (!on)
{
adventureInt->statusbar->clear();
GH.statusbar->clear();
CCS->curh->set(Cursor::Map::POINTER);
}
//Hoverable::hover(on);
@ -360,10 +360,11 @@ void CTerrainRect::showAll(SDL_Surface * to)
void CTerrainRect::showAnim(SDL_Surface * to)
{
if (fadeAnim->isFading())
if (!needsAnimUpdate())
return;
if (fadeAnim->isFading() || lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
show(to);
else if (lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
show(to); // currently the same; maybe we should pass some flag to map handler so it redraws ONLY tiles that need redraw instead of full
}
int3 CTerrainRect::whichTileIsIt(const int x, const int y)
@ -380,17 +381,17 @@ int3 CTerrainRect::whichTileIsIt()
return whichTileIsIt(GH.getCursorPosition().x, GH.getCursorPosition().y);
}
int3 CTerrainRect::tileCountOnScreen()
Rect CTerrainRect::visibleTilesArea()
{
switch (adventureInt->mode)
{
default:
logGlobal->error("Unknown map mode %d", (int)adventureInt->mode);
return int3();
return Rect();
case EAdvMapMode::NORMAL:
return int3(tilesw, tilesh, 1);
return Rect(adventureInt->position.x, adventureInt->position.y, tilesw, tilesh);
case EAdvMapMode::WORLD_VIEW:
return int3((si32)(tilesw / adventureInt->worldViewScale), (si32)(tilesh / adventureInt->worldViewScale), 1);
return Rect(adventureInt->position.x, adventureInt->position.y, tilesw / adventureInt->worldViewScale, tilesh / adventureInt->worldViewScale);
}
}

View File

@ -35,14 +35,22 @@ class CTerrainRect : public CIntObject
void handleSwipeMove(const Point & cursorPosition);
/// handles start/finish of swipe (press/release of corresponding button); returns true if state change was handled
bool handleSwipeStateChange(bool btnPressed);
int3 curHoveredTile;
int3 whichTileIsIt(const int x, const int y); //x,y are cursor position
int3 whichTileIsIt(); //uses current cursor pos
void showPath(const Rect &extRect, SDL_Surface * to);
bool needsAnimUpdate();
public:
int tilesw, tilesh; //width and height of terrain to blit in tiles
int3 curHoveredTile;
int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels)
CGPath * currentPath;
CTerrainRect();
virtual ~CTerrainRect();
~CTerrainRect();
// CIntObject interface implementation
void deactivate() override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
@ -51,14 +59,13 @@ public:
void mouseMoved (const Point & cursorPosition) override;
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
void showAnim(SDL_Surface * to);
void showPath(const Rect &extRect, SDL_Surface * to);
int3 whichTileIsIt(const int x, const int y); //x,y are cursor position
int3 whichTileIsIt(); //uses current cursor pos
/// @returns number of visible tiles on screen respecting current map scaling
int3 tileCountOnScreen();
Rect visibleTilesArea();
/// animates view by caching current surface and crossfading it with normal screen
void fadeFromCurrentView();
bool needsAnimUpdate();
};

View File

@ -360,7 +360,7 @@ void CMapHandler::init()
logGlobal->info("\tMaking object rects: %d ms", th.getDiff());
}
CMapHandler::CMapBlitter *CMapHandler::resolveBlitter(const MapDrawingInfo * info) const
CMapBlitter *CMapHandler::resolveBlitter(const MapDrawingInfo * info) const
{
if (info->scaled)
return worldViewBlitter;
@ -370,12 +370,12 @@ CMapHandler::CMapBlitter *CMapHandler::resolveBlitter(const MapDrawingInfo * inf
return normalBlitter;
}
void CMapHandler::CMapNormalBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const
void CMapNormalBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const
{
source->draw(targetSurf, destRect, sourceRect);
}
void CMapHandler::CMapNormalBlitter::init(const MapDrawingInfo * drawingInfo)
void CMapNormalBlitter::init(const MapDrawingInfo * drawingInfo)
{
info = drawingInfo;
// Width and height of the portion of the map to process. Units in tiles.
@ -426,7 +426,7 @@ void CMapHandler::CMapNormalBlitter::init(const MapDrawingInfo * drawingInfo)
tileCount.y = parent->sizes.y + parent->frameH - topTile.y;
}
Rect CMapHandler::CMapNormalBlitter::clip(SDL_Surface * targetSurf) const
Rect CMapNormalBlitter::clip(SDL_Surface * targetSurf) const
{
Rect prevClip;
CSDL_Ext::getClipRect(targetSurf, prevClip);
@ -434,7 +434,7 @@ Rect CMapHandler::CMapNormalBlitter::clip(SDL_Surface * targetSurf) const
return prevClip;
}
CMapHandler::CMapNormalBlitter::CMapNormalBlitter(CMapHandler * parent)
CMapNormalBlitter::CMapNormalBlitter(CMapHandler * parent)
: CMapBlitter(parent)
{
tileSize = 32;
@ -442,7 +442,7 @@ CMapHandler::CMapNormalBlitter::CMapNormalBlitter(CMapHandler * parent)
defaultTileRect = Rect(0, 0, tileSize, tileSize);
}
std::shared_ptr<IImage> CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const
std::shared_ptr<IImage> CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const
{
int ownerIndex = 0;
if(owner < PlayerColor::PLAYER_LIMIT)
@ -476,7 +476,7 @@ std::shared_ptr<IImage> CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id,
return std::shared_ptr<IImage>();
}
void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos()
void CMapWorldViewBlitter::calculateWorldViewCameraPos()
{
bool outsideLeft = topTile.x < 0;
bool outsideTop = topTile.y < 0;
@ -508,7 +508,7 @@ void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos()
topTile.y = parent->sizes.y - tileCount.y;
}
void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const
void CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const
{
auto scaled = parent->cache.requestWorldViewCacheOrCreate(cacheType, source);
@ -516,7 +516,7 @@ void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, std
scaled->draw(targetSurf, destRect, sourceRect);
}
void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
void CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
{
auto drawIcon = [this,targetSurf](Obj id, si32 subId, PlayerColor owner)
{
@ -548,7 +548,7 @@ void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf
}
}
void CMapHandler::CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf)
void CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf)
{
if(nullptr == info->additionalIcons)
return;
@ -580,7 +580,7 @@ void CMapHandler::CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf)
}
}
void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const
void CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const
{
if (moving)
return;
@ -588,7 +588,7 @@ void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, s
CMapBlitter::drawHeroFlag(targetSurf, source, sourceRect, destRect, false);
}
void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const
void CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const
{
if (moving)
return;
@ -597,7 +597,7 @@ void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, std
CMapBlitter::drawObject(targetSurf, source, &scaledSourceRect, false);
}
void CMapHandler::CMapBlitter::drawTileTerrain(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile2 & tile) const
void CMapBlitter::drawTileTerrain(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile2 & tile) const
{
Rect destRect(realTileRect);
@ -612,7 +612,7 @@ void CMapHandler::CMapBlitter::drawTileTerrain(SDL_Surface * targetSurf, const T
drawElement(EMapCacheType::TERRAIN, parent->terrainImages[terrainName][tinfo.terView][rotation], nullptr, targetSurf, &destRect);
}
void CMapHandler::CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo)
void CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo)
{
info = drawingInfo;
parent->cache.updateWorldViewScale(info->scale);
@ -633,7 +633,7 @@ void CMapHandler::CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo)
calculateWorldViewCameraPos();
}
Rect CMapHandler::CMapWorldViewBlitter::clip(SDL_Surface * targetSurf) const
Rect CMapWorldViewBlitter::clip(SDL_Surface * targetSurf) const
{
Rect prevClip;
@ -649,12 +649,12 @@ Rect CMapHandler::CMapWorldViewBlitter::clip(SDL_Surface * targetSurf) const
return prevClip;
}
CMapHandler::CMapWorldViewBlitter::CMapWorldViewBlitter(CMapHandler * parent)
CMapWorldViewBlitter::CMapWorldViewBlitter(CMapHandler * parent)
: CMapBlitter(parent)
{
}
void CMapHandler::CMapPuzzleViewBlitter::drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
void CMapPuzzleViewBlitter::drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
{
CMapBlitter::drawObjects(targetSurf, tile);
@ -666,12 +666,12 @@ void CMapHandler::CMapPuzzleViewBlitter::drawObjects(SDL_Surface * targetSurf, c
}
}
void CMapHandler::CMapPuzzleViewBlitter::postProcessing(SDL_Surface * targetSurf) const
void CMapPuzzleViewBlitter::postProcessing(SDL_Surface * targetSurf) const
{
CSDL_Ext::applyEffect(targetSurf, info->drawBounds, static_cast<int>(!ADVOPT.puzzleSepia));
}
bool CMapHandler::CMapPuzzleViewBlitter::canDrawObject(const CGObjectInstance * obj) const
bool CMapPuzzleViewBlitter::canDrawObject(const CGObjectInstance * obj) const
{
if (!CMapBlitter::canDrawObject(obj))
return false;
@ -686,43 +686,43 @@ bool CMapHandler::CMapPuzzleViewBlitter::canDrawObject(const CGObjectInstance *
return true;
}
CMapHandler::CMapPuzzleViewBlitter::CMapPuzzleViewBlitter(CMapHandler * parent)
CMapPuzzleViewBlitter::CMapPuzzleViewBlitter(CMapHandler * parent)
: CMapNormalBlitter(parent)
{
unblittableObjects.push_back(Obj::HOLE);
}
CMapHandler::CMapBlitter::CMapBlitter(CMapHandler * p)
CMapBlitter::CMapBlitter(CMapHandler * p)
:parent(p), tileSize(0), halfTileSizeCeil(0), info(nullptr)
{
}
CMapHandler::CMapBlitter::~CMapBlitter() = default;
CMapBlitter::~CMapBlitter() = default;
void CMapHandler::CMapBlitter::drawFrame(SDL_Surface * targetSurf) const
void CMapBlitter::drawFrame(SDL_Surface * targetSurf) const
{
Rect destRect(realTileRect);
drawElement(EMapCacheType::FRAME, parent->egdeImages[parent->edgeFrames[pos.x][pos.y][topTile.z]], nullptr, targetSurf, &destRect);
}
void CMapHandler::CMapBlitter::drawOverlayEx(SDL_Surface * targetSurf)
void CMapBlitter::drawOverlayEx(SDL_Surface * targetSurf)
{
//nothing to do here
}
void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const
void CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const
{
drawElement(EMapCacheType::HERO_FLAGS, source, sourceRect, targetSurf, destRect);
}
void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const
void CMapBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const
{
Rect dstRect(realTileRect);
drawElement(EMapCacheType::OBJECTS, source, sourceRect, targetSurf, &dstRect);
}
void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
void CMapBlitter::drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
{
auto & objects = tile.objects;
for(auto & object : objects)
@ -782,7 +782,7 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra
}
}
void CMapHandler::CMapBlitter::drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const
void CMapBlitter::drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const
{
if (tinfoUpper && tinfoUpper->roadType->getId() != Road::NO_ROAD)
{
@ -803,14 +803,14 @@ void CMapHandler::CMapBlitter::drawRoad(SDL_Surface * targetSurf, const TerrainT
}
}
void CMapHandler::CMapBlitter::drawRiver(SDL_Surface * targetSurf, const TerrainTile & tinfo) const
void CMapBlitter::drawRiver(SDL_Surface * targetSurf, const TerrainTile & tinfo) const
{
Rect destRect(realTileRect);
ui8 rotation = (tinfo.extTileFlags >> 2) % 4;
drawElement(EMapCacheType::RIVERS, parent->riverImages[tinfo.riverType->getJsonKey()][tinfo.riverDir][rotation], nullptr, targetSurf, &destRect);
}
void CMapHandler::CMapBlitter::drawFow(SDL_Surface * targetSurf) const
void CMapBlitter::drawFow(SDL_Surface * targetSurf) const
{
const NeighborTilesInfo neighborInfo(pos, parent->sizes, info->visibilityMap);
@ -829,7 +829,7 @@ void CMapHandler::CMapBlitter::drawFow(SDL_Surface * targetSurf) const
drawElement(EMapCacheType::FOW, image, nullptr, targetSurf, &destRect);
}
void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingInfo * info)
void CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingInfo * info)
{
init(info);
auto prevClip = clip(targetSurf);
@ -950,14 +950,14 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
CSDL_Ext::setClipRect(targetSurf, prevClip);
}
CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findHeroBitmap(const CGHeroInstance * hero, int anim) const
AnimBitmapHolder CMapBlitter::findHeroBitmap(const CGHeroInstance * hero, int anim) const
{
if(hero && hero->moveDir && hero->type) //it's hero or boat
{
if(hero->tempOwner >= PlayerColor::PLAYER_LIMIT) //Neutral hero?
{
logGlobal->error("A neutral hero (%s) at %s. Should not happen!", hero->getNameTranslated(), hero->pos.toString());
return CMapHandler::AnimBitmapHolder();
return AnimBitmapHolder();
}
//pick graphics of hero (or boat if hero is sailing)
@ -978,23 +978,23 @@ CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findHeroBitmap(const CGH
//get flag overlay only if we have main image
auto flagImage = findFlagBitmap(hero, anim, &hero->tempOwner, group);
return CMapHandler::AnimBitmapHolder(heroImage, flagImage, moving);
return AnimBitmapHolder(heroImage, flagImage, moving);
}
}
return CMapHandler::AnimBitmapHolder();
return AnimBitmapHolder();
}
CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findBoatBitmap(const CGBoat * boat, int anim) const
AnimBitmapHolder CMapBlitter::findBoatBitmap(const CGBoat * boat, int anim) const
{
auto animation = graphics->boatAnimations.at(boat->subID);
int group = getHeroFrameGroup(boat->direction, false);
if(animation->size(group) > 0)
return CMapHandler::AnimBitmapHolder(animation->getImage(anim % animation->size(group), group));
return AnimBitmapHolder(animation->getImage(anim % animation->size(group), group));
else
return CMapHandler::AnimBitmapHolder();
return AnimBitmapHolder();
}
std::shared_ptr<IImage> CMapHandler::CMapBlitter::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
std::shared_ptr<IImage> CMapBlitter::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
{
if(!hero)
return std::shared_ptr<IImage>();
@ -1004,12 +1004,12 @@ std::shared_ptr<IImage> CMapHandler::CMapBlitter::findFlagBitmap(const CGHeroIns
return findHeroFlagBitmap(hero, anim, color, group);
}
std::shared_ptr<IImage> CMapHandler::CMapBlitter::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
std::shared_ptr<IImage> CMapBlitter::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
{
return findFlagBitmapInternal(graphics->heroFlagAnimations.at(color->getNum()), anim, group, hero->moveDir, !hero->isStanding);
}
std::shared_ptr<IImage> CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int group, ui8 dir) const
std::shared_ptr<IImage> CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int group, ui8 dir) const
{
int boatType = boat->subID;
if(boatType < 0 || boatType >= graphics->boatFlagAnimations.size())
@ -1031,7 +1031,7 @@ std::shared_ptr<IImage> CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoa
return findFlagBitmapInternal(subtypeFlags.at(colorIndex), anim, group, dir, false);
}
std::shared_ptr<IImage> CMapHandler::CMapBlitter::findFlagBitmapInternal(std::shared_ptr<CAnimation> animation, int anim, int group, ui8 dir, bool moving) const
std::shared_ptr<IImage> CMapBlitter::findFlagBitmapInternal(std::shared_ptr<CAnimation> animation, int anim, int group, ui8 dir, bool moving) const
{
size_t groupSize = animation->size(group);
if(groupSize == 0)
@ -1043,10 +1043,10 @@ std::shared_ptr<IImage> CMapHandler::CMapBlitter::findFlagBitmapInternal(std::sh
return animation->getImage((anim / 4) % groupSize, group);
}
CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findObjectBitmap(const CGObjectInstance * obj, int anim) const
AnimBitmapHolder CMapBlitter::findObjectBitmap(const CGObjectInstance * obj, int anim) const
{
if (!obj)
return CMapHandler::AnimBitmapHolder();
return AnimBitmapHolder();
if (obj->ID == Obj::HERO)
return findHeroBitmap(static_cast<const CGHeroInstance*>(obj), anim);
if (obj->ID == Obj::BOAT)
@ -1056,18 +1056,18 @@ CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findObjectBitmap(const C
std::shared_ptr<CAnimation> animation = graphics->getAnimation(obj);
size_t groupSize = animation->size();
if(groupSize == 0)
return CMapHandler::AnimBitmapHolder();
return AnimBitmapHolder();
auto bitmap = animation->getImage((anim + getPhaseShift(obj)) % groupSize);
if(!bitmap)
return CMapHandler::AnimBitmapHolder();
return AnimBitmapHolder();
bitmap->setFlagColor(obj->tempOwner);
return CMapHandler::AnimBitmapHolder(bitmap);
return AnimBitmapHolder(bitmap);
}
ui8 CMapHandler::CMapBlitter::getPhaseShift(const CGObjectInstance *object) const
ui8 CMapBlitter::getPhaseShift(const CGObjectInstance *object) const
{
auto i = parent->animationPhase.find(object);
if(i == parent->animationPhase.end())
@ -1080,13 +1080,13 @@ ui8 CMapHandler::CMapBlitter::getPhaseShift(const CGObjectInstance *object) cons
return i->second;
}
bool CMapHandler::CMapBlitter::canDrawObject(const CGObjectInstance * obj) const
bool CMapBlitter::canDrawObject(const CGObjectInstance * obj) const
{
//checking if object has non-empty graphic on this tile
return obj->ID == Obj::HERO || obj->coveringAt(pos.x, pos.y);
}
bool CMapHandler::CMapBlitter::canDrawCurrentTile() const
bool CMapBlitter::canDrawCurrentTile() const
{
if(settings["session"]["spectate"].Bool())
return true;
@ -1095,7 +1095,7 @@ bool CMapHandler::CMapBlitter::canDrawCurrentTile() const
return !neighbors.areAllHidden();
}
ui8 CMapHandler::CMapBlitter::getHeroFrameGroup(ui8 dir, bool isMoving) const
ui8 CMapBlitter::getHeroFrameGroup(ui8 dir, bool isMoving) const
{
if(isMoving)
{
@ -1403,26 +1403,26 @@ void CMapHandler::discardWorldViewCache()
cache.discardWorldViewCache();
}
CMapHandler::CMapCache::CMapCache()
CMapCache::CMapCache()
{
worldViewCachedScale = 0;
}
void CMapHandler::CMapCache::discardWorldViewCache()
void CMapCache::discardWorldViewCache()
{
for(auto & cache : data)
cache.clear();
logAnim->debug("Discarded world view cache");
}
void CMapHandler::CMapCache::updateWorldViewScale(float scale)
void CMapCache::updateWorldViewScale(float scale)
{
if (fabs(scale - worldViewCachedScale) > 0.001f)
discardWorldViewCache();
worldViewCachedScale = scale;
}
std::shared_ptr<IImage> CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CMapHandler::EMapCacheType type, std::shared_ptr<IImage> fullSurface)
std::shared_ptr<IImage> CMapCache::requestWorldViewCacheOrCreate(EMapCacheType type, std::shared_ptr<IImage> fullSurface)
{
intptr_t key = (intptr_t) (fullSurface.get());
auto & cache = data[(ui8)type];

View File

@ -37,6 +37,7 @@ struct SDL_Surface;
class CAnimation;
class IImage;
class CFadeAnimation;
class CMapHandler;
enum class EWorldViewIcon
{
@ -161,163 +162,168 @@ private:
int offset;
std::vector<T> inver;
};
enum class EMapCacheType : ui8
{
TERRAIN, OBJECTS, ROADS, RIVERS, FOW, HEROES, HERO_FLAGS, FRAME, AFTER_LAST
};
/// temporarily caches rescaled frames for map world view redrawing
class CMapCache
{
std::array< std::map<intptr_t, std::shared_ptr<IImage>>, (ui8)EMapCacheType::AFTER_LAST> data;
float worldViewCachedScale;
public:
CMapCache();
/// destroys all cached data (frees surfaces)
void discardWorldViewCache();
/// updates scale and determines if currently cached data is still valid
void updateWorldViewScale(float scale);
/// asks for cached data; @returns cached data if found, new scaled surface otherwise, may return nullptr in case of scaling error
std::shared_ptr<IImage> requestWorldViewCacheOrCreate(EMapCacheType type, std::shared_ptr<IImage> fullSurface);
};
/// helper struct to pass around resolved bitmaps of an object; images can be nullptr if object doesn't have bitmap of that type
struct AnimBitmapHolder
{
std::shared_ptr<IImage> objBitmap; // main object bitmap
std::shared_ptr<IImage> flagBitmap; // flag bitmap for the object (probably only for heroes and boats with heroes)
bool isMoving; // indicates if the object is moving (again, heroes/boats only)
AnimBitmapHolder(std::shared_ptr<IImage> objBitmap_ = nullptr, std::shared_ptr<IImage> flagBitmap_ = nullptr, bool moving = false)
: objBitmap(objBitmap_),
flagBitmap(flagBitmap_),
isMoving(moving)
{}
};
class CMapBlitter
{
protected:
const int FRAMES_PER_MOVE_ANIM_GROUP = 8;
CMapHandler * parent; // ptr to enclosing map handler; generally for legacy reasons, probably could/should be refactored out of here
int tileSize; // size of a tile drawn on map [in pixels]
int halfTileSizeCeil; // half of the tile size, rounded up
int3 tileCount; // number of tiles in current viewport
int3 topTile; // top-left tile of the viewport
int3 initPos; // starting drawing position [in pixels]
int3 pos; // current position [in tiles]
int3 realPos; // current position [in pixels]
Rect realTileRect; // default rect based on current pos: [realPos.x, realPos.y, tileSize, tileSize]
Rect defaultTileRect; // default rect based on 0: [0, 0, tileSize, tileSize]
const MapDrawingInfo * info; // data for drawing passed from outside
/// general drawing method, called internally by more specialized ones
virtual void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const = 0;
// first drawing pass
/// draws terrain bitmap (or custom bitmap if applicable) on current tile
virtual void drawTileTerrain(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile2 & tile) const;
/// draws a river segment on current tile
virtual void drawRiver(SDL_Surface * targetSurf, const TerrainTile & tinfo) const;
/// draws a road segment on current tile
virtual void drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const;
/// draws all objects on current tile (higher-level logic, unlike other draw*** methods)
virtual void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const;
virtual void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const;
virtual void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const;
// second drawing pass
/// current tile: draws overlay over the map, used to draw world view icons
virtual void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const = 0;
/// draws fog of war on current tile
virtual void drawFow(SDL_Surface * targetSurf) const;
/// draws map border frame on current position
virtual void drawFrame(SDL_Surface * targetSurf) const;
/// draws additional icons (for VIEW_AIR, VIEW_EARTH spells atm)
virtual void drawOverlayEx(SDL_Surface * targetSurf);
// third drawing pass
/// custom post-processing, if needed (used by puzzle view)
virtual void postProcessing(SDL_Surface * targetSurf) const {}
// misc methods
/// initializes frame-drawing (called at the start of every redraw)
virtual void init(const MapDrawingInfo * drawingInfo) = 0;
/// calculates clip region for map viewport
virtual Rect clip(SDL_Surface * targetSurf) const = 0;
virtual ui8 getHeroFrameGroup(ui8 dir, bool isMoving) const;
virtual ui8 getPhaseShift(const CGObjectInstance *object) const;
virtual bool canDrawObject(const CGObjectInstance * obj) const;
virtual bool canDrawCurrentTile() const;
// internal helper methods to choose correct bitmap(s) for object; called internally by findObjectBitmap
AnimBitmapHolder findHeroBitmap(const CGHeroInstance * hero, int anim) const;
AnimBitmapHolder findBoatBitmap(const CGBoat * hero, int anim) const;
std::shared_ptr<IImage> findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
std::shared_ptr<IImage> findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
std::shared_ptr<IImage> findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int group, ui8 dir) const;
std::shared_ptr<IImage> findFlagBitmapInternal(std::shared_ptr<CAnimation> animation, int anim, int group, ui8 dir, bool moving) const;
public:
CMapBlitter(CMapHandler * p);
virtual ~CMapBlitter();
void blit(SDL_Surface * targetSurf, const MapDrawingInfo * info);
/// helper method that chooses correct bitmap(s) for given object
AnimBitmapHolder findObjectBitmap(const CGObjectInstance * obj, int anim) const;
};
class CMapNormalBlitter : public CMapBlitter
{
protected:
void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const override;
void drawTileOverlay(SDL_Surface * targetSurf,const TerrainTile2 & tile) const override {}
void init(const MapDrawingInfo * info) override;
Rect clip(SDL_Surface * targetSurf) const override;
public:
CMapNormalBlitter(CMapHandler * parent);
virtual ~CMapNormalBlitter(){}
};
class CMapWorldViewBlitter : public CMapBlitter
{
private:
std::shared_ptr<IImage> objectToIcon(Obj id, si32 subId, PlayerColor owner) const;
protected:
void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const override;
void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override;
void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const override;
void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const override;
void drawFrame(SDL_Surface * targetSurf) const override {}
void drawOverlayEx(SDL_Surface * targetSurf) override;
void init(const MapDrawingInfo * info) override;
Rect clip(SDL_Surface * targetSurf) const override;
ui8 getPhaseShift(const CGObjectInstance *object) const override { return 0u; }
void calculateWorldViewCameraPos();
public:
CMapWorldViewBlitter(CMapHandler * parent);
virtual ~CMapWorldViewBlitter(){}
};
class CMapPuzzleViewBlitter : public CMapNormalBlitter
{
std::vector<int> unblittableObjects;
void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override;
void drawFow(SDL_Surface * targetSurf) const override {} // skipping FoW in puzzle view
void postProcessing(SDL_Surface * targetSurf) const override;
bool canDrawObject(const CGObjectInstance * obj) const override;
bool canDrawCurrentTile() const override { return true; }
public:
CMapPuzzleViewBlitter(CMapHandler * parent);
};
class CMapHandler
{
enum class EMapCacheType : ui8
{
TERRAIN, OBJECTS, ROADS, RIVERS, FOW, HEROES, HERO_FLAGS, FRAME, AFTER_LAST
};
/// temporarily caches rescaled frames for map world view redrawing
class CMapCache
{
std::array< std::map<intptr_t, std::shared_ptr<IImage>>, (ui8)EMapCacheType::AFTER_LAST> data;
float worldViewCachedScale;
public:
CMapCache();
/// destroys all cached data (frees surfaces)
void discardWorldViewCache();
/// updates scale and determines if currently cached data is still valid
void updateWorldViewScale(float scale);
/// asks for cached data; @returns cached data if found, new scaled surface otherwise, may return nullptr in case of scaling error
std::shared_ptr<IImage> requestWorldViewCacheOrCreate(EMapCacheType type, std::shared_ptr<IImage> fullSurface);
};
/// helper struct to pass around resolved bitmaps of an object; images can be nullptr if object doesn't have bitmap of that type
struct AnimBitmapHolder
{
std::shared_ptr<IImage> objBitmap; // main object bitmap
std::shared_ptr<IImage> flagBitmap; // flag bitmap for the object (probably only for heroes and boats with heroes)
bool isMoving; // indicates if the object is moving (again, heroes/boats only)
AnimBitmapHolder(std::shared_ptr<IImage> objBitmap_ = nullptr, std::shared_ptr<IImage> flagBitmap_ = nullptr, bool moving = false)
: objBitmap(objBitmap_),
flagBitmap(flagBitmap_),
isMoving(moving)
{}
};
class CMapBlitter
{
protected:
const int FRAMES_PER_MOVE_ANIM_GROUP = 8;
CMapHandler * parent; // ptr to enclosing map handler; generally for legacy reasons, probably could/should be refactored out of here
int tileSize; // size of a tile drawn on map [in pixels]
int halfTileSizeCeil; // half of the tile size, rounded up
int3 tileCount; // number of tiles in current viewport
int3 topTile; // top-left tile of the viewport
int3 initPos; // starting drawing position [in pixels]
int3 pos; // current position [in tiles]
int3 realPos; // current position [in pixels]
Rect realTileRect; // default rect based on current pos: [realPos.x, realPos.y, tileSize, tileSize]
Rect defaultTileRect; // default rect based on 0: [0, 0, tileSize, tileSize]
const MapDrawingInfo * info; // data for drawing passed from outside
/// general drawing method, called internally by more specialized ones
virtual void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const = 0;
// first drawing pass
/// draws terrain bitmap (or custom bitmap if applicable) on current tile
virtual void drawTileTerrain(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile2 & tile) const;
/// draws a river segment on current tile
virtual void drawRiver(SDL_Surface * targetSurf, const TerrainTile & tinfo) const;
/// draws a road segment on current tile
virtual void drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const;
/// draws all objects on current tile (higher-level logic, unlike other draw*** methods)
virtual void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const;
virtual void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const;
virtual void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const;
// second drawing pass
/// current tile: draws overlay over the map, used to draw world view icons
virtual void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const = 0;
/// draws fog of war on current tile
virtual void drawFow(SDL_Surface * targetSurf) const;
/// draws map border frame on current position
virtual void drawFrame(SDL_Surface * targetSurf) const;
/// draws additional icons (for VIEW_AIR, VIEW_EARTH spells atm)
virtual void drawOverlayEx(SDL_Surface * targetSurf);
// third drawing pass
/// custom post-processing, if needed (used by puzzle view)
virtual void postProcessing(SDL_Surface * targetSurf) const {}
// misc methods
/// initializes frame-drawing (called at the start of every redraw)
virtual void init(const MapDrawingInfo * drawingInfo) = 0;
/// calculates clip region for map viewport
virtual Rect clip(SDL_Surface * targetSurf) const = 0;
virtual ui8 getHeroFrameGroup(ui8 dir, bool isMoving) const;
virtual ui8 getPhaseShift(const CGObjectInstance *object) const;
virtual bool canDrawObject(const CGObjectInstance * obj) const;
virtual bool canDrawCurrentTile() const;
// internal helper methods to choose correct bitmap(s) for object; called internally by findObjectBitmap
AnimBitmapHolder findHeroBitmap(const CGHeroInstance * hero, int anim) const;
AnimBitmapHolder findBoatBitmap(const CGBoat * hero, int anim) const;
std::shared_ptr<IImage> findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
std::shared_ptr<IImage> findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
std::shared_ptr<IImage> findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int group, ui8 dir) const;
std::shared_ptr<IImage> findFlagBitmapInternal(std::shared_ptr<CAnimation> animation, int anim, int group, ui8 dir, bool moving) const;
public:
CMapBlitter(CMapHandler * p);
virtual ~CMapBlitter();
void blit(SDL_Surface * targetSurf, const MapDrawingInfo * info);
/// helper method that chooses correct bitmap(s) for given object
AnimBitmapHolder findObjectBitmap(const CGObjectInstance * obj, int anim) const;
};
class CMapNormalBlitter : public CMapBlitter
{
protected:
void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const override;
void drawTileOverlay(SDL_Surface * targetSurf,const TerrainTile2 & tile) const override {}
void init(const MapDrawingInfo * info) override;
Rect clip(SDL_Surface * targetSurf) const override;
public:
CMapNormalBlitter(CMapHandler * parent);
virtual ~CMapNormalBlitter(){}
};
class CMapWorldViewBlitter : public CMapBlitter
{
private:
std::shared_ptr<IImage> objectToIcon(Obj id, si32 subId, PlayerColor owner) const;
protected:
void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, Rect * sourceRect, SDL_Surface * targetSurf, Rect * destRect) const override;
void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override;
void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, Rect * destRect, bool moving) const override;
void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, Rect * sourceRect, bool moving) const override;
void drawFrame(SDL_Surface * targetSurf) const override {}
void drawOverlayEx(SDL_Surface * targetSurf) override;
void init(const MapDrawingInfo * info) override;
Rect clip(SDL_Surface * targetSurf) const override;
ui8 getPhaseShift(const CGObjectInstance *object) const override { return 0u; }
void calculateWorldViewCameraPos();
public:
CMapWorldViewBlitter(CMapHandler * parent);
virtual ~CMapWorldViewBlitter(){}
};
class CMapPuzzleViewBlitter : public CMapNormalBlitter
{
std::vector<int> unblittableObjects;
void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override;
void drawFow(SDL_Surface * targetSurf) const override {} // skipping FoW in puzzle view
void postProcessing(SDL_Surface * targetSurf) const override;
bool canDrawObject(const CGObjectInstance * obj) const override;
bool canDrawCurrentTile() const override { return true; }
public:
CMapPuzzleViewBlitter(CMapHandler * parent);
};
friend class CMapBlitter;
friend class CMapNormalBlitter;
friend class CMapWorldViewBlitter;
CMapCache cache;
CMapBlitter * normalBlitter;
@ -335,7 +341,8 @@ class CMapHandler
void initBorderGraphics();
void initTerrainGraphics();
void prepareFOWDefs();
public:
public: //TODO: make private
boost::multi_array<TerrainTile2, 3> ttiles; //informations about map tiles [z][x][y]
int3 sizes; //map size (x = width, y = height, z = number of levels)
const CMap * map;
@ -356,7 +363,7 @@ public:
int offsetY;
//terrain graphics
private:
//FIXME: unique_ptr should be enough, but fails to compile in MSVS 2013
typedef std::map<std::string, std::array<std::shared_ptr<CAnimation>, 4>> TFlippedAnimations; //[type, rotation]
typedef std::map<std::string, std::vector<std::array<std::shared_ptr<IImage>, 4>>> TFlippedCache;//[type, view type, rotation]
@ -383,6 +390,7 @@ public:
mutable std::map<const CGObjectInstance*, ui8> animationPhase;
public:
CMapHandler();
~CMapHandler();

View File

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

View File

@ -23,14 +23,14 @@ Canvas::Canvas(SDL_Surface * surface):
surface->refcount++;
}
Canvas::Canvas(Canvas & other):
Canvas::Canvas(const Canvas & other):
surface(other.surface),
renderOffset(other.renderOffset)
{
surface->refcount++;
}
Canvas::Canvas(Canvas & other, const Rect & newClipRect):
Canvas::Canvas(const Canvas & other, const Rect & newClipRect):
Canvas(other)
{
clipRect.emplace();
@ -43,9 +43,9 @@ Canvas::Canvas(Canvas & other, const Rect & newClipRect):
}
Canvas::Canvas(const Point & size):
renderOffset(0,0)
renderOffset(0,0),
surface(CSDL_Ext::newSurface(size.x, size.y))
{
surface = CSDL_Ext::newSurface(size.x, size.y);
}
Canvas::~Canvas()
@ -75,9 +75,35 @@ void Canvas::draw(Canvas & image, const Point & pos)
CSDL_Ext::blitAt(image.surface, renderOffset.x + pos.x, renderOffset.y + pos.y, surface);
}
void Canvas::draw(Canvas & image, const Point & pos, const Point & targetSize)
{
SDL_Rect targetRect = CSDL_Ext::toSDL(Rect(pos, targetSize));
SDL_BlitScaled(image.surface, nullptr, surface, &targetRect );
}
void Canvas::drawPoint(const Point & dest, const ColorRGBA & color)
{
CSDL_Ext::putPixelWithoutRefreshIfInSurf(surface, dest.x, dest.y, color.r, color.g, color.b, color.a);
}
void Canvas::drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest)
{
CSDL_Ext::drawLine(surface, renderOffset.x + from.x, renderOffset.y + from.y, renderOffset.x + dest.x, renderOffset.y + dest.y, CSDL_Ext::toSDL(colorFrom), CSDL_Ext::toSDL(colorDest));
CSDL_Ext::drawLine(surface, renderOffset + from, renderOffset + dest, CSDL_Ext::toSDL(colorFrom), CSDL_Ext::toSDL(colorDest));
}
void Canvas::drawLineDashed(const Point & from, const Point & dest, const ColorRGBA & color)
{
CSDL_Ext::drawLineDashed(surface, renderOffset + from, renderOffset + dest, CSDL_Ext::toSDL(color));
}
void Canvas::drawBorderDashed(const Rect & target, const ColorRGBA & color)
{
Rect realTarget = target + renderOffset;
CSDL_Ext::drawLineDashed(surface, realTarget.topLeft(), realTarget.topRight(), CSDL_Ext::toSDL(color));
CSDL_Ext::drawLineDashed(surface, realTarget.bottomLeft(), realTarget.bottomRight(), CSDL_Ext::toSDL(color));
CSDL_Ext::drawLineDashed(surface, realTarget.topLeft(), realTarget.bottomLeft(), CSDL_Ext::toSDL(color));
CSDL_Ext::drawLineDashed(surface, realTarget.topRight(), realTarget.bottomRight(), CSDL_Ext::toSDL(color));
}
void Canvas::drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text )

View File

@ -34,16 +34,16 @@ class Canvas
public:
/// constructs canvas using existing surface. Caller maintains ownership on the surface
Canvas(SDL_Surface * surface);
explicit Canvas(SDL_Surface * surface);
/// copy contructor
Canvas(Canvas & other);
Canvas(const Canvas & other);
/// creates canvas that only covers specified subsection of a surface
Canvas(Canvas & other, const Rect & clipRect);
Canvas(const Canvas & other, const Rect & clipRect);
/// constructs canvas of specified size
Canvas(const Point & size);
explicit Canvas(const Point & size);
~Canvas();
@ -56,9 +56,21 @@ public:
/// renders another canvas onto this canvas
void draw(Canvas & image, const Point & pos);
/// renders another canvas onto this canvas with scaling
void draw(Canvas & image, const Point & pos, const Point & targetSize);
/// renders single pixels with specified color
void drawPoint(const Point & dest, const ColorRGBA & color);
/// renders continuous, 1-pixel wide line with color gradient
void drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest);
/// renders dashed, 1-pixel wide line with specified color
void drawLineDashed(const Point & from, const Point & dest, const ColorRGBA & color);
/// renders rectangular, dashed border in specified location
void drawBorderDashed(const Rect & target, const ColorRGBA & color);
/// renders single line of text with specified parameters
void drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text );

View File

@ -364,11 +364,40 @@ uint32_t CSDL_Ext::colorTouint32_t(const SDL_Color * color)
return ret;
}
static void drawLineX(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2)
static void drawLineXDashed(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color)
{
double length(x2 - x1);
for(int x = x1; x <= x2; x++)
{
float f = float(x - x1) / float(x2 - x1);
double f = (x - x1) / length;
int y = vstd::lerp(y1, y2, f);
if (std::abs(x - x1) % 5 != 4)
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y, color.r, color.g, color.b);
}
}
static void drawLineYDashed(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color)
{
double length(y2 - y1);
for(int y = y1; y <= y2; y++)
{
double f = (y - y1) / length;
int x = vstd::lerp(x1, x2, f);
if (std::abs(y - y1) % 5 != 4)
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y, color.r, color.g, color.b);
}
}
static void drawLineX(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2)
{
double length(x2 - x1);
for(int x = x1; x <= x2; x++)
{
double f = (x - x1) / length;
int y = vstd::lerp(y1, y2, f);
uint8_t r = vstd::lerp(color1.r, color2.r, f);
@ -383,9 +412,10 @@ static void drawLineX(SDL_Surface * sur, int x1, int y1, int x2, int y2, const S
static void drawLineY(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2)
{
double length(y2 - y1);
for(int y = y1; y <= y2; y++)
{
float f = float(y - y1) / float(y2 - y1);
double f = (y - y1) / length;
int x = vstd::lerp(x1, x2, f);
uint8_t r = vstd::lerp(color1.r, color2.r, f);
@ -398,31 +428,60 @@ static void drawLineY(SDL_Surface * sur, int x1, int y1, int x2, int y2, const S
}
}
void CSDL_Ext::drawLine(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2)
void CSDL_Ext::drawLine(SDL_Surface * sur, const Point & from, const Point & dest, const SDL_Color & color1, const SDL_Color & color2)
{
int width = std::abs(x1-x2);
int height = std::abs(y1-y2);
//FIXME: duplicated code with drawLineDashed
int width = std::abs(from.x - dest.x);
int height = std::abs(from.y - dest.y);
if ( width == 0 && height == 0)
{
uint8_t *p = CSDL_Ext::getPxPtr(sur, x1, y1);
uint8_t *p = CSDL_Ext::getPxPtr(sur, from.x, from.y);
ColorPutter<4, 0>::PutColorAlpha(p, color1);
return;
}
if (width > height)
{
if ( x1 < x2)
drawLineX(sur, x1,y1,x2,y2, color1, color2);
if ( from.x < dest.x)
drawLineX(sur, from.x, from.y, dest.x, dest.y, color1, color2);
else
drawLineX(sur, x2,y2,x1,y1, color2, color1);
drawLineX(sur, dest.x, dest.y, from.x, from.y, color2, color1);
}
else
{
if ( y1 < y2)
drawLineY(sur, x1,y1,x2,y2, color1, color2);
if ( from.y < dest.y)
drawLineY(sur, from.x, from.y, dest.x, dest.y, color1, color2);
else
drawLineY(sur, x2,y2,x1,y1, color2, color1);
drawLineY(sur, dest.x, dest.y, from.x, from.y, color2, color1);
}
}
void CSDL_Ext::drawLineDashed(SDL_Surface * sur, const Point & from, const Point & dest, const SDL_Color & color)
{
//FIXME: duplicated code with drawLine
int width = std::abs(from.x - dest.x);
int height = std::abs(from.y - dest.y);
if ( width == 0 && height == 0)
{
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, from.x, from.y, color.r, color.g, color.b);
return;
}
if (width > height)
{
if ( from.x < dest.x)
drawLineXDashed(sur, from.x, from.y, dest.x, dest.y, color);
else
drawLineXDashed(sur, dest.x, dest.y, from.x, from.y, color);
}
else
{
if ( from.y < dest.y)
drawLineYDashed(sur, from.x, from.y, dest.x, dest.y, color);
else
drawLineYDashed(sur, dest.x, dest.y, from.x, from.y, color);
}
}
@ -449,31 +508,6 @@ void CSDL_Ext::drawBorder( SDL_Surface * sur, const Rect &r, const SDL_Color &co
drawBorder(sur, r.x, r.y, r.w, r.h, color, depth);
}
void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color)
{
const int y1 = r.y, y2 = r.y + r.h-1;
for (int i=0; i<r.w; i++)
{
const int x = r.x + i;
if (i%4 || (i==0))
{
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y1, color.r, color.g, color.b);
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y2, color.r, color.g, color.b);
}
}
const int x1 = r.x, x2 = r.x + r.w-1;
for (int i=0; i<r.h; i++)
{
const int y = r.y + i;
if ((i%4) || (i==0))
{
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x1, y, color.r, color.g, color.b);
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x2, y, color.r, color.g, color.b);
}
}
}
void CSDL_Ext::setPlayerColor(SDL_Surface * sur, PlayerColor player)
{
if(player==PlayerColor::UNFLAGGABLE)

View File

@ -81,10 +81,11 @@ typedef void (*TColorPutterAlpha)(uint8_t *&ptr, const uint8_t & R, const uint8_
uint32_t colorTouint32_t(const SDL_Color * color); //little endian only
SDL_Color makeColor(ui8 r, ui8 g, ui8 b, ui8 a);
void drawLine(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2);
void drawLine(SDL_Surface * sur, const Point & from, const Point & dest, const SDL_Color & color1, const SDL_Color & color2);
void drawLineDashed(SDL_Surface * sur, const Point & from, const Point & dest, const SDL_Color & color);
void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color &color, int depth = 1);
void drawBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color, int depth = 1);
void drawDashedBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color);
void setPlayerColor(SDL_Surface * sur, PlayerColor player); //sets correct color of flags; -1 for neutral
SDL_Surface * newSurface(int w, int h, SDL_Surface * mod); //creates new surface, with flags/format same as in surface given

View File

@ -20,8 +20,8 @@
#include "../gui/CursorHandler.h"
#include "../gui/TextAlignment.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../windows/CMessage.h"
#include "../windows/InfoWindows.h"
#include "../widgets/TextControls.h"
#include "../CGameInfo.h"
@ -250,8 +250,8 @@ void CComponent::setSurface(std::string defName, int imgPos)
void CComponent::clickRight(tribool down, bool previousState)
{
if(!getDescription().empty())
adventureInt->handleRightClick(getDescription(), down);
if(down && !getDescription().empty())
CRClickPopup::createAndPush(getDescription());
}
void CSelectableComponent::clickLeft(tribool down, bool previousState)

View File

@ -21,7 +21,6 @@
#include "../windows/CCastleInterface.h"
#include "../windows/InfoWindows.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../../CCallback.h"
@ -57,8 +56,8 @@ void LRClickableAreaWText::clickLeft(tribool down, bool previousState)
}
void LRClickableAreaWText::clickRight(tribool down, bool previousState)
{
if (!text.empty())
adventureInt->handleRightClick(text, down);
if (down && !text.empty())
CRClickPopup::createAndPush(text);
}
LRClickableAreaWText::LRClickableAreaWText()

View File

@ -28,6 +28,8 @@
#include "../render/IImage.h"
#include "../render/ColorFilter.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../adventureMap/CList.h"
#include "../adventureMap/CResDataBar.h"
#include "../../CCallback.h"
#include "../../lib/CArtHandler.h"

View File

@ -15,12 +15,13 @@
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../adventureMap/CResDataBar.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/CComponent.h"
#include "../widgets/TextControls.h"
#include "../widgets/MiscWidgets.h"
#include "../widgets/Buttons.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../widgets/ObjectLists.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../../CCallback.h"
@ -95,7 +96,7 @@ void InfoBox::clickRight(tribool down, bool previousState)
if (comp)
CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp));
else if (!text.empty())
adventureInt->handleRightClick(text, down);
CRClickPopup::createAndPush(text);
}
}

View File

@ -82,13 +82,11 @@ void CQuestMinimap::addQuestMarks (const QuestInfo * q)
else
tile = q->tile;
int x,y;
minimap->tileToPixels (tile, x, y);
Point offset = tileToPixels(tile);
if (level != tile.z)
setLevel(tile.z);
setLevel(tile.z);
auto pic = std::make_shared<CQuestIcon>("VwSymbol.def", 3, x, y);
auto pic = std::make_shared<CQuestIcon>("VwSymbol.def", 3, offset.x, offset.y);
pic->moveBy (Point ( -pic->pos.w/2, -pic->pos.h/2));
pic->callback = std::bind (&CQuestMinimap::iconClicked, this);

View File

@ -57,7 +57,8 @@ void CSpellWindow::InteractiveArea::clickLeft(tribool down, bool previousState)
void CSpellWindow::InteractiveArea::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(helpText, down);
if (down)
CRClickPopup::createAndPush(helpText);
}
void CSpellWindow::InteractiveArea::hover(bool on)

View File

@ -13,11 +13,11 @@
#include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h"
#include "../widgets/Images.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../gui/TextAlignment.h"
#include "../widgets/Buttons.h"
#include "../widgets/TextControls.h"
#include "../windows/InfoWindows.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
@ -272,7 +272,7 @@ void CTradeWindow::CTradeableItem::clickRight(tribool down, bool previousState)
case ARTIFACT_PLACEHOLDER:
//TODO: it's would be better for market to contain actual CArtifactInstance and not just ids of certain artifact type so we can use getEffectiveDescription.
if(id >= 0)
adventureInt->handleRightClick(CGI->artifacts()->getByIndex(id)->getDescriptionTranslated(), down);
CRClickPopup::createAndPush(CGI->artifacts()->getByIndex(id)->getDescriptionTranslated());
break;
}
}

View File

@ -2135,9 +2135,10 @@ CObjectListWindow::CObjectListWindow(const std::vector<int> & _items, std::share
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
items.reserve(_items.size());
for(int id : _items)
{
items.push_back(std::make_pair(id, CGI->mh->map->objects[id]->getObjectName()));
items.push_back(std::make_pair(id, LOCPLINT->cb->getObjInstance(ObjectInstanceID(id))->getObjectName()));
}
init(titleWidget_, _title, _descr);

View File

@ -22,6 +22,7 @@
#include "../battle/BattleInterface.h"
#include "../battle/BattleInterfaceClasses.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../adventureMap/CTerrainRect.h"
#include "../windows/CMessage.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../gui/CursorHandler.h"
@ -364,8 +365,10 @@ CRClickPopupInt::~CRClickPopupInt()
Point CInfoBoxPopup::toScreen(Point p)
{
vstd::abetween(p.x, adventureInt->terrain.pos.x + 100, adventureInt->terrain.pos.x + adventureInt->terrain.pos.w - 100);
vstd::abetween(p.y, adventureInt->terrain.pos.y + 100, adventureInt->terrain.pos.y + adventureInt->terrain.pos.h - 100);
auto bounds = adventureInt->terrainAreaPixels();
vstd::abetween(p.x, bounds.top() + 100, bounds.bottom() - 100);
vstd::abetween(p.y, bounds.left() + 100, bounds.right() - 100);
return p;
}
@ -374,7 +377,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town)
: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
{
InfoAboutTown iah;
LOCPLINT->cb->getTownInfo(town, iah, adventureInt->selection); //todo: should this be nearest hero?
LOCPLINT->cb->getTownInfo(town, iah, adventureInt->curTown()); //todo: should this be nearest hero?
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
tooltip = std::make_shared<CTownTooltip>(Point(9, 10), iah);
@ -384,7 +387,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero)
: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position))
{
InfoAboutHero iah;
LOCPLINT->cb->getHeroInfo(hero, iah, adventureInt->selection);//todo: should this be nearest hero?
LOCPLINT->cb->getHeroInfo(hero, iah, adventureInt->curHero());//todo: should this be nearest hero?
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
tooltip = std::make_shared<CHeroTooltip>(Point(9, 10), iah);
@ -403,7 +406,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr)
std::shared_ptr<WindowBase> CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
{
if(nullptr == specific)
specific = adventureInt->selection;
specific = adventureInt->curArmy();
if(nullptr == specific)
{

View File

@ -127,6 +127,7 @@ public:
virtual void requestRealized(PackageApplied *pa){};
virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
virtual void objectRemoved(const CGObjectInstance *obj){}; //eg. collected resource, picked artifact, beaten hero
virtual void objectRemovedAfter(){}; //eg. collected resource, picked artifact, beaten hero
virtual void playerBlocked(int reason, bool start){}; //reason: 0 - upcoming battle
virtual void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) {}; //player lost or won the game
virtual void playerStartsTurn(PlayerColor player){};

View File

@ -2016,7 +2016,7 @@ void NewTurn::applyGs(CGameState *gs)
for(const auto & re : res)
{
assert(i->first < PlayerColor::PLAYER_LIMIT);
assert(re.first < PlayerColor::PLAYER_LIMIT);
gs->getPlayerState(re.first)->resources = re.second;
}