mapHandler.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * mapHandler.h, 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. #pragma once
  11. #include "../lib/int3.h"
  12. #include "../lib/spells/ViewSpellInt.h"
  13. #include "gui/Geometries.h"
  14. #include "SDL.h"
  15. class CGObjectInstance;
  16. class CGHeroInstance;
  17. class CGBoat;
  18. class CMap;
  19. struct TerrainTile;
  20. struct SDL_Surface;
  21. struct SDL_Rect;
  22. class CAnimation;
  23. class IImage;
  24. class CFadeAnimation;
  25. class PlayerColor;
  26. enum class EWorldViewIcon
  27. {
  28. TOWN = 0,
  29. HERO,
  30. ARTIFACT,
  31. TELEPORT,
  32. GATE,
  33. MINE_WOOD,
  34. MINE_MERCURY,
  35. MINE_STONE,
  36. MINE_SULFUR,
  37. MINE_CRYSTAL,
  38. MINE_GEM,
  39. MINE_GOLD,
  40. RES_WOOD,
  41. RES_MERCURY,
  42. RES_STONE,
  43. RES_SULFUR,
  44. RES_CRYSTAL,
  45. RES_GEM,
  46. RES_GOLD,
  47. };
  48. enum class EMapObjectFadingType
  49. {
  50. NONE,
  51. IN,
  52. OUT
  53. };
  54. enum class EMapAnimRedrawStatus
  55. {
  56. OK,
  57. REDRAW_REQUESTED // map blitter requests quick redraw due to current animation
  58. };
  59. struct TerrainTileObject
  60. {
  61. const CGObjectInstance * obj;
  62. SDL_Rect rect;
  63. int fadeAnimKey;
  64. TerrainTileObject(const CGObjectInstance * obj_, SDL_Rect rect_);
  65. ~TerrainTileObject();
  66. };
  67. struct TerrainTile2
  68. {
  69. std::vector<TerrainTileObject> objects; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
  70. };
  71. struct MapDrawingInfo
  72. {
  73. bool scaled;
  74. int3 & topTile; // top-left tile in viewport [in tiles]
  75. const std::vector<std::vector<std::vector<ui8>>> * visibilityMap;
  76. SDL_Rect * drawBounds; // map rect drawing bounds on screen
  77. std::shared_ptr<CAnimation> icons; // holds overlay icons for world view mode
  78. float scale; // map scale for world view mode (only if scaled == true)
  79. bool otherheroAnim;
  80. ui8 anim;
  81. ui8 heroAnim;
  82. int3 movement; // used for smooth map movement
  83. bool puzzleMode;
  84. int3 grailPos; // location of grail for puzzle mode [in tiles]
  85. const std::vector<ObjectPosInfo> * additionalIcons;
  86. bool showAllTerrain; //for expert viewEarth
  87. MapDrawingInfo(int3 & topTile_, const std::vector<std::vector<std::vector<ui8>>> * visibilityMap_, SDL_Rect * drawBounds_, std::shared_ptr<CAnimation> icons_ = nullptr)
  88. : 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)
  89. {}
  90. ui8 getHeroAnim() const { return otherheroAnim ? anim : heroAnim; }
  91. };
  92. template<typename T> class PseudoV
  93. {
  94. public:
  95. PseudoV()
  96. : offset(0) {}
  97. inline T & operator[](const int & n)
  98. {
  99. return inver[n + offset];
  100. }
  101. inline const T & operator[](const int & n) const
  102. {
  103. return inver[n + offset];
  104. }
  105. void resize(int rest, int before, int after)
  106. {
  107. inver.resize(before + rest + after);
  108. offset = before;
  109. }
  110. int size() const
  111. {
  112. return inver.size();
  113. }
  114. private:
  115. int offset;
  116. std::vector<T> inver;
  117. };
  118. class CMapHandler
  119. {
  120. enum class EMapCacheType : ui8
  121. {
  122. TERRAIN,
  123. OBJECTS,
  124. ROADS,
  125. RIVERS,
  126. FOW,
  127. HEROES,
  128. HERO_FLAGS,
  129. FRAME,
  130. AFTER_LAST
  131. };
  132. /// temporarily caches rescaled frames for map world view redrawing
  133. class CMapCache
  134. {
  135. std::array<std::map<intptr_t, std::unique_ptr<IImage>>, (ui8)EMapCacheType::AFTER_LAST> data;
  136. float worldViewCachedScale;
  137. public:
  138. CMapCache();
  139. /// destroys all cached data (frees surfaces)
  140. void discardWorldViewCache();
  141. /// updates scale and determines if currently cached data is still valid
  142. void updateWorldViewScale(float scale);
  143. /// asks for cached data; @returns cached data if found, new scaled surface otherwise, may return nullptr in case of scaling error
  144. IImage * requestWorldViewCacheOrCreate(EMapCacheType type, const IImage * fullSurface);
  145. };
  146. /// helper struct to pass around resolved bitmaps of an object; images can be nullptr if object doesn't have bitmap of that type
  147. struct AnimBitmapHolder
  148. {
  149. IImage * objBitmap; // main object bitmap
  150. IImage * flagBitmap; // flag bitmap for the object (probably only for heroes and boats with heroes)
  151. bool isMoving; // indicates if the object is moving (again, heroes/boats only)
  152. AnimBitmapHolder(IImage * objBitmap_ = nullptr, IImage * flagBitmap_ = nullptr, bool moving = false)
  153. : objBitmap(objBitmap_), flagBitmap(flagBitmap_), isMoving(moving)
  154. {}
  155. };
  156. class CMapBlitter
  157. {
  158. protected:
  159. const int FRAMES_PER_MOVE_ANIM_GROUP = 8;
  160. CMapHandler * parent; // ptr to enclosing map handler; generally for legacy reasons, probably could/should be refactored out of here
  161. int tileSize; // size of a tile drawn on map [in pixels]
  162. int halfTileSizeCeil; // half of the tile size, rounded up
  163. int3 tileCount; // number of tiles in current viewport
  164. int3 topTile; // top-left tile of the viewport
  165. int3 initPos; // starting drawing position [in pixels]
  166. int3 pos; // current position [in tiles]
  167. int3 realPos; // current position [in pixels]
  168. Rect realTileRect; // default rect based on current pos: [realPos.x, realPos.y, tileSize, tileSize]
  169. Rect defaultTileRect; // default rect based on 0: [0, 0, tileSize, tileSize]
  170. const MapDrawingInfo * info; // data for drawing passed from outside
  171. /// general drawing method, called internally by more specialized ones
  172. virtual void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const = 0;
  173. // first drawing pass
  174. /// draws terrain bitmap (or custom bitmap if applicable) on current tile
  175. virtual void drawTileTerrain(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile2 & tile) const;
  176. /// draws a river segment on current tile
  177. virtual void drawRiver(SDL_Surface * targetSurf, const TerrainTile & tinfo) const;
  178. /// draws a road segment on current tile
  179. virtual void drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const;
  180. /// draws all objects on current tile (higher-level logic, unlike other draw*** methods)
  181. virtual void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const;
  182. virtual void drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const;
  183. virtual void drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const;
  184. // second drawing pass
  185. /// current tile: draws overlay over the map, used to draw world view icons
  186. virtual void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const = 0;
  187. /// draws fog of war on current tile
  188. virtual void drawFow(SDL_Surface * targetSurf) const;
  189. /// draws map border frame on current position
  190. virtual void drawFrame(SDL_Surface * targetSurf) const;
  191. /// draws additional icons (for VIEW_AIR, VIEW_EARTH spells atm)
  192. virtual void drawOverlayEx(SDL_Surface * targetSurf);
  193. // third drawing pass
  194. /// custom post-processing, if needed (used by puzzle view)
  195. virtual void postProcessing(SDL_Surface * targetSurf) const {}
  196. // misc methods
  197. /// initializes frame-drawing (called at the start of every redraw)
  198. virtual void init(const MapDrawingInfo * drawingInfo) = 0;
  199. /// calculates clip region for map viewport
  200. virtual SDL_Rect clip(SDL_Surface * targetSurf) const = 0;
  201. virtual ui8 getHeroFrameGroup(ui8 dir, bool isMoving) const;
  202. virtual ui8 getPhaseShift(const CGObjectInstance * object) const;
  203. virtual bool canDrawObject(const CGObjectInstance * obj) const;
  204. virtual bool canDrawCurrentTile() const;
  205. // internal helper methods to choose correct bitmap(s) for object; called internally by findObjectBitmap
  206. AnimBitmapHolder findHeroBitmap(const CGHeroInstance * hero, int anim) const;
  207. AnimBitmapHolder findBoatBitmap(const CGBoat * hero, int anim) const;
  208. IImage * findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
  209. IImage * findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
  210. IImage * findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int group, ui8 dir) const;
  211. IImage * findFlagBitmapInternal(std::shared_ptr<CAnimation> animation, int anim, int group, ui8 dir, bool moving) const;
  212. public:
  213. CMapBlitter(CMapHandler * p);
  214. virtual ~CMapBlitter();
  215. void blit(SDL_Surface * targetSurf, const MapDrawingInfo * info);
  216. /// helper method that chooses correct bitmap(s) for given object
  217. AnimBitmapHolder findObjectBitmap(const CGObjectInstance * obj, int anim) const;
  218. };
  219. class CMapNormalBlitter : public CMapBlitter
  220. {
  221. protected:
  222. void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override;
  223. void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override {}
  224. void init(const MapDrawingInfo * info) override;
  225. SDL_Rect clip(SDL_Surface * targetSurf) const override;
  226. public:
  227. CMapNormalBlitter(CMapHandler * parent);
  228. virtual ~CMapNormalBlitter(){}
  229. };
  230. class CMapWorldViewBlitter : public CMapBlitter
  231. {
  232. private:
  233. IImage * objectToIcon(Obj id, si32 subId, PlayerColor owner) const;
  234. protected:
  235. void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override;
  236. void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override;
  237. void drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override;
  238. void drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const override;
  239. void drawFrame(SDL_Surface * targetSurf) const override {}
  240. void drawOverlayEx(SDL_Surface * targetSurf) override;
  241. void init(const MapDrawingInfo * info) override;
  242. SDL_Rect clip(SDL_Surface * targetSurf) const override;
  243. ui8 getPhaseShift(const CGObjectInstance * object) const override { return 0u; }
  244. void calculateWorldViewCameraPos();
  245. public:
  246. CMapWorldViewBlitter(CMapHandler * parent);
  247. virtual ~CMapWorldViewBlitter(){}
  248. };
  249. class CMapPuzzleViewBlitter : public CMapNormalBlitter
  250. {
  251. std::vector<int> unblittableObjects;
  252. void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override;
  253. void drawFow(SDL_Surface * targetSurf) const override {} // skipping FoW in puzzle view
  254. void postProcessing(SDL_Surface * targetSurf) const override;
  255. bool canDrawObject(const CGObjectInstance * obj) const override;
  256. bool canDrawCurrentTile() const override { return true; }
  257. public:
  258. CMapPuzzleViewBlitter(CMapHandler * parent);
  259. };
  260. CMapCache cache;
  261. CMapBlitter * normalBlitter;
  262. CMapBlitter * worldViewBlitter;
  263. CMapBlitter * puzzleViewBlitter;
  264. std::map<int, std::pair<int3, CFadeAnimation *>> fadeAnims;
  265. int fadeAnimCounter;
  266. CMapBlitter * resolveBlitter(const MapDrawingInfo * info) const;
  267. bool updateObjectsFade();
  268. bool startObjectFade(TerrainTileObject & obj, bool in, int3 pos);
  269. void initObjectRects();
  270. void initBorderGraphics();
  271. void initTerrainGraphics();
  272. void prepareFOWDefs();
  273. public:
  274. PseudoV<PseudoV<PseudoV<TerrainTile2>>> ttiles; //informations about map tiles
  275. int3 sizes; //map size (x = width, y = height, z = number of levels)
  276. const CMap * map;
  277. // Max number of tiles that will fit in the map screen. Tiles
  278. // can be partial on each edges.
  279. int tilesW;
  280. int tilesH;
  281. // size of each side of the frame around the whole map, in tiles
  282. int frameH;
  283. int frameW;
  284. // Coord in pixels of the top left corner of the top left tile to
  285. // draw. Values range is [-31..0]. A negative value
  286. // implies that part of the tile won't be displayed.
  287. int offsetX;
  288. int offsetY;
  289. //terrain graphics
  290. //FIXME: unique_ptr should be enough, but fails to compile in MSVS 2013
  291. typedef std::vector<std::array<std::shared_ptr<CAnimation>, 4>> TFlippedAnimations; //[type, rotation]
  292. typedef std::vector<std::vector<std::array<IImage *, 4>>> TFlippedCache; //[type, view type, rotation]
  293. TFlippedAnimations terrainAnimations; //[terrain type, rotation]
  294. TFlippedCache terrainImages; //[terrain type, view type, rotation]
  295. TFlippedAnimations roadAnimations; //[road type, rotation]
  296. TFlippedCache roadImages; //[road type, view type, rotation]
  297. TFlippedAnimations riverAnimations; //[river type, rotation]
  298. TFlippedCache riverImages; //[river type, view type, rotation]
  299. //Fog of War cache (not owned)
  300. std::vector<const IImage *> FoWfullHide;
  301. std::vector<std::vector<std::vector<ui8>>> hideBitmap; //frame indexes (in FoWfullHide) of graphic that should be used to fully hide a tile
  302. std::vector<const IImage *> FoWpartialHide;
  303. //edge graphics
  304. std::unique_ptr<CAnimation> egdeAnimation;
  305. std::vector<const IImage *> egdeImages; //cache of links to egdeAnimation (for faster access)
  306. PseudoV<PseudoV<PseudoV<ui8>>> edgeFrames; //frame indexes (in egdeImages) of tile outside of map
  307. mutable std::map<const CGObjectInstance *, ui8> animationPhase;
  308. CMapHandler();
  309. ~CMapHandler();
  310. void getTerrainDescr(const int3 & pos, std::string & out, bool terName); //if tername == false => empty string when tile is clear
  311. bool printObject(const CGObjectInstance * obj, bool fadein = false); //puts appropriate things to tiles, so obj will be visible on map
  312. 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)
  313. void init();
  314. EMapAnimRedrawStatus drawTerrainRectNew(SDL_Surface * targetSurface, const MapDrawingInfo * info, bool redrawOnlyAnim = false);
  315. void updateWater();
  316. /// determines if the map is ready to handle new hero movement (not available during fading animations)
  317. bool canStartHeroMovement();
  318. void discardWorldViewCache();
  319. static bool compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b);
  320. };