mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Basic version of hero movement on map. Removed old code.
This commit is contained in:
parent
d46687a9c8
commit
4501036a04
@ -480,10 +480,6 @@ int main(int argc, char * argv[])
|
||||
|
||||
CCS->curh = new CursorHandler();
|
||||
logGlobal->info("Screen handler: %d ms", pomtime.getDiff());
|
||||
pomtime.getDiff();
|
||||
|
||||
graphics->load();//must be after Content loading but should be in main thread
|
||||
logGlobal->info("Main graphics: %d ms", pomtime.getDiff());
|
||||
|
||||
CMessage::init();
|
||||
logGlobal->info("Message handler: %d ms", pomtime.getDiff());
|
||||
|
@ -103,11 +103,6 @@ std::shared_ptr<BattleInterface> CPlayerInterface::battleInt;
|
||||
enum EMoveState {STOP_MOVE, WAITING_MOVE, CONTINUE_MOVE, DURING_MOVE};
|
||||
CondSh<EMoveState> stillMoveHero(STOP_MOVE); //used during hero movement
|
||||
|
||||
static bool objectBlitOrderSorter(const TerrainTileObject & a, const TerrainTileObject & b)
|
||||
{
|
||||
return CMapHandler::compareObjectBlitOrder(a.obj, b.obj);
|
||||
}
|
||||
|
||||
struct HeroObjectRetriever : boost::static_visitor<const CGHeroInstance *>
|
||||
{
|
||||
const CGHeroInstance * operator()(const ConstTransitivePtr<CGHeroInstance> &h) const
|
||||
@ -396,21 +391,9 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
return;
|
||||
|
||||
const CGHeroInstance * hero = cb->getHero(details.id); //object representing this hero
|
||||
int3 hp = details.start;
|
||||
|
||||
if(!hero)
|
||||
{
|
||||
//AI hero left the visible area (we can't obtain info)
|
||||
//TODO very evil workaround -> retrieve pointer to hero so we could animate it
|
||||
// TODO -> we should not need full CGHeroInstance structure to display animation or it should not be handled by playerint (but by the client itself)
|
||||
const TerrainTile2 & tile = CGI->mh->ttiles[hp.z][hp.x - 1][hp.y];
|
||||
for(auto & elem : tile.objects)
|
||||
if(elem.obj && elem.obj->id == details.id)
|
||||
hero = dynamic_cast<const CGHeroInstance *>(elem.obj);
|
||||
|
||||
if(!hero) //still nothing...
|
||||
return;
|
||||
}
|
||||
if (!hero)
|
||||
return;
|
||||
|
||||
adventureInt->minimap->updateTile(hero->convertToVisitablePos(details.start));
|
||||
adventureInt->minimap->updateTile(hero->convertToVisitablePos(details.end));
|
||||
@ -474,60 +457,24 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
return;
|
||||
}
|
||||
|
||||
ui32 speed = 0;
|
||||
if(settings["session"]["spectate"].Bool())
|
||||
{
|
||||
if(!settings["session"]["spectate-hero-speed"].isNull())
|
||||
speed = static_cast<ui32>(settings["session"]["spectate-hero-speed"].Integer());
|
||||
}
|
||||
else if(makingTurn) // our turn, our hero moves
|
||||
speed = static_cast<ui32>(settings["adventure"]["heroSpeed"].Float());
|
||||
else
|
||||
speed = static_cast<ui32>(settings["adventure"]["enemySpeed"].Float());
|
||||
|
||||
if(speed == 0)
|
||||
{
|
||||
//FIXME: is this a proper solution?
|
||||
CGI->mh->hideObject(hero);
|
||||
CGI->mh->printObject(hero);
|
||||
return; // no animation
|
||||
}
|
||||
|
||||
adventureInt->centerOn(hero); //actualizing screen pos
|
||||
adventureInt->minimap->redraw();
|
||||
adventureInt->heroList->redraw();
|
||||
|
||||
initMovement(details, hero, hp);
|
||||
|
||||
auto waitFrame = [&]()
|
||||
{
|
||||
int frameNumber = GH.mainFPSmng->getFrameNumber();
|
||||
|
||||
auto unlockPim = vstd::makeUnlockGuard(*pim);
|
||||
while(frameNumber == GH.mainFPSmng->getFrameNumber())
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(5));
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
|
||||
};
|
||||
|
||||
//first initializing done
|
||||
|
||||
//main moving
|
||||
for(int i = 1; i < 32; i += 2 * speed)
|
||||
{
|
||||
movementPxStep(details, i, hp, hero);
|
||||
#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->requestRedrawMapOnNextFrame();
|
||||
#endif
|
||||
|
||||
//evil returns here ...
|
||||
//todo: get rid of it
|
||||
while (CGI->mh->hasActiveAnimations())
|
||||
waitFrame(); //for animation purposes
|
||||
}
|
||||
//main moving done
|
||||
|
||||
//finishing move
|
||||
finishMovement(details, hp, hero);
|
||||
hero->isStanding = true;
|
||||
|
||||
//move finished
|
||||
@ -570,6 +517,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
const_cast<CGHeroInstance *>(hero)->moveDir = dirLookup[posOffset.y][posOffset.x];
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -711,14 +659,12 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
|
||||
|
||||
if (town->garrisonHero) //wandering hero moved to the garrison
|
||||
{
|
||||
CGI->mh->hideObject(town->garrisonHero);
|
||||
if (town->garrisonHero->tempOwner == playerID && vstd::contains(wanderingHeroes,town->garrisonHero)) // our hero
|
||||
wanderingHeroes -= town->garrisonHero;
|
||||
}
|
||||
|
||||
if (town->visitingHero) //hero leaves garrison
|
||||
{
|
||||
CGI->mh->printObject(town->visitingHero);
|
||||
if (town->visitingHero->tempOwner == playerID && !vstd::contains(wanderingHeroes,town->visitingHero)) // our hero
|
||||
wanderingHeroes.push_back(town->visitingHero);
|
||||
}
|
||||
@ -1748,7 +1694,7 @@ int CPlayerInterface::getLastIndex( std::string namePrefix)
|
||||
return (--dates.end())->second; //return latest file number
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroInstance * ho, const int3 &hp )
|
||||
{
|
||||
auto subArr = (CGI->mh->ttiles)[hp.z];
|
||||
@ -1892,7 +1838,7 @@ void CPlayerInterface::finishMovement( const TryMoveHero &details, const int3 &h
|
||||
//recompute hero sprite positioning using hero's final position
|
||||
movementPxStep(details, 32, hp, ho);
|
||||
}
|
||||
|
||||
*/
|
||||
void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult )
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -2510,9 +2456,6 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
// (i == 0) means hero went through all the path
|
||||
adventureInt->updateMoveHero(h, (i != 0));
|
||||
adventureInt->updateNextHero(h);
|
||||
|
||||
// ugly workaround to force instant update of adventure map
|
||||
adventureInt->animValHitCount = 8;
|
||||
}
|
||||
|
||||
setMovementStatus(false);
|
||||
@ -2558,13 +2501,10 @@ void CPlayerInterface::updateAmbientSounds(bool resetAll)
|
||||
{
|
||||
int dist = pos.dist(tile, int3::DIST_CHEBYSHEV);
|
||||
// We want sound for every special terrain on tile and not just one on top
|
||||
for(auto & ttObj : CGI->mh->ttiles[tile.z][tile.x][tile.y].objects)
|
||||
{
|
||||
if(ttObj.ambientSound)
|
||||
updateSounds(ttObj.ambientSound.get(), dist);
|
||||
}
|
||||
if(CGI->mh->map->isCoastalTile(tile))
|
||||
updateSounds("LOOPOCEA", dist);
|
||||
|
||||
for(auto & soundName : CGI->mh->getAmbientSounds(tile))
|
||||
updateSounds(soundName, dist);
|
||||
|
||||
}
|
||||
CCS->soundh->ambientUpdateChannels(currentSounds);
|
||||
}
|
||||
|
@ -256,9 +256,6 @@ public:
|
||||
|
||||
void stopMovement();
|
||||
void moveHero(const CGHeroInstance *h, const CGPath& path);
|
||||
void initMovement(const TryMoveHero &details, const CGHeroInstance * ho, const int3 &hp );//initializing objects and performing first step of move
|
||||
void movementPxStep( const TryMoveHero &details, int i, const int3 &hp, const CGHeroInstance * ho );//performing step of movement
|
||||
void finishMovement( const TryMoveHero &details, const int3 &hp, const CGHeroInstance * ho ); //finish movement
|
||||
|
||||
void acceptTurn(); //used during hot seat after your turn message is close
|
||||
void tryDiggging(const CGHeroInstance *h);
|
||||
|
@ -404,11 +404,8 @@ void CClient::initMapHandler()
|
||||
// During loading CPlayerInterface from serialized state it's depend on MH
|
||||
if(!settings["session"]["headless"].Bool())
|
||||
{
|
||||
const_cast<CGameInfo *>(CGI)->mh = new CMapHandler();
|
||||
CGI->mh->map = gs->map;
|
||||
const_cast<CGameInfo *>(CGI)->mh = new CMapHandler(gs->map);
|
||||
logNetwork->trace("Creating mapHandler: %d ms", CSH->th->getDiff());
|
||||
CGI->mh->init();
|
||||
logNetwork->trace("Initializing mapHandler (together): %d ms", CSH->th->getDiff());
|
||||
}
|
||||
|
||||
pathCache.clear();
|
||||
|
@ -229,7 +229,7 @@ public:
|
||||
void setMovePoints(SetMovePoints * smp) override {};
|
||||
void setManaPoints(ObjectInstanceID hid, int val) override {};
|
||||
void giveHero(ObjectInstanceID id, PlayerColor player) override {};
|
||||
void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags) override {};
|
||||
void changeObjPos(ObjectInstanceID objid, int3 newPos) override {};
|
||||
void sendAndApply(CPackForClient * pack) override {};
|
||||
void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override {};
|
||||
|
||||
|
@ -342,14 +342,14 @@ void ApplyClientNetPackVisitor::visitGiveBonus(GiveBonus & pack)
|
||||
void ApplyFirstClientNetPackVisitor::visitChangeObjPos(ChangeObjPos & pack)
|
||||
{
|
||||
CGObjectInstance *obj = gs.getObjInstance(pack.objid);
|
||||
if(pack.flags & 1 && CGI->mh)
|
||||
CGI->mh->hideObject(obj);
|
||||
if(CGI->mh)
|
||||
CGI->mh->onObjectFadeOut(obj);
|
||||
}
|
||||
void ApplyClientNetPackVisitor::visitChangeObjPos(ChangeObjPos & pack)
|
||||
{
|
||||
CGObjectInstance *obj = gs.getObjInstance(pack.objid);
|
||||
if(pack.flags & 1 && CGI->mh)
|
||||
CGI->mh->printObject(obj);
|
||||
if(CGI->mh)
|
||||
CGI->mh->onObjectFadeIn(obj);
|
||||
|
||||
cl.invalidatePaths();
|
||||
}
|
||||
@ -416,7 +416,7 @@ void ApplyFirstClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
|
||||
const CGObjectInstance *o = cl.getObj(pack.id);
|
||||
|
||||
if(CGI->mh)
|
||||
CGI->mh->hideObject(o, true);
|
||||
CGI->mh->onObjectFadeOut(o);
|
||||
|
||||
//notify interfaces about removal
|
||||
for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++)
|
||||
@ -443,7 +443,7 @@ void ApplyFirstClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
|
||||
for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++)
|
||||
{
|
||||
auto ps = gs.getPlayerState(i->first);
|
||||
if(ps && (gs.isVisible(pack.start - int3(1, 0, 0), i->first) || gs.isVisible(pack.end - int3(1, 0, 0), i->first)))
|
||||
if(ps && (gs.isVisible(h->convertToVisitablePos(pack.start), i->first) || gs.isVisible(h->convertToVisitablePos(pack.end), i->first)))
|
||||
{
|
||||
if(ps->human)
|
||||
pack.humanKnows = true;
|
||||
@ -452,12 +452,6 @@ void ApplyFirstClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
|
||||
|
||||
if(!CGI->mh)
|
||||
return;
|
||||
|
||||
if(pack.result == TryMoveHero::TELEPORTATION || pack.result == TryMoveHero::EMBARK || pack.result == TryMoveHero::DISEMBARK || !pack.humanKnows)
|
||||
CGI->mh->hideObject(h, pack.result == TryMoveHero::EMBARK && pack.humanKnows);
|
||||
|
||||
if(pack.result == TryMoveHero::DISEMBARK)
|
||||
CGI->mh->printObject(h->boat);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
|
||||
@ -467,11 +461,26 @@ void ApplyClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
|
||||
|
||||
if(CGI->mh)
|
||||
{
|
||||
if(pack.result == TryMoveHero::TELEPORTATION || pack.result == TryMoveHero::EMBARK || pack.result == TryMoveHero::DISEMBARK)
|
||||
CGI->mh->printObject(h, pack.result == TryMoveHero::DISEMBARK);
|
||||
|
||||
if(pack.result == TryMoveHero::EMBARK)
|
||||
CGI->mh->hideObject(h->boat);
|
||||
switch(pack.result)
|
||||
{
|
||||
case TryMoveHero::FAILED:
|
||||
break; // no-op
|
||||
case TryMoveHero::SUCCESS:
|
||||
CGI->mh->onHeroMoved(h, pack.start, pack.end);
|
||||
break;
|
||||
case TryMoveHero::TELEPORTATION:
|
||||
CGI->mh->onHeroTeleported(h, pack.start, pack.end);
|
||||
break;
|
||||
case TryMoveHero::BLOCKING_VISIT:
|
||||
CGI->mh->onHeroRotated(h, pack.start, pack.end);
|
||||
break;
|
||||
case TryMoveHero::EMBARK:
|
||||
CGI->mh->onObjectFadeOut(h);
|
||||
break;
|
||||
case TryMoveHero::DISEMBARK:
|
||||
CGI->mh->onObjectFadeIn(h);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerColor player = h->tempOwner;
|
||||
@ -485,19 +494,14 @@ void ApplyClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
|
||||
if(i->first != PlayerColor::SPECTATOR && gs.checkForStandardLoss(i->first)) // Do not notify vanquished pack.player's interface
|
||||
continue;
|
||||
|
||||
if(gs.isVisible(pack.start - int3(1, 0, 0), i->first)
|
||||
|| gs.isVisible(pack.end - int3(1, 0, 0), i->first))
|
||||
if(gs.isVisible(h->convertToVisitablePos(pack.start), i->first)
|
||||
|| gs.isVisible(h->convertToVisitablePos(pack.end), i->first))
|
||||
{
|
||||
// pack.src and pack.dst of enemy hero move may be not visible => 'verbose' should be false
|
||||
const bool verbose = cl.getPlayerRelations(i->first, player) != PlayerRelations::ENEMIES;
|
||||
i->second->heroMoved(pack, verbose);
|
||||
}
|
||||
}
|
||||
|
||||
//maphandler didn't get update from playerint, do it now
|
||||
//TODO: restructure nicely
|
||||
if(!pack.humanKnows && CGI->mh)
|
||||
CGI->mh->printObject(h);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitNewStructures(NewStructures & pack)
|
||||
@ -569,21 +573,19 @@ void ApplyClientNetPackVisitor::visitHeroRecruited(HeroRecruited & pack)
|
||||
}
|
||||
}
|
||||
if(needsPrinting && CGI->mh)
|
||||
CGI->mh->printObject(h);
|
||||
CGI->mh->onObjectInstantAdd(h);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitGiveHero(GiveHero & pack)
|
||||
{
|
||||
CGHeroInstance *h = gs.getHero(pack.id);
|
||||
if(CGI->mh)
|
||||
CGI->mh->printObject(h);
|
||||
CGI->mh->onObjectInstantAdd(h);
|
||||
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroCreated, h);
|
||||
}
|
||||
|
||||
void ApplyFirstClientNetPackVisitor::visitGiveHero(GiveHero & pack)
|
||||
{
|
||||
if(CGI->mh)
|
||||
CGI->mh->hideObject(gs.getHero(pack.id));
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitInfoWindow(InfoWindow & pack)
|
||||
@ -950,7 +952,7 @@ void ApplyClientNetPackVisitor::visitNewObject(NewObject & pack)
|
||||
|
||||
const CGObjectInstance *obj = cl.getObj(pack.id);
|
||||
if(CGI->mh)
|
||||
CGI->mh->printObject(obj, true);
|
||||
CGI->mh->onObjectFadeIn(obj);
|
||||
|
||||
for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++)
|
||||
{
|
||||
|
@ -90,7 +90,6 @@ CAdvMapInt::CAdvMapInt():
|
||||
terrain(new CTerrainRect),
|
||||
state(NA),
|
||||
spellBeingCasted(nullptr), selection(nullptr),
|
||||
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(Point(0, 0))
|
||||
@ -239,9 +238,9 @@ CAdvMapInt::CAdvMapInt():
|
||||
|
||||
changeMode(EAdvMapMode::NORMAL);
|
||||
|
||||
underground->block(!CGI->mh->map->twoLevel);
|
||||
questlog->block(!CGI->mh->map->quests.size());
|
||||
worldViewUnderground->block(!CGI->mh->map->twoLevel);
|
||||
underground->block(!CGI->mh->getMap()->twoLevel);
|
||||
questlog->block(!CGI->mh->getMap()->quests.size());
|
||||
worldViewUnderground->block(!CGI->mh->getMap()->twoLevel);
|
||||
|
||||
addUsedEvents(MOVE);
|
||||
}
|
||||
@ -254,7 +253,6 @@ void CAdvMapInt::fshowOverview()
|
||||
void CAdvMapInt::fworldViewBack()
|
||||
{
|
||||
changeMode(EAdvMapMode::NORMAL);
|
||||
CGI->mh->discardWorldViewCache();
|
||||
|
||||
auto hero = curHero();
|
||||
if (hero)
|
||||
@ -280,7 +278,7 @@ void CAdvMapInt::fworldViewScale4x()
|
||||
void CAdvMapInt::fswitchLevel()
|
||||
{
|
||||
// with support for future multi-level maps :)
|
||||
int maxLevels = CGI->mh->map->levels();
|
||||
int maxLevels = CGI->mh->getMap()->levels();
|
||||
if (maxLevels < 2)
|
||||
return;
|
||||
|
||||
@ -292,7 +290,6 @@ void CAdvMapInt::fswitchLevel()
|
||||
worldViewUnderground->setIndex(terrain->getLevel(), true);
|
||||
worldViewUnderground->redraw();
|
||||
|
||||
redrawOnNextFrame = true;
|
||||
minimap->setLevel(terrain->getLevel());
|
||||
}
|
||||
|
||||
@ -322,7 +319,7 @@ void CAdvMapInt::fsleepWake()
|
||||
void CAdvMapInt::fmoveHero()
|
||||
{
|
||||
const CGHeroInstance *h = curHero();
|
||||
if (!h || !LOCPLINT->paths.hasPath(h) || !CGI->mh->canStartHeroMovement())
|
||||
if (!h || !LOCPLINT->paths.hasPath(h) || CGI->mh->hasActiveAnimations())
|
||||
return;
|
||||
|
||||
LOCPLINT->moveHero(h, LOCPLINT->paths.getPath(h));
|
||||
@ -530,7 +527,6 @@ void CAdvMapInt::showAll(SDL_Surface * to)
|
||||
}
|
||||
activeMapPanel->showAll(to);
|
||||
|
||||
redrawOnNextFrame = true;
|
||||
minimap->showAll(to);
|
||||
show(to);
|
||||
|
||||
@ -564,20 +560,6 @@ void CAdvMapInt::show(SDL_Surface * to)
|
||||
if(state != INGAME)
|
||||
return;
|
||||
|
||||
++animValHitCount; //for animations
|
||||
|
||||
if(animValHitCount % 2 == 0)
|
||||
{
|
||||
++heroAnim;
|
||||
}
|
||||
if(animValHitCount >= 8)
|
||||
{
|
||||
CGI->mh->updateWater();
|
||||
animValHitCount = 0;
|
||||
++anim;
|
||||
redrawOnNextFrame = true;
|
||||
}
|
||||
|
||||
if(swipeEnabled)
|
||||
{
|
||||
handleSwipeUpdate();
|
||||
@ -596,18 +578,14 @@ void CAdvMapInt::show(SDL_Surface * to)
|
||||
else
|
||||
gems[i]->setFrame(LOCPLINT->playerID.getNum());
|
||||
}
|
||||
if(redrawOnNextFrame)
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
gems[i]->showAll(to);
|
||||
redrawOnNextFrame=false;
|
||||
LOCPLINT->cingconsole->show(to);
|
||||
}
|
||||
|
||||
terrain->show(to);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
gems[i]->showAll(to);
|
||||
|
||||
LOCPLINT->cingconsole->show(to);
|
||||
|
||||
infoBar->show(to);
|
||||
statusbar->showAll(to);
|
||||
}
|
||||
@ -616,30 +594,28 @@ 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)
|
||||
|
||||
if(scrollingDir & LEFT)
|
||||
terrain->moveViewBy(Point(-scrollSpeed, 0));
|
||||
|
||||
if(scrollingDir & RIGHT)
|
||||
terrain->moveViewBy(Point(+scrollSpeed, 0));
|
||||
|
||||
if(scrollingDir & UP)
|
||||
terrain->moveViewBy(Point(0, -scrollSpeed));
|
||||
|
||||
if(scrollingDir & DOWN)
|
||||
terrain->moveViewBy(Point(0, +scrollSpeed));
|
||||
|
||||
if(scrollingDir)
|
||||
{
|
||||
if(scrollingDir & LEFT)
|
||||
terrain->moveViewBy(Point(-4, 0));
|
||||
|
||||
if(scrollingDir & RIGHT)
|
||||
terrain->moveViewBy(Point(+4, 0));
|
||||
|
||||
if(scrollingDir & UP)
|
||||
terrain->moveViewBy(Point(0, -4));
|
||||
|
||||
if(scrollingDir & DOWN)
|
||||
terrain->moveViewBy(Point(0, +4));
|
||||
|
||||
if(scrollingDir)
|
||||
{
|
||||
setScrollingCursor(scrollingDir);
|
||||
scrollingState = true;
|
||||
}
|
||||
else if(scrollingState)
|
||||
{
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
scrollingState = false;
|
||||
}
|
||||
setScrollingCursor(scrollingDir);
|
||||
scrollingState = true;
|
||||
}
|
||||
else if(scrollingState)
|
||||
{
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
scrollingState = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -649,7 +625,6 @@ void CAdvMapInt::handleSwipeUpdate()
|
||||
{
|
||||
terrain->setViewCenter(swipeTargetPosition, terrain->getLevel());
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
redrawOnNextFrame = true;
|
||||
minimap->redraw();
|
||||
swipeMovementRequested = false;
|
||||
}
|
||||
@ -673,7 +648,6 @@ void CAdvMapInt::centerOn(int3 on, bool fade)
|
||||
|
||||
terrain->setViewCenter(on);
|
||||
|
||||
redrawOnNextFrame=true;
|
||||
underground->setIndex(on.z,true); //change underground switch button image
|
||||
underground->redraw();
|
||||
worldViewUnderground->setIndex(on.z, true);
|
||||
@ -859,7 +833,7 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
|
||||
if(!h || !isActive())
|
||||
return;
|
||||
|
||||
if (!CGI->mh->canStartHeroMovement())
|
||||
if (CGI->mh->hasActiveAnimations())
|
||||
return;
|
||||
|
||||
if(*direction == Point(0,0))
|
||||
@ -870,7 +844,7 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
|
||||
|
||||
int3 dst = h->visitablePos() + int3(direction->x, direction->y, 0);
|
||||
|
||||
if(dst != verifyPos(dst))
|
||||
if (!CGI->mh->isInMap((dst)))
|
||||
return;
|
||||
|
||||
if ( !LOCPLINT->paths.setPath(h, dst))
|
||||
@ -910,23 +884,6 @@ boost::optional<Point> CAdvMapInt::keyToMoveDirection(const SDL_Keycode & key)
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
int3 CAdvMapInt::verifyPos(int3 ver)
|
||||
{
|
||||
if (ver.x<0)
|
||||
ver.x=0;
|
||||
if (ver.y<0)
|
||||
ver.y=0;
|
||||
if (ver.z<0)
|
||||
ver.z=0;
|
||||
if (ver.x>=CGI->mh->sizes.x)
|
||||
ver.x=CGI->mh->sizes.x-1;
|
||||
if (ver.y>=CGI->mh->sizes.y)
|
||||
ver.y=CGI->mh->sizes.y-1;
|
||||
if (ver.z>=CGI->mh->sizes.z)
|
||||
ver.z=CGI->mh->sizes.z-1;
|
||||
return ver;
|
||||
}
|
||||
|
||||
void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
|
||||
{
|
||||
assert(sel);
|
||||
@ -1181,7 +1138,7 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
|
||||
if(LOCPLINT->paths.hasPath(currentHero) &&
|
||||
LOCPLINT->paths.getPath(currentHero).endPos() == mapPos)//we'll be moving
|
||||
{
|
||||
if(CGI->mh->canStartHeroMovement())
|
||||
if(!CGI->mh->hasActiveAnimations())
|
||||
LOCPLINT->moveHero(currentHero, LOCPLINT->paths.getPath(currentHero));
|
||||
return;
|
||||
}
|
||||
@ -1556,15 +1513,3 @@ void CAdvMapInt::WorldViewOptions::clear()
|
||||
|
||||
iconPositions.clear();
|
||||
}
|
||||
|
||||
void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
|
||||
{
|
||||
info.showAllTerrain = showAllTerrain;
|
||||
|
||||
info.additionalIcons = &iconPositions;
|
||||
}
|
||||
|
||||
void CAdvMapInt::requestRedrawMapOnNextFrame()
|
||||
{
|
||||
redrawOnNextFrame = true;
|
||||
}
|
||||
|
@ -67,7 +67,6 @@ private:
|
||||
std::vector<ObjectPosInfo> iconPositions;
|
||||
WorldViewOptions();
|
||||
void clear();
|
||||
void adjustDrawingInfo(MapDrawingInfo & info);
|
||||
};
|
||||
|
||||
bool swipeEnabled;
|
||||
@ -75,15 +74,7 @@ private:
|
||||
Point swipeTargetPosition;
|
||||
|
||||
EGameStates state;
|
||||
|
||||
ui8 anim, animValHitCount; //animation frame
|
||||
ui8 heroAnim, heroAnimValHitCount; //animation frame
|
||||
|
||||
/// top left corner of visible map part
|
||||
//int3 position;
|
||||
|
||||
EAdvMapMode mode;
|
||||
|
||||
WorldViewOptions worldViewOptions;
|
||||
|
||||
/// Currently selected object, can be town, hero or null
|
||||
@ -166,7 +157,6 @@ private:
|
||||
|
||||
boost::optional<Point> keyToMoveDirection(const SDL_Keycode & key);
|
||||
|
||||
bool redrawOnNextFrame;
|
||||
public:
|
||||
CAdvMapInt();
|
||||
|
||||
@ -184,12 +174,9 @@ public:
|
||||
|
||||
// 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);
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
CTerrainRect::CTerrainRect()
|
||||
: fadeSurface(nullptr)
|
||||
, lastRedrawStatus(EMapAnimRedrawStatus::OK)
|
||||
, fadeAnim(std::make_shared<CFadeAnimation>())
|
||||
, curHoveredTile(-1, -1, -1)
|
||||
, isSwiping(false)
|
||||
@ -113,7 +112,7 @@ void CTerrainRect::clickRight(tribool down, bool previousState)
|
||||
return;
|
||||
int3 mp = whichTileIsIt();
|
||||
|
||||
if(CGI->mh->map->isInTheMap(mp) && down)
|
||||
if(CGI->mh->isInMap(mp) && down)
|
||||
adventureInt->tileRClicked(mp);
|
||||
}
|
||||
|
||||
@ -180,18 +179,17 @@ bool CTerrainRect::handleSwipeStateChange(bool btnPressed)
|
||||
void CTerrainRect::handleHover(const Point & cursorPosition)
|
||||
{
|
||||
int3 tHovered = whichTileIsIt(cursorPosition);
|
||||
int3 pom = adventureInt->verifyPos(tHovered);
|
||||
|
||||
if(tHovered != pom) //tile outside the map
|
||||
if(!CGI->mh->isInMap(tHovered))
|
||||
{
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pom != curHoveredTile)
|
||||
if (tHovered != curHoveredTile)
|
||||
{
|
||||
curHoveredTile = pom;
|
||||
adventureInt->tileHovered(pom);
|
||||
curHoveredTile = tHovered;
|
||||
adventureInt->tileHovered(tHovered);
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,50 +203,6 @@ void CTerrainRect::hover(bool on)
|
||||
//Hoverable::hover(on);
|
||||
}
|
||||
|
||||
/*
|
||||
void CTerrainRect::show(SDL_Surface * to)
|
||||
{
|
||||
if (adventureInt->mode == EAdvMapMode::NORMAL)
|
||||
{
|
||||
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos);
|
||||
info.otherheroAnim = true;
|
||||
info.anim = adventureInt->anim;
|
||||
info.heroAnim = adventureInt->heroAnim;
|
||||
if (ADVOPT.smoothMove)
|
||||
info.movement = int3(moveX, moveY, 0);
|
||||
|
||||
lastRedrawStatus = CGI->mh->drawTerrainRectNew(to, &info);
|
||||
if (fadeAnim->isFading())
|
||||
{
|
||||
Rect r(pos);
|
||||
fadeAnim->update();
|
||||
fadeAnim->draw(to, r.topLeft());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::showAll(SDL_Surface * to)
|
||||
{
|
||||
// world view map is static and doesn't need redraw every frame
|
||||
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
{
|
||||
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos, adventureInt->worldViewIcons);
|
||||
info.scaled = true;
|
||||
info.scale = adventureInt->worldViewScale;
|
||||
adventureInt->worldViewOptions.adjustDrawingInfo(info);
|
||||
CGI->mh->drawTerrainRectNew(to, &info);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::showAnim(SDL_Surface * to)
|
||||
{
|
||||
if (!needsAnimUpdate())
|
||||
return;
|
||||
|
||||
if (fadeAnim->isFading() || lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
|
||||
show(to);
|
||||
}
|
||||
*/
|
||||
int3 CTerrainRect::whichTileIsIt(const Point &position)
|
||||
{
|
||||
return renderer->getModel()->getTileAtPoint(position - pos);
|
||||
@ -277,11 +231,6 @@ void CTerrainRect::fadeFromCurrentView()
|
||||
fadeAnim->init(CFadeAnimation::EMode::OUT, fadeSurface);
|
||||
}
|
||||
|
||||
bool CTerrainRect::needsAnimUpdate()
|
||||
{
|
||||
return fadeAnim->isFading() || lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED;
|
||||
}
|
||||
|
||||
void CTerrainRect::setLevel(int level)
|
||||
{
|
||||
renderer->setViewCenter(renderer->getModel()->getMapViewCenter(), level);
|
||||
|
@ -16,7 +16,6 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
struct CGPath;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
enum class EMapAnimRedrawStatus;
|
||||
class CFadeAnimation;
|
||||
class MapView;
|
||||
|
||||
@ -26,7 +25,6 @@ class CTerrainRect : public CIntObject
|
||||
std::shared_ptr<MapView> renderer;
|
||||
|
||||
SDL_Surface * fadeSurface;
|
||||
EMapAnimRedrawStatus lastRedrawStatus;
|
||||
std::shared_ptr<CFadeAnimation> fadeAnim;
|
||||
|
||||
Point swipeInitialViewPos;
|
||||
@ -48,8 +46,6 @@ class CTerrainRect : public CIntObject
|
||||
int3 whichTileIsIt(const Point & position); //x,y are cursor position
|
||||
int3 whichTileIsIt(); //uses current cursor pos
|
||||
|
||||
bool needsAnimUpdate();
|
||||
|
||||
public:
|
||||
CTerrainRect();
|
||||
~CTerrainRect();
|
||||
|
@ -326,10 +326,12 @@ std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const CGObjectInsta
|
||||
return std::shared_ptr<CAnimation>();
|
||||
}
|
||||
|
||||
return getAnimation(info->animationFile);
|
||||
bool generateMovementGroups = (info->id == Obj::BOAT) || (info->id == Obj::HERO);
|
||||
|
||||
return getAnimation(info->animationFile, generateMovementGroups);
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const std::string & filename)
|
||||
std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const std::string & filename, bool generateMovementGroups)
|
||||
{
|
||||
if (animations.count(filename))
|
||||
return animations[filename];
|
||||
@ -338,73 +340,27 @@ std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const std::string &
|
||||
animations[filename] = ret;
|
||||
ret->preload();
|
||||
|
||||
if (generateMovementGroups)
|
||||
{
|
||||
ret->createFlippedGroup(1,13);
|
||||
ret->createFlippedGroup(2,14);
|
||||
ret->createFlippedGroup(3,15);
|
||||
|
||||
ret->createFlippedGroup(6,10);
|
||||
ret->createFlippedGroup(7,11);
|
||||
ret->createFlippedGroup(8,12);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MapRendererObjects::initializeObjects(const IMapRendererContext & context)
|
||||
MapRendererObjects::MapRendererObjects(const IMapRendererContext & context)
|
||||
{
|
||||
auto mapSize = context.getMapSize();
|
||||
|
||||
objects.resize(boost::extents[mapSize.z][mapSize.x][mapSize.y]);
|
||||
|
||||
for(const auto & obj : context.getAllObjects())
|
||||
{
|
||||
if(!obj)
|
||||
continue;
|
||||
|
||||
if(obj->ID == Obj::HERO && dynamic_cast<const CGHeroInstance *>(obj.get())->inTownGarrison)
|
||||
continue;
|
||||
|
||||
if(obj->ID == Obj::BOAT && dynamic_cast<const CGBoat *>(obj.get())->hero)
|
||||
continue;
|
||||
|
||||
std::shared_ptr<CAnimation> animation = getAnimation(obj);
|
||||
|
||||
//no animation at all, e.g. Event
|
||||
if(!animation)
|
||||
continue;
|
||||
|
||||
//empty animation. Illegal?
|
||||
assert(animation->size(0) > 0);
|
||||
if(animation->size(0) == 0)
|
||||
continue;
|
||||
|
||||
auto image = animation->getImage(0, 0);
|
||||
|
||||
int imageWidthTiles = (image->width() + 31) / 32;
|
||||
int imageHeightTiles = (image->height() + 31) / 32;
|
||||
|
||||
int objectWidth = std::min(obj->getWidth(), imageWidthTiles);
|
||||
int objectHeight = std::min(obj->getHeight(), imageHeightTiles);
|
||||
|
||||
for(int fx = 0; fx < objectWidth; ++fx)
|
||||
{
|
||||
for(int fy = 0; fy < objectHeight; ++fy)
|
||||
{
|
||||
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
|
||||
|
||||
if(context.isInMap(currTile) && obj->coveringAt(currTile.x, currTile.y))
|
||||
objects[currTile.z][currTile.x][currTile.y].push_back(obj->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int z = 0; z < mapSize.z; z++)
|
||||
{
|
||||
for(int x = 0; x < mapSize.x; x++)
|
||||
{
|
||||
for(int y = 0; y < mapSize.y; y++)
|
||||
{
|
||||
auto & array = objects[z][x][y];
|
||||
std::sort(array.begin(), array.end(), MapObjectsSorter(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MapRendererObjects::MapRendererObjects(const IMapRendererContext & context)
|
||||
{
|
||||
initializeObjects(context);
|
||||
onObjectInstantAdd(context, obj);
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> MapRendererObjects::getFlagAnimation(const CGObjectInstance* obj)
|
||||
@ -425,7 +381,7 @@ std::shared_ptr<CAnimation> MapRendererObjects::getFlagAnimation(const CGObjectI
|
||||
{
|
||||
assert(dynamic_cast<const CGHeroInstance *>(obj) != nullptr);
|
||||
assert(obj->tempOwner.isValidPlayer());
|
||||
return getAnimation(heroFlags[obj->tempOwner.getNum()]);
|
||||
return getAnimation(heroFlags[obj->tempOwner.getNum()], true);
|
||||
}
|
||||
if(obj->ID == Obj::BOAT)
|
||||
{
|
||||
@ -435,7 +391,7 @@ std::shared_ptr<CAnimation> MapRendererObjects::getFlagAnimation(const CGObjectI
|
||||
assert(!boat->hero || boat->hero->tempOwner.isValidPlayer());
|
||||
|
||||
if(boat->hero)
|
||||
return getAnimation(boatFlags[obj->subID][boat->hero->tempOwner.getNum()]);
|
||||
return getAnimation(boatFlags[obj->subID][boat->hero->tempOwner.getNum()], true);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -516,14 +472,59 @@ void MapRendererObjects::renderTile(const IMapRendererContext & context, Canvas
|
||||
}
|
||||
}
|
||||
|
||||
void MapRendererObjects::addObject(const IMapRendererContext & context, const CGObjectInstance * object)
|
||||
void MapRendererObjects::onObjectInstantAdd(const IMapRendererContext & context, const CGObjectInstance * obj)
|
||||
{
|
||||
if(!obj)
|
||||
return;
|
||||
|
||||
if(obj->ID == Obj::HERO && dynamic_cast<const CGHeroInstance *>(obj)->inTownGarrison)
|
||||
return;
|
||||
|
||||
if(obj->ID == Obj::BOAT && dynamic_cast<const CGBoat *>(obj)->hero)
|
||||
return;
|
||||
|
||||
std::shared_ptr<CAnimation> animation = getAnimation(obj);
|
||||
|
||||
//no animation at all, e.g. Event
|
||||
if(!animation)
|
||||
return;
|
||||
|
||||
//empty animation. Illegal?
|
||||
assert(animation->size(0) > 0);
|
||||
if(animation->size(0) == 0)
|
||||
return;
|
||||
|
||||
auto image = animation->getImage(0, 0);
|
||||
|
||||
int imageWidthTiles = (image->width() + 31) / 32;
|
||||
int imageHeightTiles = (image->height() + 31) / 32;
|
||||
|
||||
int objectWidth = std::min(obj->getWidth(), imageWidthTiles);
|
||||
int objectHeight = std::min(obj->getHeight(), imageHeightTiles);
|
||||
|
||||
for(int fx = 0; fx < objectWidth; ++fx)
|
||||
{
|
||||
for(int fy = 0; fy < objectHeight; ++fy)
|
||||
{
|
||||
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
|
||||
|
||||
if(context.isInMap(currTile) && obj->coveringAt(currTile.x, currTile.y))
|
||||
{
|
||||
auto & container = objects[currTile.z][currTile.x][currTile.y];
|
||||
|
||||
container.push_back(obj->id);
|
||||
boost::range::sort(container, MapObjectsSorter(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapRendererObjects::removeObject(const IMapRendererContext & context, const CGObjectInstance * object)
|
||||
void MapRendererObjects::onObjectInstantRemove(const IMapRendererContext & context, const CGObjectInstance * object)
|
||||
{
|
||||
|
||||
for(int z = 0; z < context.getMapSize().z; z++)
|
||||
for(int x = 0; x < context.getMapSize().x; x++)
|
||||
for(int y = 0; y < context.getMapSize().y; y++)
|
||||
vstd::erase(objects[z][x][y], object->id);
|
||||
}
|
||||
|
||||
void MapRendererDebugGrid::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
|
||||
@ -656,13 +657,3 @@ void MapRenderer::renderTile(const IMapRendererContext & context, Canvas & targe
|
||||
}
|
||||
rendererDebugGrid.renderTile(context, target,coordinates);
|
||||
}
|
||||
|
||||
void MapRenderer::addObject(const IMapRendererContext & context, const CGObjectInstance * object)
|
||||
{
|
||||
rendererObjects.addObject(context, object);
|
||||
}
|
||||
|
||||
void MapRenderer::removeObject(const IMapRendererContext & context, const CGObjectInstance * object)
|
||||
{
|
||||
rendererObjects.addObject(context, object);
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "MapRendererContext.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class int3;
|
||||
@ -20,31 +22,33 @@ VCMI_LIB_NAMESPACE_END
|
||||
class CAnimation;
|
||||
class IImage;
|
||||
class Canvas;
|
||||
class IMapRendererContext;
|
||||
|
||||
class MapObjectsSorter
|
||||
{
|
||||
const IMapRendererContext & context;
|
||||
|
||||
public:
|
||||
explicit MapObjectsSorter(const IMapRendererContext & context);
|
||||
|
||||
bool operator ()(const ObjectInstanceID & left, const ObjectInstanceID & right) const;
|
||||
bool operator ()(const CGObjectInstance * left, const CGObjectInstance * right) const;
|
||||
bool operator()(const ObjectInstanceID & left, const ObjectInstanceID & right) const;
|
||||
bool operator()(const CGObjectInstance * left, const CGObjectInstance * right) const;
|
||||
};
|
||||
|
||||
class MapTileStorage
|
||||
{
|
||||
using TerrainAnimation = std::array<std::unique_ptr<CAnimation>, 4>;
|
||||
std::vector<TerrainAnimation> animations;
|
||||
|
||||
public:
|
||||
explicit MapTileStorage( size_t capacity);
|
||||
void load(size_t index, const std::string& filename);
|
||||
std::shared_ptr<IImage> find(size_t fileIndex, size_t rotationIndex, size_t imageIndex );
|
||||
explicit MapTileStorage(size_t capacity);
|
||||
void load(size_t index, const std::string & filename);
|
||||
std::shared_ptr<IImage> find(size_t fileIndex, size_t rotationIndex, size_t imageIndex);
|
||||
};
|
||||
|
||||
class MapRendererTerrain
|
||||
{
|
||||
MapTileStorage storage;
|
||||
|
||||
public:
|
||||
MapRendererTerrain();
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
@ -53,6 +57,7 @@ public:
|
||||
class MapRendererRiver
|
||||
{
|
||||
MapTileStorage storage;
|
||||
|
||||
public:
|
||||
MapRendererRiver();
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
@ -61,36 +66,36 @@ public:
|
||||
class MapRendererRoad
|
||||
{
|
||||
MapTileStorage storage;
|
||||
|
||||
public:
|
||||
MapRendererRoad();
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
};
|
||||
|
||||
class MapRendererObjects
|
||||
class MapRendererObjects : public IMapObjectObserver
|
||||
{
|
||||
using MapObject = ObjectInstanceID;
|
||||
using MapTile = std::vector<MapObject>;
|
||||
using MapTile = std::vector<MapObject>;
|
||||
|
||||
boost::multi_array<MapTile, 3> objects;
|
||||
std::map<std::string, std::shared_ptr<CAnimation>> animations;
|
||||
|
||||
std::shared_ptr<CAnimation> getFlagAnimation(const CGObjectInstance* obj);
|
||||
std::shared_ptr<CAnimation> getAnimation(const CGObjectInstance* obj);
|
||||
std::shared_ptr<CAnimation> getAnimation(const std::string & filename);
|
||||
std::shared_ptr<CAnimation> getFlagAnimation(const CGObjectInstance * obj);
|
||||
std::shared_ptr<CAnimation> getAnimation(const CGObjectInstance * obj);
|
||||
std::shared_ptr<CAnimation> getAnimation(const std::string & filename, bool generateMovementGroups);
|
||||
|
||||
std::shared_ptr<IImage> getImage(const IMapRendererContext & context, const CGObjectInstance * obj, const std::shared_ptr<CAnimation>& animation) const;
|
||||
std::shared_ptr<IImage> getImage(const IMapRendererContext & context, const CGObjectInstance * obj, const std::shared_ptr<CAnimation> & animation) const;
|
||||
size_t getAnimationGroup(const IMapRendererContext & context, const CGObjectInstance * obj) const;
|
||||
|
||||
void initializeObjects(const IMapRendererContext & context);
|
||||
void renderImage(Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage>& image);
|
||||
void renderImage(Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage> & image);
|
||||
void renderObject(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * obj);
|
||||
|
||||
void renderObject(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance* obj);
|
||||
public:
|
||||
explicit MapRendererObjects(const IMapRendererContext & context);
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
|
||||
void addObject(const IMapRendererContext & context, const CGObjectInstance * object);
|
||||
void removeObject(const IMapRendererContext & context, const CGObjectInstance * object);
|
||||
void onObjectInstantAdd(const IMapRendererContext & context, const CGObjectInstance * object) final override;
|
||||
void onObjectInstantRemove(const IMapRendererContext & context, const CGObjectInstance * object) final override;
|
||||
};
|
||||
|
||||
class MapRendererBorder
|
||||
@ -98,6 +103,7 @@ class MapRendererBorder
|
||||
std::unique_ptr<CAnimation> animation;
|
||||
|
||||
size_t getIndexForTile(const IMapRendererContext & context, const int3 & coordinates);
|
||||
|
||||
public:
|
||||
MapRendererBorder();
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
@ -120,12 +126,12 @@ class MapRendererPath
|
||||
void renderImage(Canvas & target, bool reachableToday, size_t imageIndex);
|
||||
void renderImageCross(Canvas & target, bool reachableToday, const int3 & curr);
|
||||
void renderImageArrow(Canvas & target, bool reachableToday, const int3 & curr, const int3 & prev, const int3 & next);
|
||||
|
||||
public:
|
||||
MapRendererPath();
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
};
|
||||
|
||||
|
||||
class MapRendererDebugGrid
|
||||
{
|
||||
public:
|
||||
@ -147,8 +153,4 @@ public:
|
||||
explicit MapRenderer(const IMapRendererContext & context);
|
||||
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
|
||||
void addObject(const IMapRendererContext & context, const CGObjectInstance * object);
|
||||
void removeObject(const IMapRendererContext & context, const CGObjectInstance * object);
|
||||
|
||||
};
|
||||
|
@ -17,6 +17,7 @@ class int3;
|
||||
class Point;
|
||||
class ObjectInstanceID;
|
||||
class CGObjectInstance;
|
||||
class CGHeroInstance;
|
||||
struct TerrainTile;
|
||||
struct CGPath;
|
||||
|
||||
@ -27,7 +28,7 @@ class IMapRendererContext
|
||||
public:
|
||||
virtual ~IMapRendererContext() = default;
|
||||
|
||||
using ObjectsVector = std::vector< ConstTransitivePtr<CGObjectInstance> >;
|
||||
using ObjectsVector = std::vector<ConstTransitivePtr<CGObjectInstance>>;
|
||||
|
||||
/// returns dimensions of current map
|
||||
virtual int3 getMapSize() const = 0;
|
||||
@ -42,7 +43,7 @@ public:
|
||||
virtual ObjectsVector getAllObjects() const = 0;
|
||||
|
||||
/// returns specific object by ID, or nullptr if not found
|
||||
virtual const CGObjectInstance * getObject( ObjectInstanceID objectID ) const = 0;
|
||||
virtual const CGObjectInstance * getObject(ObjectInstanceID objectID) const = 0;
|
||||
|
||||
/// returns path of currently active hero, or nullptr if none
|
||||
virtual const CGPath * currentPath() const = 0;
|
||||
@ -62,3 +63,31 @@ public:
|
||||
/// if true, map grid should be visible on map
|
||||
virtual bool showGrid() const = 0;
|
||||
};
|
||||
|
||||
class IMapObjectObserver
|
||||
{
|
||||
public:
|
||||
IMapObjectObserver();
|
||||
virtual ~IMapObjectObserver();
|
||||
|
||||
/// Plays fade-in animation and adds object to map
|
||||
virtual void onObjectFadeIn(const IMapRendererContext & context, const CGObjectInstance * obj) {}
|
||||
|
||||
/// Plays fade-out animation and removed object from map
|
||||
virtual void onObjectFadeOut(const IMapRendererContext & context, const CGObjectInstance * obj) {}
|
||||
|
||||
/// Adds object to map instantly, with no animation
|
||||
virtual void onObjectInstantAdd(const IMapRendererContext & context, const CGObjectInstance * obj) {}
|
||||
|
||||
/// Removes object from map instantly, with no animation
|
||||
virtual void onObjectInstantRemove(const IMapRendererContext & context, const CGObjectInstance * obj) {}
|
||||
|
||||
/// Perform hero teleportation animation with terrain fade animation
|
||||
virtual void onHeroTeleported(const IMapRendererContext & context, const CGHeroInstance * obj, const int3 & from, const int3 & dest) {}
|
||||
|
||||
/// Perform hero movement animation, moving hero across terrain
|
||||
virtual void onHeroMoved(const IMapRendererContext & context, const CGHeroInstance * obj, const int3 & from, const int3 & dest) {}
|
||||
|
||||
/// Instantly rotates hero to face destination tile
|
||||
virtual void onHeroRotated(const IMapRendererContext & context, const CGHeroInstance * obj, const int3 & from, const int3 & dest) {}
|
||||
};
|
||||
|
@ -147,17 +147,17 @@ bool MapRendererContext::isInMap(const int3 & coordinates) const
|
||||
|
||||
const TerrainTile & MapRendererContext::getMapTile(const int3 & coordinates) const
|
||||
{
|
||||
return CGI->mh->map->getTile(coordinates);
|
||||
return CGI->mh->getMap()->getTile(coordinates);
|
||||
}
|
||||
|
||||
MapRendererContext::ObjectsVector MapRendererContext::getAllObjects() const
|
||||
{
|
||||
return CGI->mh->map->objects;
|
||||
return CGI->mh->getMap()->objects;
|
||||
}
|
||||
|
||||
const CGObjectInstance * MapRendererContext::getObject(ObjectInstanceID objectID) const
|
||||
{
|
||||
return CGI->mh->map->objects.at(objectID.getNum());
|
||||
return CGI->mh->getMap()->objects.at(objectID.getNum());
|
||||
}
|
||||
|
||||
bool MapRendererContext::isVisible(const int3 & coordinates) const
|
||||
|
@ -18,7 +18,7 @@ class MapRenderer;
|
||||
|
||||
class MapRendererContext : public IMapRendererContext
|
||||
{
|
||||
Point tileSize = Point(32,32);
|
||||
Point tileSize = Point(32, 32);
|
||||
uint32_t animationTime = 0;
|
||||
|
||||
public:
|
||||
@ -50,10 +50,11 @@ class MapViewModel
|
||||
Point viewDimensions;
|
||||
|
||||
int mapLevel = 0;
|
||||
|
||||
public:
|
||||
void setTileSize(Point const & newValue);
|
||||
void setViewCenter(Point const & newValue);
|
||||
void setViewDimensions(Point const & newValue);
|
||||
void setTileSize(const Point & newValue);
|
||||
void setViewCenter(const Point & newValue);
|
||||
void setViewDimensions(const Point & newValue);
|
||||
void setLevel(int newLevel);
|
||||
|
||||
/// returns current size of map tile in pixels
|
||||
@ -112,6 +113,7 @@ class MapView : public CIntObject
|
||||
std::unique_ptr<MapCache> tilesCache;
|
||||
|
||||
std::shared_ptr<MapViewModel> createModel(const Point & dimensions) const;
|
||||
|
||||
public:
|
||||
std::shared_ptr<const MapViewModel> getModel() const;
|
||||
|
||||
@ -121,6 +123,8 @@ public:
|
||||
void setViewCenter(const Point & position, int level);
|
||||
void setTileSize(const Point & tileSize);
|
||||
|
||||
void moveHero();
|
||||
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,12 +9,12 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
#include "../../lib/int3.h"
|
||||
#include "../../lib/spells/ViewSpellInt.h"
|
||||
#include "../../lib/Rect.h"
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
#ifdef IN
|
||||
#undef IN
|
||||
@ -40,6 +40,7 @@ class CAnimation;
|
||||
class IImage;
|
||||
class CFadeAnimation;
|
||||
class CMapHandler;
|
||||
class IMapObjectObserver;
|
||||
|
||||
enum class EWorldViewIcon
|
||||
{
|
||||
@ -72,12 +73,6 @@ enum class EMapObjectFadingType
|
||||
OUT
|
||||
};
|
||||
|
||||
enum class EMapAnimRedrawStatus
|
||||
{
|
||||
OK,
|
||||
REDRAW_REQUESTED // map blitter requests quick redraw due to current animation
|
||||
};
|
||||
|
||||
struct TerrainTileObject
|
||||
{
|
||||
const CGObjectInstance *obj;
|
||||
@ -94,319 +89,43 @@ struct TerrainTile2
|
||||
std::vector<TerrainTileObject> objects; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
|
||||
};
|
||||
|
||||
struct MapDrawingInfo
|
||||
{
|
||||
bool scaled;
|
||||
int3 &topTile; // top-left tile in viewport [in tiles]
|
||||
std::shared_ptr<const boost::multi_array<ui8, 3>> visibilityMap;
|
||||
Rect drawBounds; // map rect drawing bounds on screen
|
||||
std::shared_ptr<CAnimation> icons; // holds overlay icons for world view mode
|
||||
float scale; // map scale for world view mode (only if scaled == true)
|
||||
|
||||
bool otherheroAnim;
|
||||
ui8 anim;
|
||||
ui8 heroAnim;
|
||||
|
||||
int3 movement; // used for smooth map movement
|
||||
|
||||
bool puzzleMode;
|
||||
int3 grailPos; // location of grail for puzzle mode [in tiles]
|
||||
|
||||
const std::vector<ObjectPosInfo> * additionalIcons;
|
||||
|
||||
bool showAllTerrain; //for expert viewEarth
|
||||
|
||||
MapDrawingInfo(int3 &topTile_, std::shared_ptr<const boost::multi_array<ui8, 3>> visibilityMap_, const Rect & drawBounds_, std::shared_ptr<CAnimation> icons_ = nullptr)
|
||||
: scaled(false),
|
||||
topTile(topTile_),
|
||||
|
||||
visibilityMap(visibilityMap_),
|
||||
drawBounds(drawBounds_),
|
||||
icons(icons_),
|
||||
scale(1.0f),
|
||||
otherheroAnim(false),
|
||||
anim(0u),
|
||||
heroAnim(0u),
|
||||
movement(int3()),
|
||||
puzzleMode(false),
|
||||
grailPos(int3()),
|
||||
additionalIcons(nullptr),
|
||||
showAllTerrain(false)
|
||||
{}
|
||||
|
||||
ui8 getHeroAnim() const { return otherheroAnim ? anim : heroAnim; }
|
||||
};
|
||||
|
||||
|
||||
template <typename T> class PseudoV
|
||||
{
|
||||
public:
|
||||
PseudoV() : offset(0) { }
|
||||
inline T & operator[](const int & n)
|
||||
{
|
||||
return inver[n+offset];
|
||||
}
|
||||
inline const T & operator[](const int & n) const
|
||||
{
|
||||
return inver[n+offset];
|
||||
}
|
||||
void resize(int rest, int before, int after)
|
||||
{
|
||||
inver.resize(before + rest + after);
|
||||
offset=before;
|
||||
}
|
||||
int size() const
|
||||
{
|
||||
return static_cast<int>(inver.size());
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
friend class CMapBlitter;
|
||||
friend class CMapNormalBlitter;
|
||||
friend class CMapWorldViewBlitter;
|
||||
|
||||
CMapCache cache;
|
||||
CMapBlitter * normalBlitter;
|
||||
CMapBlitter * worldViewBlitter;
|
||||
CMapBlitter * puzzleViewBlitter;
|
||||
|
||||
std::map<int, std::pair<int3, CFadeAnimation*>> fadeAnims;
|
||||
int fadeAnimCounter;
|
||||
|
||||
CMapBlitter * resolveBlitter(const MapDrawingInfo * info) const;
|
||||
bool updateObjectsFade();
|
||||
bool startObjectFade(TerrainTileObject & obj, bool in, int3 pos);
|
||||
|
||||
void initObjectRects();
|
||||
void initBorderGraphics();
|
||||
void initTerrainGraphics();
|
||||
void prepareFOWDefs();
|
||||
|
||||
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;
|
||||
private:
|
||||
// Max number of tiles that will fit in the map screen. Tiles
|
||||
// can be partial on each edges.
|
||||
int tilesW;
|
||||
int tilesH;
|
||||
|
||||
// size of each side of the frame around the whole map, in tiles
|
||||
int frameH;
|
||||
int frameW;
|
||||
|
||||
// Coord in pixels of the top left corner of the top left tile to
|
||||
// draw. Values range is [-31..0]. A negative value
|
||||
// implies that part of the tile won't be displayed.
|
||||
int offsetX;
|
||||
int offsetY;
|
||||
|
||||
//terrain graphics
|
||||
//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]
|
||||
|
||||
TFlippedAnimations terrainAnimations;//[terrain type, rotation]
|
||||
TFlippedCache terrainImages;//[terrain type, view type, rotation]
|
||||
|
||||
TFlippedAnimations roadAnimations;//[road type, rotation]
|
||||
TFlippedCache roadImages;//[road type, view type, rotation]
|
||||
|
||||
TFlippedAnimations riverAnimations;//[river type, rotation]
|
||||
TFlippedCache riverImages;//[river type, view type, rotation]
|
||||
|
||||
//Fog of War cache (not owned)
|
||||
std::vector<std::shared_ptr<IImage>> FoWfullHide;
|
||||
boost::multi_array<ui8, 3> hideBitmap; //frame indexes (in FoWfullHide) of graphic that should be used to fully hide a tile
|
||||
|
||||
std::vector<std::shared_ptr<IImage>> FoWpartialHide;
|
||||
|
||||
//edge graphics
|
||||
std::unique_ptr<CAnimation> egdeAnimation;
|
||||
std::vector<std::shared_ptr<IImage>> egdeImages;//cache of links to egdeAnimation (for faster access)
|
||||
PseudoV< PseudoV< PseudoV <ui8> > > edgeFrames; //frame indexes (in egdeImages) of tile outside of map
|
||||
|
||||
mutable std::map<const CGObjectInstance*, ui8> animationPhase;
|
||||
std::vector<IMapObjectObserver *> observers;
|
||||
|
||||
public:
|
||||
CMapHandler();
|
||||
~CMapHandler();
|
||||
explicit CMapHandler(const CMap * map);
|
||||
|
||||
void getTerrainDescr(const int3 & pos, std::string & out, bool isRMB) const; // isRMB = whether Right Mouse Button is clicked
|
||||
bool printObject(const CGObjectInstance * obj, bool fadein = false); //puts appropriate things to tiles, so obj will be visible on map
|
||||
bool hideObject(const CGObjectInstance * obj, bool fadeout = false); //removes appropriate things from ttiles, so obj will be no longer visible on map (but still will exist)
|
||||
bool hasObjectHole(const int3 & pos) const; // Checks if TerrainTile2 tile has a pit remained after digging.
|
||||
void init();
|
||||
const CMap * getMap();
|
||||
|
||||
/// returns true if tile is within map bounds
|
||||
bool isInMap(const int3 & tile);
|
||||
|
||||
/// see MapObjectObserver interface
|
||||
void onObjectFadeIn(const CGObjectInstance * obj);
|
||||
void onObjectFadeOut(const CGObjectInstance * obj);
|
||||
void onObjectInstantAdd(const CGObjectInstance * obj);
|
||||
void onObjectInstantRemove(const CGObjectInstance * obj);
|
||||
void onHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest);
|
||||
void onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest);
|
||||
void onHeroRotated(const CGHeroInstance * obj, const int3 & from, const int3 & dest);
|
||||
|
||||
/// Add object to receive notifications on any changes in visible map state
|
||||
void addMapObserver(IMapObjectObserver * observer);
|
||||
void removeMapObserver(IMapObjectObserver * observer);
|
||||
|
||||
/// returns string description for terrain interaction
|
||||
void getTerrainDescr(const int3 & pos, std::string & out, bool isRMB) const;
|
||||
|
||||
/// returns list of ambient sounds for specified tile
|
||||
std::vector<std::string> getAmbientSounds(const int3 & tile);
|
||||
|
||||
/// returns true if tile has hole from grail digging attempt
|
||||
bool hasObjectHole(const int3 & pos) const;
|
||||
|
||||
EMapAnimRedrawStatus drawTerrainRectNew(SDL_Surface * targetSurface, const MapDrawingInfo * info, bool redrawOnlyAnim = false);
|
||||
void updateWater();
|
||||
/// determines if the map is ready to handle new hero movement (not available during fading animations)
|
||||
bool canStartHeroMovement();
|
||||
|
||||
void discardWorldViewCache();
|
||||
bool hasActiveAnimations();
|
||||
|
||||
static bool compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b);
|
||||
};
|
||||
|
@ -159,115 +159,6 @@ Graphics::~Graphics()
|
||||
delete[] neutralColorPalette;
|
||||
}
|
||||
|
||||
void Graphics::load()
|
||||
{
|
||||
heroMoveArrows = std::make_shared<CAnimation>("ADAG");
|
||||
heroMoveArrows->preload();
|
||||
|
||||
loadHeroAnimations();
|
||||
loadHeroFlagAnimations();
|
||||
loadFogOfWar();
|
||||
}
|
||||
|
||||
void Graphics::loadHeroAnimations()
|
||||
{
|
||||
for(auto & elem : CGI->heroh->classes.objects)
|
||||
{
|
||||
for (auto & templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->getIndex())->getTemplates())
|
||||
{
|
||||
if (!heroAnimations.count(templ->animationFile))
|
||||
heroAnimations[templ->animationFile] = loadHeroAnimation(templ->animationFile);
|
||||
}
|
||||
}
|
||||
|
||||
boatAnimations[0] = loadHeroAnimation("AB01_.DEF");
|
||||
boatAnimations[1] = loadHeroAnimation("AB02_.DEF");
|
||||
boatAnimations[2] = loadHeroAnimation("AB03_.DEF");
|
||||
|
||||
|
||||
mapObjectAnimations["AB01_.DEF"] = boatAnimations[0];
|
||||
mapObjectAnimations["AB02_.DEF"] = boatAnimations[1];
|
||||
mapObjectAnimations["AB03_.DEF"] = boatAnimations[2];
|
||||
}
|
||||
void Graphics::loadHeroFlagAnimations()
|
||||
{
|
||||
static const std::vector<std::string> HERO_FLAG_ANIMATIONS =
|
||||
{
|
||||
"AF00", "AF01","AF02","AF03",
|
||||
"AF04", "AF05","AF06","AF07"
|
||||
};
|
||||
|
||||
static const std::vector< std::vector<std::string> > BOAT_FLAG_ANIMATIONS =
|
||||
{
|
||||
{
|
||||
"ABF01L", "ABF01G", "ABF01R", "ABF01D",
|
||||
"ABF01B", "ABF01P", "ABF01W", "ABF01K"
|
||||
},
|
||||
{
|
||||
"ABF02L", "ABF02G", "ABF02R", "ABF02D",
|
||||
"ABF02B", "ABF02P", "ABF02W", "ABF02K"
|
||||
},
|
||||
{
|
||||
"ABF03L", "ABF03G", "ABF03R", "ABF03D",
|
||||
"ABF03B", "ABF03P", "ABF03W", "ABF03K"
|
||||
}
|
||||
};
|
||||
|
||||
for(const auto & name : HERO_FLAG_ANIMATIONS)
|
||||
heroFlagAnimations.push_back(loadHeroFlagAnimation(name));
|
||||
|
||||
for(int i = 0; i < BOAT_FLAG_ANIMATIONS.size(); i++)
|
||||
for(const auto & name : BOAT_FLAG_ANIMATIONS[i])
|
||||
boatFlagAnimations[i].push_back(loadHeroFlagAnimation(name));
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> Graphics::loadHeroFlagAnimation(const std::string & name)
|
||||
{
|
||||
//first - group number to be rotated, second - group number after rotation
|
||||
static const std::vector<std::pair<int,int> > rotations =
|
||||
{
|
||||
{6,10}, {7,11}, {8,12}, {1,13},
|
||||
{2,14}, {3,15}
|
||||
};
|
||||
|
||||
std::shared_ptr<CAnimation> anim = std::make_shared<CAnimation>(name);
|
||||
anim->preload();
|
||||
|
||||
for(const auto & rotation : rotations)
|
||||
{
|
||||
const int sourceGroup = rotation.first;
|
||||
const int targetGroup = rotation.second;
|
||||
|
||||
anim->createFlippedGroup(sourceGroup, targetGroup);
|
||||
}
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> Graphics::loadHeroAnimation(const std::string &name)
|
||||
{
|
||||
//first - group number to be rotated, second - group number after rotation
|
||||
static const std::vector<std::pair<int,int> > rotations =
|
||||
{
|
||||
{6,10}, {7,11}, {8,12}, {1,13},
|
||||
{2,14}, {3,15}
|
||||
};
|
||||
|
||||
std::shared_ptr<CAnimation> anim = std::make_shared<CAnimation>(name);
|
||||
anim->preload();
|
||||
|
||||
|
||||
for(const auto & rotation : rotations)
|
||||
{
|
||||
const int sourceGroup = rotation.first;
|
||||
const int targetGroup = rotation.second;
|
||||
|
||||
anim->createFlippedGroup(sourceGroup, targetGroup);
|
||||
}
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player)
|
||||
{
|
||||
if(sur->format->palette)
|
||||
@ -335,26 +226,6 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player)
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::loadFogOfWar()
|
||||
{
|
||||
fogOfWarFullHide = std::make_shared<CAnimation>("TSHRC");
|
||||
fogOfWarFullHide->preload();
|
||||
fogOfWarPartialHide = std::make_shared<CAnimation>("TSHRE");
|
||||
fogOfWarPartialHide->preload();
|
||||
|
||||
static const int rotations [] = {22, 15, 2, 13, 12, 16, 28, 17, 20, 19, 7, 24, 26, 25, 30, 32, 27};
|
||||
|
||||
size_t size = fogOfWarPartialHide->size(0);//group size after next rotation
|
||||
|
||||
for(const int rotation : rotations)
|
||||
{
|
||||
fogOfWarPartialHide->duplicateImage(0, rotation, 0);
|
||||
auto image = fogOfWarPartialHide->getImage(size, 0);
|
||||
image->verticalFlip();
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::loadFonts()
|
||||
{
|
||||
const JsonNode config(ResourceID("config/fonts.json"));
|
||||
@ -378,41 +249,6 @@ void Graphics::loadFonts()
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> Graphics::getAnimation(const CGObjectInstance* obj)
|
||||
{
|
||||
return getAnimation(obj->appearance);
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> Graphics::getAnimation(std::shared_ptr<const ObjectTemplate> info)
|
||||
{
|
||||
//the only(?) invisible object
|
||||
if(info->id == Obj::EVENT)
|
||||
{
|
||||
return std::shared_ptr<CAnimation>();
|
||||
}
|
||||
|
||||
if(info->animationFile.empty())
|
||||
{
|
||||
logGlobal->warn("Def name for obj (%d,%d) is empty!", info->id, info->subid);
|
||||
return std::shared_ptr<CAnimation>();
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> ret = mapObjectAnimations[info->animationFile];
|
||||
|
||||
//already loaded
|
||||
if(ret)
|
||||
{
|
||||
ret->preload();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = std::make_shared<CAnimation>(info->animationFile);
|
||||
mapObjectAnimations[info->animationFile] = ret;
|
||||
|
||||
ret->preload();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Graphics::loadErmuToPicture()
|
||||
{
|
||||
//loading ERMU to picture
|
||||
|
@ -39,23 +39,11 @@ enum EFonts : int
|
||||
class Graphics
|
||||
{
|
||||
void addImageListEntry(size_t index, size_t group, const std::string & listName, const std::string & imageName);
|
||||
|
||||
void addImageListEntries(const EntityService * service);
|
||||
|
||||
void initializeBattleGraphics();
|
||||
void loadPaletteAndColors();
|
||||
|
||||
void loadHeroAnimations();
|
||||
//loads animation and adds required rotated frames
|
||||
std::shared_ptr<CAnimation> loadHeroAnimation(const std::string &name);
|
||||
|
||||
void loadHeroFlagAnimations();
|
||||
|
||||
//loads animation and adds required rotated frames
|
||||
std::shared_ptr<CAnimation> loadHeroFlagAnimation(const std::string &name);
|
||||
|
||||
void loadErmuToPicture();
|
||||
void loadFogOfWar();
|
||||
void loadFonts();
|
||||
void initializeImageLists();
|
||||
|
||||
@ -70,23 +58,6 @@ public:
|
||||
SDL_Color * playerColorPalette; //palette to make interface colors good - array of size [256]
|
||||
SDL_Color * neutralColorPalette;
|
||||
|
||||
std::shared_ptr<CAnimation> heroMoveArrows;
|
||||
|
||||
// [hero class def name] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing
|
||||
std::map< std::string, std::shared_ptr<CAnimation> > heroAnimations;
|
||||
std::vector< std::shared_ptr<CAnimation> > heroFlagAnimations;
|
||||
|
||||
// [boat type: 0 .. 2] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing
|
||||
std::array< std::shared_ptr<CAnimation>, 3> boatAnimations;
|
||||
|
||||
std::array< std::vector<std::shared_ptr<CAnimation> >, 3> boatFlagAnimations;
|
||||
|
||||
//all other objects (not hero or boat)
|
||||
std::map< std::string, std::shared_ptr<CAnimation> > mapObjectAnimations;
|
||||
|
||||
std::shared_ptr<CAnimation> fogOfWarFullHide;
|
||||
std::shared_ptr<CAnimation> fogOfWarPartialHide;
|
||||
|
||||
std::map<std::string, JsonNode> imageLists;
|
||||
|
||||
//towns
|
||||
@ -98,12 +69,7 @@ public:
|
||||
Graphics();
|
||||
~Graphics();
|
||||
|
||||
void load();
|
||||
|
||||
void blueToPlayersAdv(SDL_Surface * sur, PlayerColor player); //replaces blue interface colour with a color of player
|
||||
|
||||
std::shared_ptr<CAnimation> getAnimation(const CGObjectInstance * obj);
|
||||
std::shared_ptr<CAnimation> getAnimation(std::shared_ptr<const ObjectTemplate> info);
|
||||
};
|
||||
|
||||
extern Graphics * graphics;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../CServerHandler.h"
|
||||
|
||||
#include "../adventureMap/mapHandler.h"
|
||||
#include "../adventureMap/CResDataBar.h"
|
||||
#include "../battle/BattleInterfaceClasses.h"
|
||||
#include "../battle/BattleInterface.h"
|
||||
@ -1159,14 +1158,15 @@ CPuzzleWindow::CPuzzleWindow(const int3 & GrailPos, double discoveredRatio)
|
||||
|
||||
void CPuzzleWindow::showAll(SDL_Surface * to)
|
||||
{
|
||||
int3 moveInt = int3(8, 9, 0);
|
||||
Rect mapRect = Rect(Point(pos.x + 8, pos.y + 7), Point(544, 591));
|
||||
int3 topTile = grailPos - moveInt;
|
||||
assert(0);
|
||||
//int3 moveInt = int3(8, 9, 0);
|
||||
//Rect mapRect = Rect(Point(pos.x + 8, pos.y + 7), Point(544, 591));
|
||||
//int3 topTile = grailPos - moveInt;
|
||||
|
||||
MapDrawingInfo info(topTile, LOCPLINT->cb->getVisibilityMap(), mapRect);
|
||||
info.puzzleMode = true;
|
||||
info.grailPos = grailPos;
|
||||
CGI->mh->drawTerrainRectNew(to, &info);
|
||||
//MapDrawingInfo info(topTile, LOCPLINT->cb->getVisibilityMap(), mapRect);
|
||||
//info.puzzleMode = true;
|
||||
//info.grailPos = grailPos;
|
||||
//CGI->mh->drawTerrainRectNew(to, &info);
|
||||
|
||||
CWindowObject::showAll(to);
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ public:
|
||||
virtual void setMovePoints(SetMovePoints * smp)=0;
|
||||
virtual void setManaPoints(ObjectInstanceID hid, int val)=0;
|
||||
virtual void giveHero(ObjectInstanceID id, PlayerColor player)=0;
|
||||
virtual void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags)=0;
|
||||
virtual void changeObjPos(ObjectInstanceID objid, int3 newPos)=0;
|
||||
virtual void sendAndApply(CPackForClient * pack) = 0;
|
||||
virtual void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)=0; //when two heroes meet on adventure map
|
||||
virtual void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) = 0;
|
||||
|
@ -380,7 +380,6 @@ struct DLL_LINKAGE ChangeObjPos : public CPackForClient
|
||||
|
||||
ObjectInstanceID objid;
|
||||
int3 nPos;
|
||||
ui8 flags = 0; //bit flags: 1 - redraw
|
||||
|
||||
virtual void visitTyped(ICPackVisitor & visitor) override;
|
||||
|
||||
@ -388,7 +387,6 @@ struct DLL_LINKAGE ChangeObjPos : public CPackForClient
|
||||
{
|
||||
h & objid;
|
||||
h & nPos;
|
||||
h & flags;
|
||||
}
|
||||
};
|
||||
|
||||
@ -583,7 +581,6 @@ struct DLL_LINKAGE TryMoveHero : public CPackForClient
|
||||
FAILED,
|
||||
SUCCESS,
|
||||
TELEPORTATION,
|
||||
RESERVED_,
|
||||
BLOCKING_VISIT,
|
||||
EMBARK,
|
||||
DISEMBARK
|
||||
|
@ -22,11 +22,13 @@ public:
|
||||
Point()
|
||||
{
|
||||
x = y = 0;
|
||||
};
|
||||
}
|
||||
|
||||
Point(int X, int Y)
|
||||
:x(X),y(Y)
|
||||
{};
|
||||
: x(X)
|
||||
, y(Y)
|
||||
{
|
||||
}
|
||||
|
||||
explicit DLL_LINKAGE Point(const int3 &a);
|
||||
|
||||
|
@ -200,7 +200,6 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
|
||||
ChangeObjPos cop;
|
||||
cop.objid = nearest->id;
|
||||
cop.nPos = summonPos + int3(1,0,0);
|
||||
cop.flags = 1;
|
||||
env->apply(&cop);
|
||||
}
|
||||
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
|
||||
|
@ -2773,12 +2773,11 @@ void CGameHandler::giveHero(ObjectInstanceID id, PlayerColor player)
|
||||
sendAndApply(&gh);
|
||||
}
|
||||
|
||||
void CGameHandler::changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags)
|
||||
void CGameHandler::changeObjPos(ObjectInstanceID objid, int3 newPos)
|
||||
{
|
||||
ChangeObjPos cop;
|
||||
cop.objid = objid;
|
||||
cop.nPos = newPos;
|
||||
cop.flags = flags;
|
||||
sendAndApply(&cop);
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ public:
|
||||
void setMovePoints(SetMovePoints * smp) override;
|
||||
void setManaPoints(ObjectInstanceID hid, int val) override;
|
||||
void giveHero(ObjectInstanceID id, PlayerColor player) override;
|
||||
void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags) override;
|
||||
void changeObjPos(ObjectInstanceID objid, int3 newPos) override;
|
||||
void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override;
|
||||
|
||||
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override;
|
||||
|
Loading…
Reference in New Issue
Block a user