MapViewController.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. /*
  2. * MapViewController.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "MapViewController.h"
  12. #include "MapRendererContext.h"
  13. #include "MapRendererContextState.h"
  14. #include "MapViewCache.h"
  15. #include "MapViewModel.h"
  16. #include "../CCallback.h"
  17. #include "../CPlayerInterface.h"
  18. #include "../adventureMap/AdventureMapInterface.h"
  19. #include "../gui/CGuiHandler.h"
  20. #include "../gui/WindowHandler.h"
  21. #include "../eventsSDL/InputHandler.h"
  22. #include "../../lib/CConfigHandler.h"
  23. #include "../../lib/StartInfo.h"
  24. #include "../../lib/mapObjects/CGHeroInstance.h"
  25. #include "../../lib/mapObjects/MiscObjects.h"
  26. #include "../../lib/pathfinder/CGPathNode.h"
  27. #include "../../lib/spells/ViewSpellInt.h"
  28. void MapViewController::setViewCenter(const int3 & position)
  29. {
  30. setViewCenter(Point(position) * model->getSingleTileSize() + model->getSingleTileSize() / 2, position.z);
  31. }
  32. void MapViewController::setViewCenter(const Point & position, int level)
  33. {
  34. Point upperLimit = Point(context->getMapSize()) * model->getSingleTileSize();
  35. Point lowerLimit = Point(0, 0);
  36. if(worldViewContext)
  37. {
  38. Point area = model->getPixelsVisibleDimensions();
  39. Point mapCenter = upperLimit / 2;
  40. Point desiredLowerLimit = lowerLimit + area / 2;
  41. Point desiredUpperLimit = upperLimit - area / 2;
  42. Point actualLowerLimit{
  43. std::min(desiredLowerLimit.x, mapCenter.x),
  44. std::min(desiredLowerLimit.y, mapCenter.y)
  45. };
  46. Point actualUpperLimit{
  47. std::max(desiredUpperLimit.x, mapCenter.x),
  48. std::max(desiredUpperLimit.y, mapCenter.y)
  49. };
  50. upperLimit = actualUpperLimit;
  51. lowerLimit = actualLowerLimit;
  52. }
  53. Point betterPosition = {std::clamp(position.x, lowerLimit.x, upperLimit.x), std::clamp(position.y, lowerLimit.y, upperLimit.y)};
  54. model->setViewCenter(betterPosition);
  55. model->setLevel(std::clamp(level, 0, context->getMapSize().z));
  56. if(adventureInt && !puzzleMapContext) // may be called before adventureInt is initialized
  57. adventureInt->onMapViewMoved(model->getTilesTotalRect(), model->getLevel());
  58. }
  59. void MapViewController::setTileSize(const Point & tileSize)
  60. {
  61. Point oldSize = model->getSingleTileSize();
  62. model->setTileSize(tileSize);
  63. double scaleChangeX = 1.0 * tileSize.x / oldSize.x;
  64. double scaleChangeY = 1.0 * tileSize.y / oldSize.y;
  65. Point newViewCenter {
  66. static_cast<int>(std::round(model->getMapViewCenter().x * scaleChangeX)),
  67. static_cast<int>(std::round(model->getMapViewCenter().y * scaleChangeY))
  68. };
  69. // force update of view center since changing tile size may invalidated it
  70. setViewCenter(newViewCenter, model->getLevel());
  71. }
  72. void MapViewController::modifyTileSize(int stepsChange)
  73. {
  74. // we want to zoom in/out in fixed 10% steps, to allow player to return back to exactly 100% zoom just by scrolling
  75. // so, zooming in for 5 steps will put game at 1.1^5 = 1.61 scale
  76. // try to determine current zooming level and change it by requested number of steps
  77. double currentZoomFactor = targetTileSize.x / static_cast<double>(defaultTileSize);
  78. double currentZoomSteps = std::round(std::log(currentZoomFactor) / std::log(1.01));
  79. double newZoomSteps = stepsChange != 0 ? currentZoomSteps + stepsChange : stepsChange;
  80. double newZoomFactor = std::pow(1.01, newZoomSteps);
  81. Point currentZoom = targetTileSize;
  82. Point desiredZoom = Point(defaultTileSize,defaultTileSize) * newZoomFactor;
  83. if (desiredZoom == currentZoom && stepsChange < 0)
  84. desiredZoom -= Point(1,1);
  85. if (desiredZoom == currentZoom && stepsChange > 0)
  86. desiredZoom += Point(1,1);
  87. Point minimal = model->getSingleTileSizeLowerLimit();
  88. Point maximal = model->getSingleTileSizeUpperLimit();
  89. Point actualZoom = {
  90. std::clamp(desiredZoom.x, minimal.x, maximal.x),
  91. std::clamp(desiredZoom.y, minimal.y, maximal.y)
  92. };
  93. if (actualZoom != currentZoom)
  94. {
  95. targetTileSize = actualZoom;
  96. if(actualZoom.x >= defaultTileSize - zoomTileDeadArea && actualZoom.x <= defaultTileSize + zoomTileDeadArea)
  97. actualZoom.x = defaultTileSize;
  98. if(actualZoom.y >= defaultTileSize - zoomTileDeadArea && actualZoom.y <= defaultTileSize + zoomTileDeadArea)
  99. actualZoom.y = defaultTileSize;
  100. bool isInDeadZone = targetTileSize != actualZoom || actualZoom == Point(defaultTileSize, defaultTileSize);
  101. if(!wasInDeadZone && isInDeadZone)
  102. GH.input().hapticFeedback();
  103. wasInDeadZone = isInDeadZone;
  104. setTileSize(actualZoom);
  105. }
  106. }
  107. MapViewController::MapViewController(std::shared_ptr<MapViewModel> model, std::shared_ptr<MapViewCache> view)
  108. : state(new MapRendererContextState())
  109. , model(std::move(model))
  110. , view(view)
  111. {
  112. adventureContext = std::make_shared<MapRendererAdventureContext>(*state);
  113. context = adventureContext;
  114. }
  115. std::shared_ptr<IMapRendererContext> MapViewController::getContext() const
  116. {
  117. return context;
  118. }
  119. void MapViewController::tick(uint32_t timeDelta)
  120. {
  121. // confirmed to match H3 for
  122. // - hero embarking on boat (500 ms)
  123. // - hero disembarking from boat (500 ms)
  124. // - TODO: picking up resources
  125. // - TODO: killing mosters
  126. // - teleporting ( 250 ms)
  127. static const double fadeOutDuration = 500;
  128. static const double fadeInDuration = 500;
  129. static const double heroTeleportDuration = 250;
  130. if(movementContext)
  131. {
  132. const auto * object = context->getObject(movementContext->target);
  133. const auto * hero = dynamic_cast<const CGHeroInstance *>(object);
  134. const auto * boat = dynamic_cast<const CGBoat *>(object);
  135. assert(boat || hero);
  136. if(!hero)
  137. hero = boat->hero;
  138. double heroMoveTime = LOCPLINT->playerID == hero->getOwner() ?
  139. settings["adventure"]["heroMoveTime"].Float() :
  140. settings["adventure"]["enemyMoveTime"].Float();
  141. movementContext->progress += timeDelta / heroMoveTime;
  142. movementContext->progress = std::min( 1.0, movementContext->progress);
  143. Point positionFrom = Point(hero->convertToVisitablePos(movementContext->tileFrom)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
  144. Point positionDest = Point(hero->convertToVisitablePos(movementContext->tileDest)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
  145. Point positionCurr = vstd::lerp(positionFrom, positionDest, movementContext->progress);
  146. setViewCenter(positionCurr, movementContext->tileDest.z);
  147. }
  148. if(teleportContext)
  149. {
  150. teleportContext->progress += timeDelta / heroTeleportDuration;
  151. teleportContext->progress = std::min( 1.0, teleportContext->progress);
  152. }
  153. if(fadingOutContext)
  154. {
  155. fadingOutContext->progress -= timeDelta / fadeOutDuration;
  156. fadingOutContext->progress = std::max( 0.0, fadingOutContext->progress);
  157. }
  158. if(fadingInContext)
  159. {
  160. fadingInContext->progress += timeDelta / fadeInDuration;
  161. fadingInContext->progress = std::min( 1.0, fadingInContext->progress);
  162. }
  163. if (adventureContext)
  164. adventureContext->animationTime += timeDelta;
  165. updateState();
  166. }
  167. void MapViewController::updateState()
  168. {
  169. if(adventureContext)
  170. {
  171. adventureContext->settingsSessionSpectate = settings["session"]["spectate"].Bool();
  172. adventureContext->settingsAdventureObjectAnimation = settings["adventure"]["objectAnimation"].Bool();
  173. adventureContext->settingsAdventureTerrainAnimation = settings["adventure"]["terrainAnimation"].Bool();
  174. adventureContext->settingShowGrid = settings["gameTweaks"]["showGrid"].Bool();
  175. adventureContext->settingShowVisitable = settings["session"]["showVisitable"].Bool();
  176. adventureContext->settingShowBlocked = settings["session"]["showBlocked"].Bool();
  177. adventureContext->settingSpellRange = settings["session"]["showSpellRange"].Bool();
  178. }
  179. }
  180. void MapViewController::afterRender()
  181. {
  182. if(movementContext)
  183. {
  184. const auto * object = context->getObject(movementContext->target);
  185. const auto * hero = dynamic_cast<const CGHeroInstance *>(object);
  186. const auto * boat = dynamic_cast<const CGBoat *>(object);
  187. assert(boat || hero);
  188. if(!hero)
  189. hero = boat->hero;
  190. if(movementContext->progress >= 0.999)
  191. {
  192. logGlobal->debug("Ending movement animation");
  193. setViewCenter(hero->getSightCenter());
  194. removeObject(context->getObject(movementContext->target));
  195. addObject(context->getObject(movementContext->target));
  196. activateAdventureContext(movementContext->animationTime);
  197. }
  198. }
  199. if(teleportContext && teleportContext->progress >= 0.999)
  200. {
  201. logGlobal->debug("Ending teleport animation");
  202. activateAdventureContext(teleportContext->animationTime);
  203. }
  204. if(fadingOutContext && fadingOutContext->progress <= 0.001)
  205. {
  206. logGlobal->debug("Ending fade out animation");
  207. removeObject(context->getObject(fadingOutContext->target));
  208. activateAdventureContext(fadingOutContext->animationTime);
  209. }
  210. if(fadingInContext && fadingInContext->progress >= 0.999)
  211. {
  212. logGlobal->debug("Ending fade in animation");
  213. activateAdventureContext(fadingInContext->animationTime);
  214. }
  215. }
  216. bool MapViewController::isEventInstant(const CGObjectInstance * obj, const PlayerColor & initiator)
  217. {
  218. if(settings["gameTweaks"]["skipAdventureMapAnimations"].Bool())
  219. return true;
  220. if (!isEventVisible(obj, initiator))
  221. return true;
  222. if(initiator != LOCPLINT->playerID && settings["adventure"]["enemyMoveTime"].Float() <= 0)
  223. return true; // instant movement speed
  224. if(initiator == LOCPLINT->playerID && settings["adventure"]["heroMoveTime"].Float() <= 0)
  225. return true; // instant movement speed
  226. return false;
  227. }
  228. bool MapViewController::isEventVisible(const CGObjectInstance * obj, const PlayerColor & initiator)
  229. {
  230. if(adventureContext == nullptr)
  231. return false;
  232. if(initiator != LOCPLINT->playerID && settings["adventure"]["enemyMoveTime"].Float() < 0)
  233. return false; // enemy move speed set to "hidden/none"
  234. if(!GH.windows().isTopWindow(adventureInt))
  235. return false;
  236. // do not focus on actions of other players except for AI with simturns off
  237. if (initiator != LOCPLINT->playerID && initiator.isValidPlayer())
  238. {
  239. if (LOCPLINT->makingTurn)
  240. return false;
  241. if (LOCPLINT->cb->getStartInfo()->playerInfos.at(initiator).isControlledByHuman() && !settings["session"]["adventureTrackHero"].Bool())
  242. return false;
  243. }
  244. if(obj->isVisitable())
  245. return context->isVisible(obj->visitablePos());
  246. else
  247. return context->isVisible(obj->pos);
  248. }
  249. bool MapViewController::isEventVisible(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  250. {
  251. if(adventureContext == nullptr)
  252. return false;
  253. if(obj->getOwner() != LOCPLINT->playerID && settings["adventure"]["enemyMoveTime"].Float() < 0)
  254. return false; // enemy move speed set to "hidden/none"
  255. if(!GH.windows().isTopWindow(adventureInt))
  256. return false;
  257. // do not focus on actions of other players except for AI with simturns off
  258. if (obj->getOwner() != LOCPLINT->playerID && obj->getOwner().isValidPlayer())
  259. {
  260. if (LOCPLINT->makingTurn)
  261. return false;
  262. if (LOCPLINT->cb->getStartInfo()->playerInfos.at(obj->getOwner()).isControlledByHuman() && !settings["session"]["adventureTrackHero"].Bool())
  263. return false;
  264. }
  265. if(context->isVisible(obj->convertToVisitablePos(from)))
  266. return true;
  267. if(context->isVisible(obj->convertToVisitablePos(dest)))
  268. return true;
  269. return false;
  270. }
  271. void MapViewController::fadeOutObject(const CGObjectInstance * obj)
  272. {
  273. logGlobal->debug("Starting fade out animation");
  274. fadingOutContext = std::make_shared<MapRendererAdventureFadingContext>(*state);
  275. fadingOutContext->animationTime = adventureContext->animationTime;
  276. adventureContext = fadingOutContext;
  277. context = fadingOutContext;
  278. const CGObjectInstance * movingObject = obj;
  279. if (obj->ID == Obj::HERO)
  280. {
  281. auto * hero = dynamic_cast<const CGHeroInstance*>(obj);
  282. if (hero->boat)
  283. movingObject = hero->boat;
  284. }
  285. fadingOutContext->target = movingObject->id;
  286. fadingOutContext->progress = 1.0;
  287. }
  288. void MapViewController::fadeInObject(const CGObjectInstance * obj)
  289. {
  290. logGlobal->debug("Starting fade in animation");
  291. fadingInContext = std::make_shared<MapRendererAdventureFadingContext>(*state);
  292. fadingInContext->animationTime = adventureContext->animationTime;
  293. adventureContext = fadingInContext;
  294. context = fadingInContext;
  295. const CGObjectInstance * movingObject = obj;
  296. if (obj->ID == Obj::HERO)
  297. {
  298. auto * hero = dynamic_cast<const CGHeroInstance*>(obj);
  299. if (hero->boat)
  300. movingObject = hero->boat;
  301. }
  302. fadingInContext->target = movingObject->id;
  303. fadingInContext->progress = 0.0;
  304. }
  305. void MapViewController::removeObject(const CGObjectInstance * obj)
  306. {
  307. if (obj->ID == Obj::BOAT)
  308. {
  309. auto * boat = dynamic_cast<const CGBoat*>(obj);
  310. if (boat->hero)
  311. {
  312. view->invalidate(context, boat->hero->id);
  313. state->removeObject(boat->hero);
  314. }
  315. }
  316. if (obj->ID == Obj::HERO)
  317. {
  318. auto * hero = dynamic_cast<const CGHeroInstance*>(obj);
  319. if (hero->boat)
  320. {
  321. view->invalidate(context, hero->boat->id);
  322. state->removeObject(hero->boat);
  323. }
  324. }
  325. view->invalidate(context, obj->id);
  326. state->removeObject(obj);
  327. }
  328. void MapViewController::addObject(const CGObjectInstance * obj)
  329. {
  330. state->addObject(obj);
  331. view->invalidate(context, obj->id);
  332. }
  333. void MapViewController::onBeforeHeroEmbark(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  334. {
  335. if(isEventVisible(obj, from, dest))
  336. {
  337. if (!isEventInstant(obj, obj->getOwner()))
  338. fadeOutObject(obj);
  339. setViewCenter(obj->getSightCenter());
  340. }
  341. else
  342. removeObject(obj);
  343. }
  344. void MapViewController::onAfterHeroEmbark(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  345. {
  346. if(isEventVisible(obj, from, dest))
  347. setViewCenter(obj->getSightCenter());
  348. }
  349. void MapViewController::onBeforeHeroDisembark(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  350. {
  351. if(isEventVisible(obj, from, dest))
  352. setViewCenter(obj->getSightCenter());
  353. }
  354. void MapViewController::onAfterHeroDisembark(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  355. {
  356. if(isEventVisible(obj, from, dest))
  357. {
  358. if (!isEventInstant(obj, obj->getOwner()))
  359. fadeInObject(obj);
  360. setViewCenter(obj->getSightCenter());
  361. }
  362. addObject(obj);
  363. }
  364. void MapViewController::onObjectFadeIn(const CGObjectInstance * obj, const PlayerColor & initiator)
  365. {
  366. assert(!hasOngoingAnimations());
  367. if(isEventVisible(obj, initiator) && !isEventInstant(obj, initiator) )
  368. fadeInObject(obj);
  369. addObject(obj);
  370. }
  371. void MapViewController::onObjectFadeOut(const CGObjectInstance * obj, const PlayerColor & initiator)
  372. {
  373. assert(!hasOngoingAnimations());
  374. if(isEventVisible(obj, initiator) && !isEventInstant(obj, initiator) )
  375. fadeOutObject(obj);
  376. else
  377. removeObject(obj);
  378. }
  379. void MapViewController::onObjectInstantAdd(const CGObjectInstance * obj, const PlayerColor & initiator)
  380. {
  381. addObject(obj);
  382. };
  383. void MapViewController::onObjectInstantRemove(const CGObjectInstance * obj, const PlayerColor & initiator)
  384. {
  385. removeObject(obj);
  386. };
  387. void MapViewController::onBeforeHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  388. {
  389. assert(!hasOngoingAnimations());
  390. if(isEventVisible(obj, from, dest))
  391. {
  392. setViewCenter(obj->getSightCenter());
  393. view->createTransitionSnapshot(context);
  394. }
  395. }
  396. void MapViewController::onAfterHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  397. {
  398. assert(!hasOngoingAnimations());
  399. const CGObjectInstance * movingObject = obj;
  400. if(obj->boat)
  401. movingObject = obj->boat;
  402. removeObject(movingObject);
  403. addObject(movingObject);
  404. if(isEventVisible(obj, from, dest))
  405. {
  406. logGlobal->debug("Starting teleport animation");
  407. teleportContext = std::make_shared<MapRendererAdventureTransitionContext>(*state);
  408. teleportContext->animationTime = adventureContext->animationTime;
  409. adventureContext = teleportContext;
  410. context = teleportContext;
  411. setViewCenter(movingObject->getSightCenter());
  412. }
  413. }
  414. void MapViewController::onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  415. {
  416. assert(!hasOngoingAnimations());
  417. // revisiting via spacebar, no need to animate
  418. if(from == dest)
  419. return;
  420. const CGObjectInstance * movingObject = obj;
  421. if(obj->boat)
  422. movingObject = obj->boat;
  423. removeObject(movingObject);
  424. if(!isEventVisible(obj, from, dest))
  425. {
  426. addObject(movingObject);
  427. return;
  428. }
  429. double movementTime = LOCPLINT->playerID == obj->tempOwner ?
  430. settings["adventure"]["heroMoveTime"].Float() :
  431. settings["adventure"]["enemyMoveTime"].Float();
  432. if(movementTime > 1)
  433. {
  434. logGlobal->debug("Starting movement animation");
  435. movementContext = std::make_shared<MapRendererAdventureMovingContext>(*state);
  436. movementContext->animationTime = adventureContext->animationTime;
  437. adventureContext = movementContext;
  438. context = movementContext;
  439. state->addMovingObject(movingObject, from, dest);
  440. movementContext->target = movingObject->id;
  441. movementContext->tileFrom = from;
  442. movementContext->tileDest = dest;
  443. movementContext->progress = 0.0;
  444. }
  445. else // instant movement
  446. {
  447. addObject(movingObject);
  448. setViewCenter(movingObject->visitablePos());
  449. }
  450. }
  451. bool MapViewController::hasOngoingAnimations()
  452. {
  453. if(movementContext)
  454. return true;
  455. if(fadingOutContext)
  456. return true;
  457. if(fadingInContext)
  458. return true;
  459. if(teleportContext)
  460. return true;
  461. return false;
  462. }
  463. void MapViewController::activateAdventureContext(uint32_t animationTime)
  464. {
  465. resetContext();
  466. adventureContext = std::make_shared<MapRendererAdventureContext>(*state);
  467. adventureContext->animationTime = animationTime;
  468. context = adventureContext;
  469. updateState();
  470. }
  471. void MapViewController::activateAdventureContext()
  472. {
  473. activateAdventureContext(0);
  474. }
  475. void MapViewController::activateWorldViewContext()
  476. {
  477. if(worldViewContext)
  478. return;
  479. resetContext();
  480. worldViewContext = std::make_shared<MapRendererWorldViewContext>(*state);
  481. context = worldViewContext;
  482. }
  483. void MapViewController::activateSpellViewContext()
  484. {
  485. if(spellViewContext)
  486. return;
  487. resetContext();
  488. spellViewContext = std::make_shared<MapRendererSpellViewContext>(*state);
  489. worldViewContext = spellViewContext;
  490. context = spellViewContext;
  491. }
  492. void MapViewController::activatePuzzleMapContext(const int3 & grailPosition)
  493. {
  494. resetContext();
  495. puzzleMapContext = std::make_shared<MapRendererPuzzleMapContext>(*state);
  496. context = puzzleMapContext;
  497. CGPathNode fakeNode;
  498. fakeNode.coord = grailPosition;
  499. puzzleMapContext->grailPos = std::make_unique<CGPath>();
  500. // create two nodes since 1st one is normally not visible
  501. puzzleMapContext->grailPos->nodes.push_back(fakeNode);
  502. puzzleMapContext->grailPos->nodes.push_back(fakeNode);
  503. }
  504. void MapViewController::resetContext()
  505. {
  506. adventureContext.reset();
  507. movementContext.reset();
  508. fadingOutContext.reset();
  509. fadingInContext.reset();
  510. teleportContext.reset();
  511. worldViewContext.reset();
  512. spellViewContext.reset();
  513. puzzleMapContext.reset();
  514. }
  515. void MapViewController::setTerrainVisibility(bool showAllTerrain)
  516. {
  517. assert(spellViewContext);
  518. spellViewContext->showAllTerrain = showAllTerrain;
  519. }
  520. void MapViewController::setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions)
  521. {
  522. assert(spellViewContext);
  523. spellViewContext->additionalOverlayIcons = objectPositions;
  524. }