1 /*
2  *  The ManaPlus Client
3  *  Copyright (C) 2004-2009  The Mana World Development Team
4  *  Copyright (C) 2009-2010  The Mana Developers
5  *  Copyright (C) 2011-2019  The ManaPlus Developers
6  *  Copyright (C) 2019-2021  Andrei Karas
7  *
8  *  This file is part of The ManaPlus Client.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef RESOURCES_MAP_MAPLAYER_H
25 #define RESOURCES_MAP_MAPLAYER_H
26 
27 #include "listeners/configlistener.h"
28 
29 #include "resources/memorycounter.h"
30 
31 #include "being/actor.h"
32 
33 #include "enums/resources/map/maptype.h"
34 
35 #include "utils/vector.h"
36 
37 #include "resources/map/tileinfo.h"
38 
39 class Image;
40 class MapRowVertexes;
41 class SpecialLayer;
42 
43 struct MetaTile;
44 
45 /**
46  * A map layer. Stores a grid of tiles and their offset, and implements layer
47  * rendering.
48  */
49 class MapLayer final : public MemoryCounter, public ConfigListener
50 {
51     public:
52         friend class Map;
53 
54         /**
55          * Constructor, taking layer origin, size and whether this layer is the
56          * fringe layer. The fringe layer is the layer that draws the actors.
57          * There can be only one fringe layer per map.
58          */
59         MapLayer(const std::string &name,
60                  const int x,
61                  const int y,
62                  const int width,
63                  const int height,
64                  const bool isFringeLayer,
65                  const int mask,
66                  const int tileCondition);
67 
68         A_DELETE_COPY(MapLayer)
69 
70         /**
71          * Destructor.
72          */
73         ~MapLayer() override final;
74 
75         /**
76          * Set tile image, with x and y in layer coordinates.
77          */
setTile(const int x,const int y,Image * restrict const img)78         constexpr3 void setTile(const int x,
79                                 const int y,
80                                 Image *restrict const img) restrict
81         {
82             mTiles[x + y * mWidth].image = img;
83         }
84 
85         /**
86          * Set tile image with x + y * width already known.
87          */
setTile(const int index,Image * restrict const img)88         constexpr3 void setTile(const int index,
89                                 Image *restrict const img) restrict
90         { mTiles[index].image = img; }
91 
92         /**
93          * Draws this layer to the given graphics context. The coordinates are
94          * expected to be in map range and will be translated to local layer
95          * coordinates and clipped to the layer's dimensions.
96          *
97          * The given actors are only drawn when this layer is the fringe
98          * layer.
99          */
100         void draw(Graphics *restrict const graphics,
101                   int startX,
102                   int startY,
103                   int endX,
104                   int endY,
105                   const int scrollX,
106                   const int scrollY) const restrict A_NONNULL(2);
107 
108         void drawSDL(Graphics *restrict const graphics) const restrict2
109                      A_NONNULL(2);
110 
111 #ifdef USE_OPENGL
112         void drawOGL(Graphics *restrict const graphics) const restrict2
113                      A_NONNULL(2);
114 
115         void updateOGL(Graphics *restrict const graphics,
116                        int startX,
117                        int startY,
118                        int endX,
119                        int endY,
120                        const int scrollX,
121                        const int scrollY) restrict2 A_NONNULL(2);
122 #endif  // USE_OPENGL
123 
124         void updateSDL(const Graphics *restrict const graphics,
125                        int startX,
126                        int startY,
127                        int endX,
128                        int endY,
129                        const int scrollX,
130                        const int scrollY) restrict2 A_NONNULL(2);
131 
132         void drawFringe(Graphics *restrict const graphics,
133                         int startX,
134                         int startY,
135                         int endX,
136                         int endY,
137                         const int scrollX,
138                         const int scrollY,
139                         const Actors &actors) const restrict A_NONNULL(2);
140 
isFringeLayer()141         constexpr3 bool isFringeLayer() const restrict noexcept2 A_WARN_UNUSED
142         { return mIsFringeLayer; }
143 
setSpecialLayer(const SpecialLayer * restrict const val)144         void setSpecialLayer(const SpecialLayer *restrict const val)
145                              restrict noexcept2
146         { mSpecialLayer = val; }
147 
setTempLayer(const SpecialLayer * restrict const val)148         void setTempLayer(const SpecialLayer *restrict const val)
149                           restrict noexcept2
150         { mTempLayer = val; }
151 
getWidth()152         constexpr3 int getWidth() const restrict noexcept2 A_WARN_UNUSED
153         { return mWidth; }
154 
getHeight()155         constexpr3 int getHeight() const restrict noexcept2 A_WARN_UNUSED
156         { return mHeight; }
157 
158         void optionChanged(const std::string &restrict value)
159                            restrict override final;
160 
setDrawLayerFlags(const MapTypeT & restrict n)161         void setDrawLayerFlags(const MapTypeT &restrict n)
162                                restrict noexcept2
163         {
164             mDrawLayerFlags = n;
165             mSpecialFlag = (mDrawLayerFlags != MapType::SPECIAL &&
166                 mDrawLayerFlags != MapType::SPECIAL2 &&
167                 mDrawLayerFlags != MapType::SPECIAL4);
168         }
169 
setActorsFix(const int y)170         void setActorsFix(const int y) restrict noexcept2
171         { mActorsFix = y; }
172 
173         int calcMemoryLocal() const override final;
174 
175         int calcMemoryChilds(const int level) const override final;
176 
getCounterName()177         std::string getCounterName() const override final
178         { return mName; }
179 
180 #ifdef UNITTESTS
getTiles()181         constexpr3 TileInfo *getTiles() const restrict noexcept2
182         {
183             return mTiles;
184         }
185 
setTileCondition(const int c)186         void setTileCondition(const int c) restrict noexcept2
187         {
188             mTileCondition = c;
189         }
190 #endif  // UNITTESTS
191 
192 #ifndef UNITTESTS
193     protected:
194 #endif  // UNITTESTS
195         static int getTileDrawWidth(const TileInfo *restrict img,
196                                     const int endX,
197                                     int &restrict width,
198                                     int &restrict nextTile)
199                                     A_WARN_UNUSED A_NONNULL(1);
200 
201         static int getEmptyTileDrawWidth(const TileInfo *restrict img,
202                                          const int endX,
203                                          int &restrict nextTile)
204                                          A_WARN_UNUSED A_NONNULL(1);
205 
206         void updateConditionTiles(const MetaTile *restrict const metaTiles,
207                                   const int width,
208                                   const int height) restrict A_NONNULL(2);
209 
210         void updateCache(const int width,
211                          const int height) restrict;
212 
213         void drawSpecialLayer(Graphics *const graphics,
214                               const int y,
215                               const int startX,
216                               const int endX,
217                               const int scrollX,
218                               const int scrollY) const restrict;
219 
220     private:
221         const int mX;
222         const int mY;
223         const int mPixelX;
224         const int mPixelY;
225         const int mWidth;
226         const int mHeight;
227         TileInfo *restrict const mTiles;
228         MapTypeT mDrawLayerFlags;
229         const SpecialLayer *restrict mSpecialLayer;
230         const SpecialLayer *restrict mTempLayer;
231         const std::string mName;
232         typedef STD_VECTOR<MapRowVertexes*> MapRows;
233         MapRows mTempRows;
234         int mMask;
235         int mTileCondition;
236         int mActorsFix;
237         const bool mIsFringeLayer;    /**< Whether the actors are drawn. */
238         bool mHighlightAttackRange;
239         bool mSpecialFlag;
240 };
241 
242 #endif  // RESOURCES_MAP_MAPLAYER_H
243