MapViewController.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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 "MapViewModel.h"
  14. #include "../adventureMap/CAdvMapInt.h"
  15. #include "../../lib/CConfigHandler.h"
  16. #include "../../lib/mapObjects/CGHeroInstance.h"
  17. #include "../../lib/mapObjects/MiscObjects.h"
  18. #include "../../lib/spells/ViewSpellInt.h"
  19. void MapViewController::setViewCenter(const int3 & position)
  20. {
  21. assert(context->isInMap(position));
  22. setViewCenter(Point(position) * model->getSingleTileSize() + model->getSingleTileSize() / 2, position.z);
  23. }
  24. void MapViewController::setViewCenter(const Point & position, int level)
  25. {
  26. Point upperLimit = Point(context->getMapSize()) * model->getSingleTileSize() + model->getSingleTileSize();
  27. Point lowerLimit = Point(0,0);
  28. if (context->worldViewModeActive)
  29. {
  30. Point area = model->getPixelsVisibleDimensions();
  31. Point mapCenter = upperLimit / 2;
  32. Point desiredLowerLimit = lowerLimit + area / 2;
  33. Point desiredUpperLimit = upperLimit - area / 2;
  34. Point actualLowerLimit {
  35. std::min(desiredLowerLimit.x, mapCenter.x),
  36. std::min(desiredLowerLimit.y, mapCenter.y)
  37. };
  38. Point actualUpperLimit {
  39. std::max(desiredUpperLimit.x, mapCenter.x),
  40. std::max(desiredUpperLimit.y, mapCenter.y)
  41. };
  42. upperLimit = actualUpperLimit;
  43. lowerLimit = actualLowerLimit;
  44. }
  45. Point betterPosition = {
  46. vstd::clamp(position.x, lowerLimit.x, upperLimit.x),
  47. vstd::clamp(position.y, lowerLimit.y, upperLimit.y)
  48. };
  49. model->setViewCenter(betterPosition);
  50. model->setLevel(vstd::clamp(level, 0, context->getMapSize().z));
  51. if (adventureInt) // may be called before adventureInt is initialized
  52. adventureInt->onMapViewMoved(model->getTilesTotalRect(), model->getLevel());
  53. }
  54. void MapViewController::setTileSize(const Point & tileSize)
  55. {
  56. model->setTileSize(tileSize);
  57. // force update of view center since changing tile size may invalidated it
  58. setViewCenter(model->getMapViewCenter(), model->getLevel());
  59. }
  60. MapViewController::MapViewController(std::shared_ptr<MapViewModel> model)
  61. : context(new MapRendererContext())
  62. , model(std::move(model))
  63. {
  64. }
  65. std::shared_ptr<IMapRendererContext> MapViewController::getContext() const
  66. {
  67. return context;
  68. }
  69. void MapViewController::moveFocusToSelection()
  70. {
  71. const auto * army = adventureInt->curArmy();
  72. if (army)
  73. setViewCenter(army->getSightCenter());
  74. }
  75. void MapViewController::update(uint32_t timeDelta)
  76. {
  77. // confirmed to match H3 for
  78. // - hero embarking on boat (500 ms)
  79. // - hero disembarking from boat (500 ms)
  80. // - TODO: picking up resources
  81. // - TODO: killing mosters
  82. // - teleporting ( 250 ms)
  83. static const double fadeOutDuration = 500;
  84. static const double fadeInDuration = 500;
  85. static const double heroTeleportDuration = 250;
  86. //FIXME: remove code duplication?
  87. if(context->movementAnimation)
  88. {
  89. const auto * object = context->getObject(context->movementAnimation->target);
  90. const auto * hero = dynamic_cast<const CGHeroInstance*>(object);
  91. const auto * boat = dynamic_cast<const CGBoat*>(object);
  92. assert(boat || hero);
  93. if (!hero)
  94. hero = boat->hero;
  95. // TODO: enemyMoveTime
  96. double heroMoveTime = settings["adventure"]["heroMoveTime"].Float();
  97. context->movementAnimation->progress += timeDelta / heroMoveTime;
  98. Point positionFrom = Point(hero->convertToVisitablePos(context->movementAnimation->tileFrom)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
  99. Point positionDest = Point(hero->convertToVisitablePos(context->movementAnimation->tileDest)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
  100. Point positionCurr = vstd::lerp(positionFrom, positionDest, context->movementAnimation->progress);
  101. if(context->movementAnimation->progress >= 1.0)
  102. {
  103. setViewCenter(hero->getSightCenter());
  104. context->removeObject(context->getObject(context->movementAnimation->target));
  105. context->addObject(context->getObject(context->movementAnimation->target));
  106. context->movementAnimation.reset();
  107. }
  108. else
  109. {
  110. setViewCenter(positionCurr, context->movementAnimation->tileDest.z);
  111. }
  112. }
  113. if(context->teleportAnimation)
  114. {
  115. context->teleportAnimation->progress += timeDelta / heroTeleportDuration;
  116. moveFocusToSelection();
  117. if(context->teleportAnimation->progress >= 1.0)
  118. context->teleportAnimation.reset();
  119. }
  120. if(context->fadeOutAnimation)
  121. {
  122. context->fadeOutAnimation->progress += timeDelta / fadeOutDuration;
  123. moveFocusToSelection();
  124. if(context->fadeOutAnimation->progress >= 1.0)
  125. {
  126. context->removeObject(context->getObject(context->fadeOutAnimation->target));
  127. context->fadeOutAnimation.reset();
  128. }
  129. }
  130. if(context->fadeInAnimation)
  131. {
  132. context->fadeInAnimation->progress += timeDelta / fadeInDuration;
  133. moveFocusToSelection();
  134. if(context->fadeInAnimation->progress >= 1.0)
  135. context->fadeInAnimation.reset();
  136. }
  137. context->animationTime += timeDelta;
  138. context->worldViewModeActive = model->getSingleTileSize() != Point(32,32);
  139. context->settingsSessionSpectate = settings["session"]["spectate"].Bool();
  140. context->settingsAdventureObjectAnimation = settings["adventure"]["objectAnimation"].Bool();
  141. context->settingsAdventureTerrainAnimation = settings["adventure"]["terrainAnimation"].Bool();
  142. context->settingsSessionShowGrid = settings["gameTweaks"]["showGrid"].Bool();
  143. context->settingsSessionShowVisitable = settings["session"]["showVisitable"].Bool();
  144. context->settingsSessionShowBlockable = settings["session"]["showBlockable"].Bool();
  145. }
  146. void MapViewController::onObjectFadeIn(const CGObjectInstance * obj)
  147. {
  148. bool actionVisible = context->isVisible(obj->pos);
  149. assert(!context->fadeInAnimation);
  150. if (actionVisible)
  151. context->fadeInAnimation = FadingAnimationState{obj->id, 0.0};
  152. context->addObject(obj);
  153. }
  154. void MapViewController::onObjectFadeOut(const CGObjectInstance * obj)
  155. {
  156. bool actionVisible = context->isVisible(obj->pos);
  157. assert(!context->fadeOutAnimation);
  158. if (actionVisible)
  159. context->fadeOutAnimation = FadingAnimationState{obj->id, 0.0};
  160. else
  161. context->removeObject(obj);
  162. }
  163. void MapViewController::onObjectInstantAdd(const CGObjectInstance * obj)
  164. {
  165. context->addObject(obj);
  166. };
  167. void MapViewController::onObjectInstantRemove(const CGObjectInstance * obj)
  168. {
  169. context->removeObject(obj);
  170. };
  171. void MapViewController::onHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  172. {
  173. assert(!context->teleportAnimation);
  174. bool actionVisible = context->isVisible(from) || context->isVisible(dest);
  175. if (actionVisible)
  176. {
  177. context->teleportAnimation = HeroAnimationState{obj->id, from, dest, 0.0};
  178. }
  179. else
  180. {
  181. context->removeObject(obj);
  182. context->addObject(obj);
  183. }
  184. }
  185. void MapViewController::onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  186. {
  187. assert(!context->movementAnimation);
  188. bool actionVisible = context->isVisible(from) || context->isVisible(dest);
  189. const CGObjectInstance * movingObject = obj;
  190. if(obj->boat)
  191. movingObject = obj->boat;
  192. context->removeObject(movingObject);
  193. if(settings["adventure"]["heroMoveTime"].Float() > 1 && actionVisible)
  194. {
  195. context->addMovingObject(movingObject, from, dest);
  196. context->movementAnimation = HeroAnimationState{movingObject->id, from, dest, 0.0};
  197. }
  198. else
  199. {
  200. // instant movement
  201. context->addObject(movingObject);
  202. if (actionVisible)
  203. setViewCenter(movingObject->visitablePos());
  204. }
  205. }
  206. void MapViewController::onHeroRotated(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  207. {
  208. //TODO. Or no-op?
  209. }
  210. bool MapViewController::hasOngoingAnimations()
  211. {
  212. if(context->movementAnimation)
  213. return true;
  214. if(context->teleportAnimation)
  215. return true;
  216. if(context->fadeOutAnimation)
  217. return true;
  218. if(context->fadeInAnimation)
  219. return true;
  220. return false;
  221. }
  222. void MapViewController::setTerrainVisibility(bool showAllTerrain)
  223. {
  224. context->showAllTerrain = showAllTerrain;
  225. }
  226. void MapViewController::setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions)
  227. {
  228. context->additionalOverlayIcons = objectPositions;
  229. }