1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name minimap.cpp - The minimap source file. */
12 //
13 // (c) Copyright 1998-2019 by Lutz Sammer and Jimmy Salmon, Pali Rohár and Andrettin
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; only version 2 of the License.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 // 02111-1307, USA.
28 //
29
30 //@{
31
32 /*----------------------------------------------------------------------------
33 -- Includes
34 ----------------------------------------------------------------------------*/
35
36 #include <string.h>
37
38 #include "stratagus.h"
39
40 #include "map/minimap.h"
41
42 #include "editor.h"
43 #include "map/map.h"
44 #include "map/map_layer.h"
45 #include "map/terrain_type.h"
46 #include "map/tileset.h"
47 #include "plane.h"
48 #include "player.h"
49 #include "province.h"
50 #include "ui/ui.h"
51 #include "unit/unit.h"
52 #include "unit/unit_manager.h"
53 #include "unit/unittype.h"
54 #include "video.h"
55 #include "world.h"
56
57 /*----------------------------------------------------------------------------
58 -- Defines
59 ----------------------------------------------------------------------------*/
60
61 #define MINIMAP_FAC (16 * 3) /// integer scale factor
62
63 /// unit attacked are shown red for at least this amount of cycles
64 #define ATTACK_RED_DURATION (1 * CYCLES_PER_SECOND)
65 /// unit attacked are shown blinking for this amount of cycles
66 #define ATTACK_BLINK_DURATION (7 * CYCLES_PER_SECOND)
67
68 #define SCALE_PRECISION 100
69
70
71 /*----------------------------------------------------------------------------
72 -- Variables
73 ----------------------------------------------------------------------------*/
74
75 //Wyrmgus start
76 //SDL_Surface *MinimapSurface; /// generated minimap
77 //SDL_Surface *MinimapTerrainSurface; /// generated minimap terrain
78 std::vector<SDL_Surface *> MinimapSurface; /// generated minimap
79 std::vector<SDL_Surface *> MinimapTerrainSurface; /// generated minimap terrain
80 //Wyrmgus end
81
82 #if defined(USE_OPENGL) || defined(USE_GLES)
83 //Wyrmgus start
84 //unsigned char *MinimapSurfaceGL;
85 //unsigned char *MinimapTerrainSurfaceGL;
86 std::vector<unsigned char *> MinimapSurfaceGL;
87 std::vector<unsigned char *> MinimapTerrainSurfaceGL;
88 //Wyrmgus end
89
90 //Wyrmgus start
91 //static GLuint MinimapTexture;
92 //static int MinimapTextureWidth;
93 //static int MinimapTextureHeight;
94 static std::vector<GLuint> MinimapTexture;
95 static std::vector<int> MinimapTextureWidth;
96 static std::vector<int> MinimapTextureHeight;
97 //Wyrmgus end
98 #endif
99
100 //Wyrmgus start
101 //static int *Minimap2MapX; /// fast conversion table
102 //static int *Minimap2MapY; /// fast conversion table
103 //static int Map2MinimapX[MaxMapWidth]; /// fast conversion table
104 //static int Map2MinimapY[MaxMapHeight]; /// fast conversion table
105 static std::vector<int *> Minimap2MapX; /// fast conversion table
106 static std::vector<int *> Minimap2MapY; /// fast conversion table
107 static std::vector<int *> Map2MinimapX; /// fast conversion table
108 static std::vector<int *> Map2MinimapY; /// fast conversion table
109 //Wyrmgus end
110
111 // MinimapScale:
112 // 32x32 64x64 96x96 128x128 256x256 512x512 ...
113 // *4 *2 *4/3 *1 *1/2 *1/4
114 //Wyrmgus start
115 //static int MinimapScaleX; /// Minimap scale to fit into window
116 //static int MinimapScaleY; /// Minimap scale to fit into window
117 static std::vector<int> MinimapScaleX; /// Minimap scale to fit into window
118 static std::vector<int> MinimapScaleY; /// Minimap scale to fit into window
119 //Wyrmgus end
120
121 #define MAX_MINIMAP_EVENTS 8
122
123 struct MinimapEvent {
124 PixelPos pos;
125 int Size;
126 Uint32 Color;
127 } MinimapEvents[MAX_MINIMAP_EVENTS];
128 int NumMinimapEvents;
129
130
131 /*----------------------------------------------------------------------------
132 -- Functions
133 ----------------------------------------------------------------------------*/
134
135
136 #if defined(USE_OPENGL) || defined(USE_GLES)
137 /**
138 ** Create the minimap texture
139 */
140 //Wyrmgus start
141 //static void CreateMinimapTexture()
CreateMinimapTexture(int z)142 static void CreateMinimapTexture(int z)
143 //Wyrmgus end
144 {
145 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
146 //Wyrmgus start
147 // glGenTextures(1, &MinimapTexture);
148 // glBindTexture(GL_TEXTURE_2D, MinimapTexture);
149 glGenTextures(1, &MinimapTexture[z]);
150 glBindTexture(GL_TEXTURE_2D, MinimapTexture[z]);
151 //Wyrmgus end
152 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
153 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
155 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
156 //Wyrmgus start
157 // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MinimapTextureWidth,
158 // MinimapTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
159 // MinimapSurfaceGL);
160 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MinimapTextureWidth[z],
161 MinimapTextureHeight[z], 0, GL_RGBA, GL_UNSIGNED_BYTE,
162 MinimapSurfaceGL[z]);
163 //Wyrmgus end
164 }
165 #endif
166
167 /**
168 ** Create a mini-map from the tiles of the map.
169 **
170 ** @todo Scaling and scrolling the minmap is currently not supported.
171 */
Create()172 void CMinimap::Create()
173 {
174 //Wyrmgus start
175 /*
176 // Scale to biggest value.
177 const int n = std::max(std::max(Map.Info.MapWidth, Map.Info.MapHeight), 32);
178
179 MinimapScaleX = (W * MINIMAP_FAC + n - 1) / n;
180 MinimapScaleY = (H * MINIMAP_FAC + n - 1) / n;
181
182 XOffset = (W - (Map.Info.MapWidth * MinimapScaleX) / MINIMAP_FAC + 1) / 2;
183 YOffset = (H - (Map.Info.MapHeight * MinimapScaleY) / MINIMAP_FAC + 1) / 2;
184
185 DebugPrint("MinimapScale %d %d (%d %d), X off %d, Y off %d\n" _C_
186 MinimapScaleX / MINIMAP_FAC _C_ MinimapScaleY / MINIMAP_FAC _C_
187 MinimapScaleX _C_ MinimapScaleY _C_
188 XOffset _C_ YOffset);
189
190 //
191 // Calculate minimap fast lookup tables.
192 //
193 Minimap2MapX = new int[W * H];
194 memset(Minimap2MapX, 0, W * H * sizeof(int));
195 Minimap2MapY = new int[W * H];
196 memset(Minimap2MapY, 0, W * H * sizeof(int));
197 for (int i = XOffset; i < W - XOffset; ++i) {
198 Minimap2MapX[i] = ((i - XOffset) * MINIMAP_FAC) / MinimapScaleX;
199 }
200 for (int i = YOffset; i < H - YOffset; ++i) {
201 Minimap2MapY[i] = (((i - YOffset) * MINIMAP_FAC) / MinimapScaleY) * Map.Info.MapWidth;
202 }
203 for (int i = 0; i < Map.Info.MapWidth; ++i) {
204 Map2MinimapX[i] = (i * MinimapScaleX) / MINIMAP_FAC;
205 }
206 for (int i = 0; i < Map.Info.MapHeight; ++i) {
207 Map2MinimapY[i] = (i * MinimapScaleY) / MINIMAP_FAC;
208 }
209
210 // Palette updated from UpdateMinimapTerrain()
211 #if defined(USE_OPENGL) || defined(USE_GLES)
212 if (UseOpenGL) {
213 for (MinimapTextureWidth = 1; MinimapTextureWidth < W; MinimapTextureWidth <<= 1) {
214 }
215 for (MinimapTextureHeight = 1; MinimapTextureHeight < H; MinimapTextureHeight <<= 1) {
216 }
217 MinimapTerrainSurfaceGL = new unsigned char[MinimapTextureWidth * MinimapTextureHeight * 4];
218 MinimapSurfaceGL = new unsigned char[MinimapTextureWidth * MinimapTextureHeight * 4];
219 memset(MinimapSurfaceGL, 0, MinimapTextureWidth * MinimapTextureHeight * 4);
220 CreateMinimapTexture();
221 } else
222 #endif
223 {
224 SDL_PixelFormat *f = Map.TileGraphic->Surface->format;
225 //Wyrmgus start
226 // MinimapTerrainSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);
227 MinimapTerrainSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, 32, TheScreen->format->Rmask, TheScreen->format->Gmask, TheScreen->format->Bmask, 0);
228 //Wyrmgus end
229 MinimapSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, 32, TheScreen->format->Rmask, TheScreen->format->Gmask, TheScreen->format->Bmask, 0);
230 }
231
232 UpdateTerrain();
233 */
234 #if defined(USE_OPENGL) || defined(USE_GLES)
235 MinimapTexture.resize(Map.MapLayers.size());
236 MinimapTextureWidth.resize(Map.MapLayers.size());
237 MinimapTextureHeight.resize(Map.MapLayers.size());
238 #endif
239 for (size_t z = 0; z < Map.MapLayers.size(); ++z) {
240 // Scale to biggest value.
241 const int n = std::max(std::max(Map.Info.MapWidths[z], Map.Info.MapHeights[z]), 32);
242
243 MinimapScaleX.push_back((W * MINIMAP_FAC + n - 1) / n);
244 MinimapScaleY.push_back((H * MINIMAP_FAC + n - 1) / n);
245
246 XOffset.push_back((W - (Map.Info.MapWidths[z] * MinimapScaleX[z]) / MINIMAP_FAC + 1) / 2);
247 YOffset.push_back((H - (Map.Info.MapHeights[z] * MinimapScaleY[z]) / MINIMAP_FAC + 1) / 2);
248
249 DebugPrint("MinimapScale %d %d (%d %d), X off %d, Y off %d\n" _C_
250 MinimapScaleX[z] / MINIMAP_FAC _C_ MinimapScaleY[z] / MINIMAP_FAC _C_
251 MinimapScaleX[z] _C_ MinimapScaleY[z] _C_
252 XOffset[z] _C_ YOffset[z]);
253
254 //
255 // Calculate minimap fast lookup tables.
256 //
257 Minimap2MapX.push_back(new int[W * H]);
258 memset(Minimap2MapX[z], 0, W * H * sizeof(int));
259 Minimap2MapY.push_back(new int[W * H]);
260 memset(Minimap2MapY[z], 0, W * H * sizeof(int));
261 for (int i = XOffset[z]; i < W - XOffset[z]; ++i) {
262 Minimap2MapX[z][i] = ((i - XOffset[z]) * MINIMAP_FAC) / MinimapScaleX[z];
263 }
264 for (int i = YOffset[z]; i < H - YOffset[z]; ++i) {
265 Minimap2MapY[z][i] = (((i - YOffset[z]) * MINIMAP_FAC) / MinimapScaleY[z]) * Map.Info.MapWidths[z];
266 }
267 Map2MinimapX.push_back(new int[Map.Info.MapWidths[z]]);
268 memset(Map2MinimapX[z], 0, Map.Info.MapWidths[z] * sizeof(int));
269 Map2MinimapY.push_back(new int[Map.Info.MapHeights[z]]);
270 memset(Map2MinimapY[z], 0, Map.Info.MapHeights[z] * sizeof(int));
271 for (int i = 0; i < Map.Info.MapWidths[z]; ++i) {
272 Map2MinimapX[z][i] = (i * MinimapScaleX[z]) / MINIMAP_FAC;
273 }
274 for (int i = 0; i < Map.Info.MapHeights[z]; ++i) {
275 Map2MinimapY[z][i] = (i * MinimapScaleY[z]) / MINIMAP_FAC;
276 }
277
278 // Palette updated from UpdateMinimapTerrain()
279 #if defined(USE_OPENGL) || defined(USE_GLES)
280 if (UseOpenGL) {
281 for (MinimapTextureWidth[z] = 1; MinimapTextureWidth[z] < W; MinimapTextureWidth[z] <<= 1) {
282 }
283 for (MinimapTextureHeight[z] = 1; MinimapTextureHeight[z] < H; MinimapTextureHeight[z] <<= 1) {
284 }
285 MinimapTerrainSurfaceGL.push_back(new unsigned char[MinimapTextureWidth[z] * MinimapTextureHeight[z] * 4]);
286 MinimapSurfaceGL.push_back(new unsigned char[MinimapTextureWidth[z] * MinimapTextureHeight[z] * 4]);
287 memset(MinimapSurfaceGL[z], 0, MinimapTextureWidth[z] * MinimapTextureHeight[z] * 4);
288 CreateMinimapTexture(z);
289 } else
290 #endif
291 {
292 SDL_PixelFormat *f = TheScreen->format;
293 MinimapTerrainSurface.push_back(SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, 32, RMASK, GMASK, BMASK, AMASK));
294 MinimapSurface.push_back(SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, 32, f->Rmask, f->Gmask, f->Bmask, 0));
295 }
296
297 UpdateTerrain(z);
298 }
299 //Wyrmgus end
300
301 NumMinimapEvents = 0;
302 }
303
304 #if defined(USE_OPENGL) || defined(USE_GLES)
305 /**
306 ** Free OpenGL minimap
307 */
FreeOpenGL()308 void CMinimap::FreeOpenGL()
309 {
310 //Wyrmgus start
311 // glDeleteTextures(1, &MinimapTexture);
312 for (size_t z = 0; z < MinimapTexture.size(); ++z) {
313 glDeleteTextures(1, &MinimapTexture[z]);
314 }
315 MinimapTexture.clear();
316 //Wyrmgus end
317 }
318
319 /**
320 ** Reload OpenGL minimap
321 */
Reload()322 void CMinimap::Reload()
323 {
324 //Wyrmgus start
325 // CreateMinimapTexture();
326 for (size_t z = 0; z < Map.MapLayers.size(); ++z) {
327 CreateMinimapTexture(z);
328 }
329 //Wyrmgus end
330 }
331 #endif
332
333 /**
334 ** Calculate the tile graphic pixel
335 */
336 //Wyrmgus start
337 //static inline Uint8 *GetTileGraphicPixel(int xofs, int yofs, int mx, int my, int scalex, int scaley, int bpp)
GetTileGraphicPixel(int xofs,int yofs,int mx,int my,int scalex,int scaley,int bpp,int z,CTerrainType * terrain,const CSeason * season)338 static inline Uint8 *GetTileGraphicPixel(int xofs, int yofs, int mx, int my, int scalex, int scaley, int bpp, int z, CTerrainType *terrain, const CSeason *season)
339 //Wyrmgus end
340 {
341 //Wyrmgus start
342 // Uint8 *pixels = (Uint8 *)Map.TileGraphic->Surface->pixels;
343 Uint8 *pixels = (Uint8 *)terrain->GetGraphics(season)->Surface->pixels;
344 //Wyrmgus end
345 int x = (xofs + 7 + ((mx * SCALE_PRECISION) % scalex) / SCALE_PRECISION * 8);
346 int y = (yofs + 6 + ((my * SCALE_PRECISION) % scaley) / SCALE_PRECISION * 8);
347 //Wyrmgus start
348 // return &pixels[x * bpp + y * Map.TileGraphic->Surface->pitch];
349 return &pixels[x * bpp + y * terrain->GetGraphics(season)->Surface->pitch];
350 //Wyrmgus end
351 }
352
353 /**
354 ** Update a mini-map from the tiles of the map.
355 */
356 //Wyrmgus start
357 //void CMinimap::UpdateTerrain()
UpdateTerrain(int z)358 void CMinimap::UpdateTerrain(int z)
359 //Wyrmgus end
360 {
361 //Wyrmgus start
362 // int scalex = MinimapScaleX * SCALE_PRECISION / MINIMAP_FAC;
363 int scalex = MinimapScaleX[z] * SCALE_PRECISION / MINIMAP_FAC;
364 //Wyrmgus end
365 if (!scalex) {
366 scalex = 1;
367 }
368 //Wyrmgus start
369 // int scaley = MinimapScaleY * SCALE_PRECISION / MINIMAP_FAC;
370 int scaley = MinimapScaleY[z] * SCALE_PRECISION / MINIMAP_FAC;
371 //Wyrmgus end
372 if (!scaley) {
373 scaley = 1;
374 }
375 //Wyrmgus start
376 // const int bpp = Map.TileGraphic->Surface->format->BytesPerPixel;
377 //Wyrmgus end
378
379 const CSeason *season = Map.MapLayers[z]->GetSeason();
380
381 #if defined(USE_OPENGL) || defined(USE_GLES)
382 if (!UseOpenGL)
383 #endif
384 {
385 //Wyrmgus start
386 /*
387 if (bpp == 1) {
388 SDL_SetPalette(MinimapTerrainSurface, SDL_LOGPAL,
389 Map.TileGraphic->Surface->format->palette->colors, 0, 256);
390 }
391 */
392 //Wyrmgus end
393 }
394
395 //Wyrmgus start
396 // const int tilepitch = Map.TileGraphic->Surface->w / Map.GetCurrentPixelTileSize().x;
397 //Wyrmgus end
398
399 #if defined(USE_OPENGL) || defined(USE_GLES)
400 if (UseOpenGL) {
401 SDL_LockSurface(Map.TileGraphic->Surface);
402 //Wyrmgus start
403 for (size_t i = 0; i != CTerrainType::TerrainTypes.size(); ++i) {
404 if (CTerrainType::TerrainTypes[i]->GetGraphics(season)) {
405 SDL_LockSurface(CTerrainType::TerrainTypes[i]->GetGraphics(season)->Surface);
406 }
407 }
408 //Wyrmgus end
409 } else
410 #endif
411 {
412 //Wyrmgus start
413 // SDL_LockSurface(MinimapTerrainSurface);
414 SDL_LockSurface(MinimapTerrainSurface[z]);
415 //Wyrmgus end
416 }
417
418 const CMapLayer *map_layer = Map.MapLayers[z];
419
420 //
421 // Pixel 7,6 7,14, 15,6 15,14 are taken for the minimap picture.
422 //
423 for (int my = YOffset[z]; my < H - YOffset[z]; ++my) {
424 for (int mx = XOffset[z]; mx < W - XOffset[z]; ++mx) {
425 //Wyrmgus start
426 // const int tile = Map.Fields[Minimap2MapX[mx] + Minimap2MapY[my]].getGraphicTile();
427 const CMapField &mf = *map_layer->Field(Minimap2MapX[z][mx] + Minimap2MapY[z][my]);
428 CTerrainType *terrain = mf.playerInfo.SeenOverlayTerrain ? mf.playerInfo.SeenOverlayTerrain : mf.playerInfo.SeenTerrain;
429 int tile = mf.playerInfo.SeenOverlayTerrain ? mf.playerInfo.SeenOverlaySolidTile : mf.playerInfo.SeenSolidTile;
430 if (!terrain) {
431 terrain = mf.OverlayTerrain ? mf.OverlayTerrain : mf.Terrain;
432 tile = mf.OverlayTerrain ? mf.OverlaySolidTile : mf.SolidTile;
433 }
434
435 CTerrainType *base_terrain = mf.playerInfo.SeenTerrain;
436 int base_tile = mf.playerInfo.SeenSolidTile;
437 if (!base_terrain) {
438 base_terrain = mf.Terrain;
439 base_tile = mf.SolidTile;
440 }
441 //Wyrmgus end
442
443 //Wyrmgus start
444 int tilepitch = terrain->GetGraphics(season)->Surface->w / Map.GetCurrentPixelTileSize().x;
445 const int bpp = terrain->GetGraphics(season)->Surface->format->BytesPerPixel;
446
447 int base_tilepitch = base_terrain->GetGraphics(season)->Surface->w / Map.GetCurrentPixelTileSize().x;
448 //assumes the BPP for the base terrain is the same as for the top terrain (which may be an overlay)
449 //Wyrmgus end
450
451 const int xofs = Map.GetCurrentPixelTileSize().x * (tile % tilepitch);
452 const int yofs = Map.GetCurrentPixelTileSize().y * (tile / tilepitch);
453
454 //Wyrmgus start
455 const int base_xofs = Map.GetCurrentPixelTileSize().x * (base_tile % base_tilepitch);
456 const int base_yofs = Map.GetCurrentPixelTileSize().y * (base_tile / base_tilepitch);
457 //Wyrmgus end
458
459 #if defined(USE_OPENGL) || defined(USE_GLES)
460 if (UseOpenGL) {
461 Uint32 c;
462
463 if (bpp == 1) {
464 //Wyrmgus start
465 // SDL_Color color = Map.TileGraphic->Surface->format->palette->colors[
466 // *GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp)];
467 SDL_Color color = terrain->GetGraphics(season)->Surface->format->palette->colors[
468 *GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp, z, terrain, season)];
469 if (color.r == 255 && color.g == 255 && color.b == 255) { //completely white pixel, presumed to be a transparent one; use base instead
470 color = base_terrain->GetGraphics(season)->Surface->format->palette->colors[
471 *GetTileGraphicPixel(base_xofs, base_yofs, mx, my, scalex, scaley, bpp, z, base_terrain, season)];
472 }
473 //Wyrmgus end
474
475 c = Video.MapRGB(0, color.r, color.g, color.b);
476 } else {
477 //Wyrmgus start
478 // SDL_PixelFormat *f = Map.TileGraphic->Surface->format;
479 SDL_PixelFormat *f = terrain->GetGraphics(season)->Surface->format;
480 //Wyrmgus end
481 c = *(Uint32 *)GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp, z, terrain, season);
482 //Wyrmgus start
483 if (((c & f->Amask) >> f->Ashift) == 0) { //transparent pixel, use base instead
484 f = base_terrain->GetGraphics(season)->Surface->format;
485 c = *(Uint32 *)GetTileGraphicPixel(base_xofs, base_yofs, mx, my, scalex, scaley, bpp, z, base_terrain, season);
486 }
487 //Wyrmgus end
488 c = Video.MapRGB(0,
489 ((c & f->Rmask) >> f->Rshift),
490 ((c & f->Gmask) >> f->Gshift),
491 ((c & f->Bmask) >> f->Bshift));
492 }
493 //Wyrmgus start
494 // *(Uint32 *)&(MinimapTerrainSurfaceGL[(mx + my * MinimapTextureWidth) * 4]) = c;
495 *(Uint32 *)&(MinimapTerrainSurfaceGL[z][(mx + my * MinimapTextureWidth[z]) * 4]) = c;
496 //Wyrmgus end
497 } else
498 #endif
499 {
500 if (bpp == 1) {
501 //Wyrmgus start
502 /*
503 ((Uint8 *)MinimapTerrainSurface->pixels)[mx + my * MinimapTerrainSurface->pitch] =
504 *GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp);
505 */
506 SDL_Color original_color = terrain->GetGraphics(season)->Surface->format->palette->colors[
507 *GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp, z, terrain, season)];
508
509 if (original_color.r == 255 && original_color.g == 255 && original_color.b == 255) { //completely white pixel, presumed to be a transparent one; use base instead
510 original_color = base_terrain->GetGraphics(season)->Surface->format->palette->colors[
511 *GetTileGraphicPixel(base_xofs, base_yofs, mx, my, scalex, scaley, bpp, z, base_terrain, season)];
512 }
513
514 Uint32 color;
515 color = Video.MapRGB(TheScreen->format, original_color.r, original_color.g, original_color.b);
516
517 *(Uint32 *)&((Uint8 *)MinimapTerrainSurface[z]->pixels)[mx * MinimapSurface[z]->format->BytesPerPixel + my * MinimapTerrainSurface[z]->pitch] = color;
518 //Wyrmgus end
519 } else if (bpp == 3) {
520 //Wyrmgus start
521 // Uint8 *d = &((Uint8 *)MinimapTerrainSurface->pixels)[mx * bpp + my * MinimapTerrainSurface->pitch];
522 // Uint8 *s = GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp);
523 Uint8 *d = &((Uint8 *)MinimapTerrainSurface[z]->pixels)[mx * bpp + my * MinimapTerrainSurface[z]->pitch];
524 Uint8 *s = GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp, z, terrain, season);
525 //Wyrmgus end
526 *d++ = *s++;
527 *d++ = *s++;
528 *d++ = *s++;
529 } else {
530 //Wyrmgus start
531 // *(Uint32 *)&((Uint8 *)MinimapTerrainSurface->pixels)[mx * bpp + my * MinimapTerrainSurface->pitch] =
532 // *(Uint32 *)GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp);
533 *(Uint32 *)&((Uint8 *)MinimapTerrainSurface[z]->pixels)[mx * bpp + my * MinimapTerrainSurface[z]->pitch] =
534 *(Uint32 *)GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp, z, terrain, season);
535 //Wyrmgus end
536 }
537 }
538
539 }
540 }
541 #if defined(USE_OPENGL) || defined(USE_GLES)
542 if (!UseOpenGL)
543 #endif
544 {
545 //Wyrmgus start
546 // SDL_UnlockSurface(MinimapTerrainSurface);
547 SDL_UnlockSurface(MinimapTerrainSurface[z]);
548 //Wyrmgus end
549 }
550 SDL_UnlockSurface(Map.TileGraphic->Surface);
551 //Wyrmgus start
552 for (size_t i = 0; i != CTerrainType::TerrainTypes.size(); ++i) {
553 if (CTerrainType::TerrainTypes[i]->GetGraphics(season)) {
554 SDL_UnlockSurface(CTerrainType::TerrainTypes[i]->GetGraphics(season)->Surface);
555 }
556 }
557 //Wyrmgus end
558 }
559
560 /**
561 ** @brief Update a single minimap tile after a change
562 **
563 ** @param pos The map position to update in the minimap
564 ** @param z The map layer of the tile to update
565 */
UpdateXY(const Vec2i & pos,int z)566 void CMinimap::UpdateXY(const Vec2i &pos, int z)
567 {
568 #if defined(USE_OPENGL) || defined(USE_GLES)
569 if (UseOpenGL) {
570 //Wyrmgus start
571 // if (!MinimapTerrainSurfaceGL) {
572 if (z >= (int) MinimapTerrainSurfaceGL.size() || !MinimapTerrainSurfaceGL[z]) {
573 //Wyrmgus end
574 return;
575 }
576 } else
577 #endif
578 {
579 //Wyrmgus start
580 // if (!MinimapTerrainSurface) {
581 if (z >= (int) MinimapTerrainSurface.size() || !MinimapTerrainSurface[z]) {
582 //Wyrmgus end
583 return;
584 }
585 }
586
587 //Wyrmgus start
588 // int scalex = MinimapScaleX * SCALE_PRECISION / MINIMAP_FAC;
589 int scalex = MinimapScaleX[z] * SCALE_PRECISION / MINIMAP_FAC;
590 //Wyrmgus end
591 if (scalex == 0) {
592 scalex = 1;
593 }
594 //Wyrmgus start
595 // int scaley = MinimapScaleY * SCALE_PRECISION / MINIMAP_FAC;
596 int scaley = MinimapScaleY[z] * SCALE_PRECISION / MINIMAP_FAC;
597 //Wyrmgus end
598 if (scaley == 0) {
599 scaley = 1;
600 }
601
602 //Wyrmgus start
603 // const int tilepitch = Map.TileGraphic->Surface->w / Map.GetCurrentPixelTileSize().x;
604 // const int bpp = Map.TileGraphic->Surface->format->BytesPerPixel;
605 //Wyrmgus end
606
607 const CSeason *season = Map.MapLayers[z]->GetSeason();
608
609 //
610 // Pixel 7,6 7,14, 15,6 15,14 are taken for the minimap picture.
611 //
612 #if defined(USE_OPENGL) || defined(USE_GLES)
613 if (!UseOpenGL)
614 #endif
615 {
616 //Wyrmgus start
617 // SDL_LockSurface(MinimapTerrainSurface);
618 SDL_LockSurface(MinimapTerrainSurface[z]);
619 //Wyrmgus end
620 }
621 SDL_LockSurface(Map.TileGraphic->Surface);
622 //Wyrmgus start
623 for (size_t i = 0; i != CTerrainType::TerrainTypes.size(); ++i) {
624 if (CTerrainType::TerrainTypes[i]->GetGraphics(season)) {
625 SDL_LockSurface(CTerrainType::TerrainTypes[i]->GetGraphics(season)->Surface);
626 }
627 }
628 //Wyrmgus end
629
630 //Wyrmgus start
631 // const int ty = pos.y * Map.Info.MapWidth;
632 const int ty = pos.y * Map.Info.MapWidths[z];
633 //Wyrmgus end
634 const int tx = pos.x;
635 //Wyrmgus start
636 // for (int my = YOffset; my < H - YOffset; ++my) {
637 for (int my = YOffset[z]; my < H - YOffset[z]; ++my) {
638 //Wyrmgus end
639 //Wyrmgus start
640 // const int y = Minimap2MapY[my];
641 const int y = Minimap2MapY[z][my];
642 //Wyrmgus end
643 if (y < ty) {
644 continue;
645 }
646 if (y > ty) {
647 break;
648 }
649
650 //Wyrmgus start
651 // for (int mx = XOffset; mx < W - XOffset; ++mx) {
652 for (int mx = XOffset[z]; mx < W - XOffset[z]; ++mx) {
653 //Wyrmgus end
654 //Wyrmgus start
655 // const int x = Minimap2MapX[mx];
656 const int x = Minimap2MapX[z][mx];
657 //Wyrmgus end
658
659 if (x < tx) {
660 continue;
661 }
662 if (x > tx) {
663 break;
664 }
665
666 //Wyrmgus start
667 /*
668 int tile = Map.Fields[x + y].playerInfo.SeenTile;
669 if (!tile) {
670 tile = Map.Fields[x + y].getGraphicTile();
671 }
672 */
673 const CMapField &mf = *Map.MapLayers[z]->Field(x + y);
674 CTerrainType *terrain = mf.playerInfo.SeenOverlayTerrain ? mf.playerInfo.SeenOverlayTerrain : mf.playerInfo.SeenTerrain;
675 int tile = mf.playerInfo.SeenOverlayTerrain ? mf.playerInfo.SeenOverlaySolidTile : mf.playerInfo.SeenSolidTile;
676 if (!terrain) {
677 terrain = mf.OverlayTerrain ? mf.OverlayTerrain : mf.Terrain;
678 tile = mf.OverlayTerrain ? mf.OverlaySolidTile : mf.SolidTile;
679 }
680
681 CTerrainType *base_terrain = mf.playerInfo.SeenTerrain;
682 int base_tile = mf.playerInfo.SeenSolidTile;
683 if (!base_terrain) {
684 base_terrain = mf.Terrain;
685 base_tile = mf.SolidTile;
686 }
687 //Wyrmgus end
688
689 //Wyrmgus start
690 int tilepitch = terrain->GetGraphics(season)->Surface->w / Map.GetCurrentPixelTileSize().x;
691 const int bpp = terrain->GetGraphics(season)->Surface->format->BytesPerPixel;
692
693 int base_tilepitch = base_terrain->GetGraphics(season)->Surface->w / Map.GetCurrentPixelTileSize().x;
694 //Wyrmgus end
695
696 const int xofs = Map.GetCurrentPixelTileSize().x * (tile % tilepitch);
697 const int yofs = Map.GetCurrentPixelTileSize().y * (tile / tilepitch);
698
699 //Wyrmgus start
700 const int base_xofs = Map.GetCurrentPixelTileSize().x * (base_tile % base_tilepitch);
701 const int base_yofs = Map.GetCurrentPixelTileSize().y * (base_tile / base_tilepitch);
702 //Wyrmgus end
703
704 #if defined(USE_OPENGL) || defined(USE_GLES)
705 if (UseOpenGL) {
706 Uint32 c;
707
708 if (bpp == 1) {
709 //Wyrmgus start
710 // const int colorIndex = *GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp);
711 // const SDL_Color color = Map.TileGraphic->Surface->format->palette->colors[colorIndex];
712 int colorIndex = *GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp, z, terrain, season);
713 SDL_Color color = terrain->GetGraphics(season)->Surface->format->palette->colors[colorIndex];
714 if (color.r == 255 && color.g == 255 && color.b == 255) { //completely white pixel, presumed to be a transparent one; use base instead
715 colorIndex = *GetTileGraphicPixel(base_xofs, base_yofs, mx, my, scalex, scaley, bpp, z, base_terrain, season);
716 color = base_terrain->GetGraphics(season)->Surface->format->palette->colors[colorIndex];
717 }
718 //Wyrmgus end
719
720 c = Video.MapRGB(0, color.r, color.g, color.b);
721 } else {
722 //Wyrmgus start
723 // SDL_PixelFormat *f = Map.TileGraphic->Surface->format;
724 SDL_PixelFormat *f = terrain->GetGraphics(season)->Surface->format;
725 //Wyrmgus end
726
727 //Wyrmgus start
728 // c = *(Uint32 *)GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp);
729 c = *(Uint32 *)GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp, z, terrain, season);
730
731 if (((c & f->Amask) >> f->Ashift) == 0) { //transparent pixel, use base instead
732 f = base_terrain->GetGraphics(season)->Surface->format;
733 c = *(Uint32 *)GetTileGraphicPixel(base_xofs, base_yofs, mx, my, scalex, scaley, bpp, z, base_terrain, season);
734 }
735 //Wyrmgus end
736 c = Video.MapRGB(0,
737 ((c & f->Rmask) >> f->Rshift),
738 ((c & f->Gmask) >> f->Gshift),
739 ((c & f->Bmask) >> f->Bshift));
740 }
741 //Wyrmgus start
742 // *(Uint32 *)&(MinimapTerrainSurfaceGL[(mx + my * MinimapTextureWidth) * 4]) = c;
743 *(Uint32 *)&(MinimapTerrainSurfaceGL[z][(mx + my * MinimapTextureWidth[z]) * 4]) = c;
744 //Wyrmgus end
745 } else
746 #endif
747 {
748 //Wyrmgus start
749 // const int index = mx * bpp + my * MinimapTerrainSurface->pitch;
750 // Uint8 *s = GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp);
751 const int index = mx * bpp + my * MinimapTerrainSurface[z]->pitch;
752 Uint8 *s = GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp, z, terrain, season);
753 //Wyrmgus end
754 if (bpp == 1) {
755 //Wyrmgus start
756 /*
757 ((Uint8 *)MinimapTerrainSurface->pixels)[index] = *s;
758 */
759 SDL_Color original_color = terrain->GetGraphics(season)->Surface->format->palette->colors[
760 *GetTileGraphicPixel(xofs, yofs, mx, my, scalex, scaley, bpp, z, terrain, season)];
761
762 if (original_color.r == 255 && original_color.g == 255 && original_color.b == 255) { //completely white pixel, presumed to be a transparent one; use base instead
763 original_color = base_terrain->GetGraphics(season)->Surface->format->palette->colors[
764 *GetTileGraphicPixel(base_xofs, base_yofs, mx, my, scalex, scaley, bpp, z, base_terrain, season)];
765 }
766
767 Uint32 color;
768 color = Video.MapRGB(TheScreen->format, original_color.r, original_color.g, original_color.b);
769
770 *(Uint32 *)&((Uint8 *)MinimapTerrainSurface[z]->pixels)[mx * MinimapSurface[z]->format->BytesPerPixel + my * MinimapTerrainSurface[z]->pitch] = color;
771 //Wyrmgus end
772 } else if (bpp == 3) {
773 //Wyrmgus start
774 // Uint8 *d = &((Uint8 *)MinimapTerrainSurface->pixels)[index];
775 Uint8 *d = &((Uint8 *)MinimapTerrainSurface[z]->pixels)[index];
776 //Wyrmgus end
777
778 *d++ = *s++;
779 *d++ = *s++;
780 *d++ = *s++;
781 } else {
782 //Wyrmgus start
783 // *(Uint32 *)&((Uint8 *)MinimapTerrainSurface->pixels)[index] = *(Uint32 *)s;
784 *(Uint32 *)&((Uint8 *)MinimapTerrainSurface[z]->pixels)[index] = *(Uint32 *)s;
785 //Wyrmgus end
786 }
787 }
788 }
789 }
790 #if defined(USE_OPENGL) || defined(USE_GLES)
791 if (!UseOpenGL)
792 #endif
793 {
794 //Wyrmgus start
795 // SDL_UnlockSurface(MinimapTerrainSurface);
796 SDL_UnlockSurface(MinimapTerrainSurface[z]);
797 //Wyrmgus end
798 }
799 SDL_UnlockSurface(Map.TileGraphic->Surface);
800 //Wyrmgus start
801 for (size_t i = 0; i != CTerrainType::TerrainTypes.size(); ++i) {
802 if (CTerrainType::TerrainTypes[i]->GetGraphics(season)) {
803 SDL_UnlockSurface(CTerrainType::TerrainTypes[i]->GetGraphics(season)->Surface);
804 }
805 }
806 //Wyrmgus end
807 }
808
809 /**
810 ** Draw a unit on the minimap.
811 */
DrawUnitOn(CUnit & unit,int red_phase)812 static void DrawUnitOn(CUnit &unit, int red_phase)
813 {
814 const CUnitType *type;
815
816 if (Editor.Running || ReplayRevealMap || unit.IsVisible(*ThisPlayer)) {
817 type = unit.Type;
818 } else {
819 type = unit.Seen.Type;
820 // This will happen for radar if the unit has not been seen and we
821 // have it on radar.
822 if (!type) {
823 type = unit.Type;
824 }
825 }
826
827 //Wyrmgus start
828 //don't draw decorations or diminutive fauna units on the minimap
829 if (type->BoolFlag[DECORATION_INDEX].value || (type->BoolFlag[DIMINUTIVE_INDEX].value && type->BoolFlag[FAUNA_INDEX].value)) {
830 return;
831 }
832 //Wyrmgus end
833
834 Uint32 color;
835 //Wyrmgus start
836 // if (unit.Player->Index == PlayerNumNeutral) {
837 if (unit.GetDisplayPlayer() == PlayerNumNeutral) {
838 //Wyrmgus end
839 color = Video.MapRGB(TheScreen->format, type->NeutralMinimapColorRGB);
840 } else if (unit.Player == ThisPlayer && !Editor.Running) {
841 if (unit.Attacked && unit.Attacked + ATTACK_BLINK_DURATION > GameCycle &&
842 (red_phase || unit.Attacked + ATTACK_RED_DURATION > GameCycle)) {
843 color = ColorRed;
844 } else if (UI.Minimap.ShowSelected && unit.Selected) {
845 color = ColorWhite;
846 } else {
847 color = ColorGreen;
848 }
849 } else {
850 color = unit.Player->Color;
851 }
852
853 //Wyrmgus start
854 // int mx = 1 + UI.Minimap.XOffset + Map2MinimapX[unit.tilePos.x];
855 // int my = 1 + UI.Minimap.YOffset + Map2MinimapY[unit.tilePos.y];
856 // int w = Map2MinimapX[type->TileSize.x];
857 int mx = 1 + UI.Minimap.XOffset[UI.CurrentMapLayer->ID] + Map2MinimapX[UI.CurrentMapLayer->ID][unit.tilePos.x];
858 int my = 1 + UI.Minimap.YOffset[UI.CurrentMapLayer->ID] + Map2MinimapY[UI.CurrentMapLayer->ID][unit.tilePos.y];
859 int w = Map2MinimapX[UI.CurrentMapLayer->ID][type->TileSize.x];
860 //Wyrmgus end
861 if (mx + w >= UI.Minimap.W) { // clip right side
862 w = UI.Minimap.W - mx;
863 }
864 //Wyrmgus start
865 // int h0 = Map2MinimapY[type->TileSize.y];
866 int h0 = Map2MinimapY[UI.CurrentMapLayer->ID][type->TileSize.y];
867 //Wyrmgus end
868 if (my + h0 >= UI.Minimap.H) { // clip bottom side
869 h0 = UI.Minimap.H - my;
870 }
871 int bpp = 0;
872 #if defined(USE_OPENGL) || defined(USE_GLES)
873 if (!UseOpenGL)
874 #endif
875 {
876 SDL_Color c;
877 //Wyrmgus start
878 // bpp = MinimapSurface->format->BytesPerPixel;
879 bpp = MinimapSurface[UI.CurrentMapLayer->ID]->format->BytesPerPixel;
880 //Wyrmgus end
881 SDL_GetRGB(color, TheScreen->format, &c.r, &c.g, &c.b);
882 }
883 while (w-- >= 0) {
884 int h = h0;
885 while (h-- >= 0) {
886 #if defined(USE_OPENGL) || defined(USE_GLES)
887 if (UseOpenGL) {
888 //Wyrmgus start
889 // *(Uint32 *)&(MinimapSurfaceGL[((mx + w) + (my + h) * MinimapTextureWidth) * 4]) = color;
890 *(Uint32 *)&(MinimapSurfaceGL[UI.CurrentMapLayer->ID][((mx + w) + (my + h) * MinimapTextureWidth[UI.CurrentMapLayer->ID]) * 4]) = color;
891 //Wyrmgus end
892 } else
893 #endif
894 {
895 //Wyrmgus start
896 // const unsigned int index = (mx + w) * bpp + (my + h) * MinimapSurface->pitch;
897 const unsigned int index = (mx + w) * bpp + (my + h) * MinimapSurface[UI.CurrentMapLayer->ID]->pitch;
898 //Wyrmgus end
899 if (bpp == 2) {
900 //Wyrmgus start
901 // *(Uint16 *)&((Uint8 *)MinimapSurface->pixels)[index] = color;
902 *(Uint16 *)&((Uint8 *)MinimapSurface[UI.CurrentMapLayer->ID]->pixels)[index] = color;
903 //Wyrmgus end
904 } else {
905 //Wyrmgus start
906 // *(Uint32 *)&((Uint8 *)MinimapSurface->pixels)[index] = color;
907 *(Uint32 *)&((Uint8 *)MinimapSurface[UI.CurrentMapLayer->ID]->pixels)[index] = color;
908 //Wyrmgus end
909 }
910 }
911 }
912 }
913 }
914
915 /**
916 ** Update the minimap with the current game information
917 */
Update()918 void CMinimap::Update()
919 {
920 static int red_phase;
921
922 int red_phase_changed = red_phase != (int)((FrameCounter / FRAMES_PER_SECOND) & 1);
923 if (red_phase_changed) {
924 red_phase = !red_phase;
925 }
926
927 // Clear Minimap background if not transparent
928 if (!Transparent) {
929 #if defined(USE_OPENGL) || defined(USE_GLES)
930 if (UseOpenGL) {
931 //Wyrmgus start
932 // memset(MinimapSurfaceGL, 0, MinimapTextureWidth * MinimapTextureHeight * 4);
933 memset(MinimapSurfaceGL[UI.CurrentMapLayer->ID], 0, MinimapTextureWidth[UI.CurrentMapLayer->ID] * MinimapTextureHeight[UI.CurrentMapLayer->ID] * 4);
934 //Wyrmgus end
935 } else
936 #endif
937 {
938 //Wyrmgus start
939 // SDL_FillRect(MinimapSurface, nullptr, SDL_MapRGB(MinimapSurface->format, 0, 0, 0));
940 SDL_FillRect(MinimapSurface[UI.CurrentMapLayer->ID], nullptr, SDL_MapRGB(MinimapSurface[UI.CurrentMapLayer->ID]->format, 0, 0, 0));
941 //Wyrmgus end
942 }
943 }
944
945 int bpp;
946 #if defined(USE_OPENGL) || defined(USE_GLES)
947 if (UseOpenGL) {
948 bpp = 0;
949 } else
950 #endif
951 {
952 //Wyrmgus start
953 // bpp = MinimapSurface->format->BytesPerPixel;
954 bpp = MinimapSurface[UI.CurrentMapLayer->ID]->format->BytesPerPixel;
955 //Wyrmgus end
956 }
957
958 //
959 // Draw the terrain
960 //
961 if (WithTerrain) {
962 #if defined(USE_OPENGL) || defined(USE_GLES)
963 if (UseOpenGL) {
964 //Wyrmgus start
965 // memcpy(MinimapSurfaceGL, MinimapTerrainSurfaceGL, MinimapTextureWidth * MinimapTextureHeight * 4);
966 memcpy(MinimapSurfaceGL[UI.CurrentMapLayer->ID], MinimapTerrainSurfaceGL[UI.CurrentMapLayer->ID], MinimapTextureWidth[UI.CurrentMapLayer->ID] * MinimapTextureHeight[UI.CurrentMapLayer->ID] * 4);
967 //Wyrmgus end
968 } else
969 #endif
970 {
971 //Wyrmgus start
972 // SDL_BlitSurface(MinimapTerrainSurface, nullptr, MinimapSurface, nullptr);
973 SDL_BlitSurface(MinimapTerrainSurface[UI.CurrentMapLayer->ID], nullptr, MinimapSurface[UI.CurrentMapLayer->ID], nullptr);
974 //Wyrmgus end
975 }
976 }
977
978 #if defined(USE_OPENGL) || defined(USE_GLES)
979 if (!UseOpenGL)
980 #endif
981 {
982 //Wyrmgus start
983 // SDL_LockSurface(MinimapSurface);
984 // SDL_LockSurface(MinimapTerrainSurface);
985 SDL_LockSurface(MinimapSurface[UI.CurrentMapLayer->ID]);
986 SDL_LockSurface(MinimapTerrainSurface[UI.CurrentMapLayer->ID]);
987 //Wyrmgus end
988 }
989
990 for (int my = 0; my < H; ++my) {
991 for (int mx = 0; mx < W; ++mx) {
992 //Wyrmgus start
993 if (mx < XOffset[UI.CurrentMapLayer->ID] || mx >= W - XOffset[UI.CurrentMapLayer->ID] || my < YOffset[UI.CurrentMapLayer->ID] || my >= H - YOffset[UI.CurrentMapLayer->ID]) {
994 #if defined(USE_OPENGL) || defined(USE_GLES)
995 if (UseOpenGL) {
996 *(Uint32 *)&(MinimapSurfaceGL[UI.CurrentMapLayer->ID][(mx + my * MinimapTextureWidth[UI.CurrentMapLayer->ID]) * 4]) = Video.MapRGB(0, 0, 0, 0);
997 } else
998 #endif
999 {
1000 //Wyrmgus start
1001 // const int index = mx * bpp + my * MinimapSurface->pitch;
1002 const int index = mx * bpp + my * MinimapSurface[UI.CurrentMapLayer->ID]->pitch;
1003 //Wyrmgus end
1004 if (bpp == 2) {
1005 //Wyrmgus start
1006 // *(Uint16 *)&((Uint8 *)MinimapSurface->pixels)[index] = ColorBlack;
1007 *(Uint16 *)&((Uint8 *)MinimapSurface[UI.CurrentMapLayer->ID]->pixels)[index] = ColorBlack;
1008 //Wyrmgus end
1009 } else {
1010 //Wyrmgus start
1011 // *(Uint32 *)&((Uint8 *)MinimapSurface->pixels)[index] = ColorBlack;
1012 *(Uint32 *)&((Uint8 *)MinimapSurface[UI.CurrentMapLayer->ID]->pixels)[index] = ColorBlack;
1013 //Wyrmgus end
1014 }
1015 }
1016 continue;
1017 }
1018 //Wyrmgus end
1019
1020 int visiontype; // 0 unexplored, 1 explored, >1 visible.
1021
1022 if (ReplayRevealMap) {
1023 visiontype = 2;
1024 } else {
1025 //Wyrmgus start
1026 // const Vec2i tilePos(Minimap2MapX[mx], Minimap2MapY[my] / Map.Info.MapWidth);
1027 // visiontype = Map.Field(tilePos)->playerInfo.TeamVisibilityState(*ThisPlayer);
1028 const Vec2i tilePos(Minimap2MapX[UI.CurrentMapLayer->ID][mx], Minimap2MapY[UI.CurrentMapLayer->ID][my] / UI.CurrentMapLayer->GetWidth());
1029 visiontype = Map.Field(tilePos, UI.CurrentMapLayer->ID)->playerInfo.TeamVisibilityState(*ThisPlayer);
1030 //Wyrmgus end
1031 }
1032
1033 if (visiontype == 0 || (visiontype == 1 && ((mx & 1) != (my & 1)))) {
1034 #if defined(USE_OPENGL) || defined(USE_GLES)
1035 if (UseOpenGL) {
1036 //Wyrmgus start
1037 // *(Uint32 *)&(MinimapSurfaceGL[(mx + my * MinimapTextureWidth) * 4]) = Video.MapRGB(0, 0, 0, 0);
1038 *(Uint32 *)&(MinimapSurfaceGL[UI.CurrentMapLayer->ID][(mx + my * MinimapTextureWidth[UI.CurrentMapLayer->ID]) * 4]) = Video.MapRGB(0, 0, 0, 0);
1039 //Wyrmgus end
1040 } else
1041 #endif
1042 {
1043 //Wyrmgus start
1044 // const int index = mx * bpp + my * MinimapSurface->pitch;
1045 const int index = mx * bpp + my * MinimapSurface[UI.CurrentMapLayer->ID]->pitch;
1046 //Wyrmgus end
1047 if (bpp == 2) {
1048 //Wyrmgus start
1049 // *(Uint16 *)&((Uint8 *)MinimapSurface->pixels)[index] = ColorBlack;
1050 *(Uint16 *)&((Uint8 *)MinimapSurface[UI.CurrentMapLayer->ID]->pixels)[index] = ColorBlack;
1051 //Wyrmgus end
1052 } else {
1053 //Wyrmgus start
1054 // *(Uint32 *)&((Uint8 *)MinimapSurface->pixels)[index] = ColorBlack;
1055 *(Uint32 *)&((Uint8 *)MinimapSurface[UI.CurrentMapLayer->ID]->pixels)[index] = ColorBlack;
1056 //Wyrmgus end
1057 }
1058 }
1059 }
1060 }
1061 }
1062
1063 #if defined(USE_OPENGL) || defined(USE_GLES)
1064 if (!UseOpenGL)
1065 #endif
1066 {
1067 //Wyrmgus start
1068 // SDL_UnlockSurface(MinimapTerrainSurface);
1069 SDL_UnlockSurface(MinimapTerrainSurface[UI.CurrentMapLayer->ID]);
1070 //Wyrmgus end
1071 }
1072
1073 //
1074 // Draw units on map
1075 //
1076 for (CUnitManager::Iterator it = UnitManager.begin(); it != UnitManager.end(); ++it) {
1077 CUnit &unit = **it;
1078 if (unit.IsVisibleOnMinimap()) {
1079 DrawUnitOn(unit, red_phase);
1080 }
1081 }
1082 #if defined(USE_OPENGL) || defined(USE_GLES)
1083 if (!UseOpenGL)
1084 #endif
1085 {
1086 //Wyrmgus start
1087 // SDL_UnlockSurface(MinimapSurface);
1088 SDL_UnlockSurface(MinimapSurface[UI.CurrentMapLayer->ID]);
1089 //Wyrmgus end
1090 }
1091 }
1092
1093 /**
1094 ** Draw the minimap events
1095 */
DrawEvents()1096 static void DrawEvents()
1097 {
1098 const unsigned char alpha = 192;
1099
1100 for (int i = 0; i < NumMinimapEvents; ++i) {
1101 Video.DrawTransCircleClip(MinimapEvents[i].Color,
1102 MinimapEvents[i].pos.x, MinimapEvents[i].pos.y,
1103 MinimapEvents[i].Size, alpha);
1104 MinimapEvents[i].Size -= 1;
1105 if (MinimapEvents[i].Size < 2) {
1106 MinimapEvents[i] = MinimapEvents[--NumMinimapEvents];
1107 --i;
1108 }
1109 }
1110 }
1111
1112 /**
1113 ** Draw the minimap on the screen
1114 */
Draw() const1115 void CMinimap::Draw() const
1116 {
1117 #if defined(USE_OPENGL) || defined(USE_GLES)
1118 if (UseOpenGL) {
1119 //Wyrmgus start
1120 // glBindTexture(GL_TEXTURE_2D, MinimapTexture);
1121 glBindTexture(GL_TEXTURE_2D, MinimapTexture[UI.CurrentMapLayer->ID]);
1122 //Wyrmgus end
1123 //Wyrmgus start
1124 // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, MinimapTextureWidth, MinimapTextureHeight,
1125 // GL_RGBA, GL_UNSIGNED_BYTE, MinimapSurfaceGL);
1126 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, MinimapTextureWidth[UI.CurrentMapLayer->ID], MinimapTextureHeight[UI.CurrentMapLayer->ID],
1127 GL_RGBA, GL_UNSIGNED_BYTE, MinimapSurfaceGL[UI.CurrentMapLayer->ID]);
1128 //Wyrmgus end
1129
1130 #ifdef USE_GLES
1131 float texCoord[] = {
1132 0.0f, 0.0f,
1133 //Wyrmgus start
1134 // (float)W / MinimapTextureWidth, 0.0f,
1135 // 0.0f, (float)H / MinimapTextureHeight,
1136 // (float)W / MinimapTextureWidth, (float)H / MinimapTextureHeight
1137 (float)W / MinimapTextureWidth[UI.CurrentMapLayer->ID], 0.0f,
1138 0.0f, (float)H / MinimapTextureHeight[UI.CurrentMapLayer->ID],
1139 (float)W / MinimapTextureWidth[UI.CurrentMapLayer->ID], (float)H / MinimapTextureHeight[UI.CurrentMapLayer->ID]
1140 //Wyrmgus end
1141 };
1142
1143 float vertex[] = {
1144 2.0f / (GLfloat)Video.Width *X - 1.0f, -2.0f / (GLfloat)Video.Height *Y + 1.0f,
1145 2.0f / (GLfloat)Video.Width *(X + W) - 1.0f, -2.0f / (GLfloat)Video.Height *Y + 1.0f,
1146 2.0f / (GLfloat)Video.Width *X - 1.0f, -2.0f / (GLfloat)Video.Height *(Y + H) + 1.0f,
1147 2.0f / (GLfloat)Video.Width *(X + W) - 1.0f, -2.0f / (GLfloat)Video.Height *(Y + H) + 1.0f
1148 };
1149
1150 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1151 glEnableClientState(GL_VERTEX_ARRAY);
1152
1153 glTexCoordPointer(2, GL_FLOAT, 0, texCoord);
1154 glVertexPointer(2, GL_FLOAT, 0, vertex);
1155 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1156
1157 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1158 glDisableClientState(GL_VERTEX_ARRAY);
1159 #endif
1160 #ifdef USE_OPENGL
1161 glBegin(GL_QUADS);
1162 glTexCoord2f(0.0f, 0.0f);
1163 glVertex2i(X, Y);
1164 //Wyrmgus start
1165 // glTexCoord2f(0.0f, (float)H / MinimapTextureHeight);
1166 glTexCoord2f(0.0f, (float)H / MinimapTextureHeight[UI.CurrentMapLayer->ID]);
1167 //Wyrmgus end
1168 glVertex2i(X, Y + H);
1169 //Wyrmgus start
1170 // glTexCoord2f((float)W / MinimapTextureWidth, (float)H / MinimapTextureHeight);
1171 glTexCoord2f((float)W / MinimapTextureWidth[UI.CurrentMapLayer->ID], (float)H / MinimapTextureHeight[UI.CurrentMapLayer->ID]);
1172 //Wyrmgus end
1173 glVertex2i(X + W, Y + H);
1174 //Wyrmgus start
1175 // glTexCoord2f((float)W / MinimapTextureWidth, 0.0f);
1176 glTexCoord2f((float)W / MinimapTextureWidth[UI.CurrentMapLayer->ID], 0.0f);
1177 //Wyrmgus end
1178 glVertex2i(X + W, Y);
1179 glEnd();
1180 #endif
1181 } else
1182 #endif
1183 {
1184 SDL_Rect drect = {Sint16(X), Sint16(Y), 0, 0};
1185 //Wyrmgus start
1186 // SDL_BlitSurface(MinimapSurface, nullptr, TheScreen, &drect);
1187 SDL_BlitSurface(MinimapSurface[UI.CurrentMapLayer->ID], nullptr, TheScreen, &drect);
1188 //Wyrmgus end
1189 }
1190
1191 DrawEvents();
1192 }
1193
1194 /**
1195 ** Convert screen position to tile map coordinate.
1196 **
1197 ** @param screenPos Screen pixel coordinate.
1198 **
1199 ** @return Tile coordinate.
1200 */
ScreenToTilePos(const PixelPos & screenPos) const1201 Vec2i CMinimap::ScreenToTilePos(const PixelPos &screenPos) const
1202 {
1203 //Wyrmgus start
1204 // Vec2i tilePos((((screenPos.x - X - XOffset) * MINIMAP_FAC) / MinimapScaleX),
1205 // (((screenPos.y - Y - YOffset) * MINIMAP_FAC) / MinimapScaleY));
1206 Vec2i tilePos((((screenPos.x - X - XOffset[UI.CurrentMapLayer->ID]) * MINIMAP_FAC) / MinimapScaleX[UI.CurrentMapLayer->ID]),
1207 (((screenPos.y - Y - YOffset[UI.CurrentMapLayer->ID]) * MINIMAP_FAC) / MinimapScaleY[UI.CurrentMapLayer->ID]));
1208 //Wyrmgus end
1209
1210 //Wyrmgus start
1211 // Map.Clamp(tilePos);
1212 Map.Clamp(tilePos, UI.CurrentMapLayer->ID);
1213 //Wyrmgus end
1214 return tilePos;
1215 }
1216
1217 /**
1218 ** Convert tile map coordinate to screen position.
1219 **
1220 ** @param tilePos Tile coordinate.
1221 **
1222 ** @return Screen pixel coordinate.
1223 */
TilePosToScreenPos(const Vec2i & tilePos) const1224 PixelPos CMinimap::TilePosToScreenPos(const Vec2i &tilePos) const
1225 {
1226 //Wyrmgus start
1227 // const PixelPos screenPos(X + XOffset + (tilePos.x * MinimapScaleX) / MINIMAP_FAC,
1228 // Y + YOffset + (tilePos.y * MinimapScaleY) / MINIMAP_FAC);
1229 const PixelPos screenPos(X + XOffset[UI.CurrentMapLayer->ID] + (tilePos.x * MinimapScaleX[UI.CurrentMapLayer->ID]) / MINIMAP_FAC,
1230 Y + YOffset[UI.CurrentMapLayer->ID] + (tilePos.y * MinimapScaleY[UI.CurrentMapLayer->ID]) / MINIMAP_FAC);
1231 //Wyrmgus end
1232 return screenPos;
1233 }
1234
1235 /**
1236 ** Destroy mini-map.
1237 */
Destroy()1238 void CMinimap::Destroy()
1239 {
1240 #if defined(USE_OPENGL) || defined(USE_GLES)
1241 if (UseOpenGL) {
1242 //Wyrmgus start
1243 // delete[] MinimapTerrainSurfaceGL;
1244 // MinimapTerrainSurfaceGL = nullptr;
1245 // if (MinimapSurfaceGL) {
1246 // glDeleteTextures(1, &MinimapTexture);
1247 // delete[] MinimapSurfaceGL;
1248 // MinimapSurfaceGL = nullptr;
1249 // }
1250 for (size_t z = 0; z < MinimapTerrainSurfaceGL.size(); ++z) {
1251 delete[] MinimapTerrainSurfaceGL[z];
1252 MinimapTerrainSurfaceGL[z] = nullptr;
1253 }
1254 MinimapTerrainSurfaceGL.clear();
1255 for (size_t z = 0; z < MinimapSurfaceGL.size(); ++z) {
1256 if (MinimapSurfaceGL[z]) {
1257 //Wyrmgus start
1258 // glDeleteTextures(1, &MinimapTexture);
1259 glDeleteTextures(1, &MinimapTexture[z]);
1260 //Wyrmgus end
1261 delete[] MinimapSurfaceGL[z];
1262 MinimapSurfaceGL[z] = nullptr;
1263 }
1264 }
1265 MinimapSurfaceGL.clear();
1266 MinimapTexture.clear();
1267 //Wyrmgus end
1268 } else
1269 #endif
1270 {
1271 //Wyrmgus start
1272 // VideoPaletteListRemove(MinimapTerrainSurface);
1273 // SDL_FreeSurface(MinimapTerrainSurface);
1274 // MinimapTerrainSurface = nullptr;
1275 // if (MinimapSurface) {
1276 // VideoPaletteListRemove(MinimapSurface);
1277 // SDL_FreeSurface(MinimapSurface);
1278 // MinimapSurface = nullptr;
1279 // }
1280 for (size_t z = 0; z < MinimapTerrainSurface.size(); ++z) {
1281 VideoPaletteListRemove(MinimapTerrainSurface[z]);
1282 SDL_FreeSurface(MinimapTerrainSurface[z]);
1283 MinimapTerrainSurface[z] = nullptr;
1284 }
1285 MinimapTerrainSurface.clear();
1286 for (size_t z = 0; z < MinimapSurface.size(); ++z) {
1287 if (MinimapSurface[z]) {
1288 VideoPaletteListRemove(MinimapSurface[z]);
1289 SDL_FreeSurface(MinimapSurface[z]);
1290 MinimapSurface[z] = nullptr;
1291 }
1292 }
1293 MinimapSurface.clear();
1294 //Wyrmgus end
1295 }
1296 //Wyrmgus start
1297 // delete[] Minimap2MapX;
1298 // Minimap2MapX = nullptr;
1299 // delete[] Minimap2MapY;
1300 // Minimap2MapY = nullptr;
1301 for (size_t z = 0; z < Minimap2MapX.size(); ++z) {
1302 delete[] Minimap2MapX[z];
1303 Minimap2MapX[z] = nullptr;
1304 }
1305 Minimap2MapX.clear();
1306 for (size_t z = 0; z < Minimap2MapY.size(); ++z) {
1307 delete[] Minimap2MapY[z];
1308 Minimap2MapY[z] = nullptr;
1309 }
1310 Minimap2MapY.clear();
1311 for (size_t z = 0; z < Map2MinimapX.size(); ++z) {
1312 delete[] Map2MinimapX[z];
1313 Map2MinimapX[z] = nullptr;
1314 }
1315 Map2MinimapX.clear();
1316 for (size_t z = 0; z < Map2MinimapY.size(); ++z) {
1317 delete[] Map2MinimapY[z];
1318 Map2MinimapY[z] = nullptr;
1319 }
1320 Map2MinimapY.clear();
1321 MinimapScaleX.clear();
1322 MinimapScaleY.clear();
1323 XOffset.clear();
1324 YOffset.clear();
1325 //Wyrmgus end
1326 }
1327
1328 /**
1329 ** Draw viewport area contour.
1330 */
DrawViewportArea(const CViewport & viewport) const1331 void CMinimap::DrawViewportArea(const CViewport &viewport) const
1332 {
1333 // Determine and save region below minimap cursor
1334 const PixelPos screenPos = TilePosToScreenPos(viewport.MapPos);
1335 //Wyrmgus start
1336 // int w = (viewport.MapWidth * MinimapScaleX) / MINIMAP_FAC;
1337 // int h = (viewport.MapHeight * MinimapScaleY) / MINIMAP_FAC;
1338 int w = (viewport.MapWidth * MinimapScaleX[UI.CurrentMapLayer->ID]) / MINIMAP_FAC;
1339 int h = (viewport.MapHeight * MinimapScaleY[UI.CurrentMapLayer->ID]) / MINIMAP_FAC;
1340 //Wyrmgus end
1341
1342 // Draw cursor as rectangle (Note: unclipped, as it is always visible)
1343 //Wyrmgus start
1344 // Video.DrawTransRectangle(UI.ViewportCursorColor, screenPos.x, screenPos.y, w, h, 128);
1345 Video.DrawTransRectangle(UI.ViewportCursorColor, screenPos.x, screenPos.y, w + 1, h + 1, 128);
1346 //Wyrmgus end
1347 }
1348
1349 /**
1350 ** Add a minimap event
1351 **
1352 ** @param pos Map tile position
1353 */
1354 //Wyrmgus start
1355 //void CMinimap::AddEvent(const Vec2i &pos, Uint32 color)
AddEvent(const Vec2i & pos,int z,Uint32 color)1356 void CMinimap::AddEvent(const Vec2i &pos, int z, Uint32 color)
1357 //Wyrmgus end
1358 {
1359 if (NumMinimapEvents == MAX_MINIMAP_EVENTS) {
1360 return;
1361 }
1362 if (z == UI.CurrentMapLayer->ID) {
1363 MinimapEvents[NumMinimapEvents].pos = TilePosToScreenPos(pos);
1364 MinimapEvents[NumMinimapEvents].Size = (W < H) ? W / 3 : H / 3;
1365 MinimapEvents[NumMinimapEvents].Color = color;
1366 ++NumMinimapEvents;
1367 } else {
1368 CMapLayer *event_map_layer = Map.MapLayers[z];
1369 if (event_map_layer->Plane != nullptr && Map.GetCurrentPlane() != event_map_layer->Plane && UI.PlaneButtons[event_map_layer->Plane->ID].X != -1) {
1370 MinimapEvents[NumMinimapEvents].pos.x = UI.PlaneButtons[event_map_layer->Plane->ID].X + (UI.PlaneButtons[event_map_layer->Plane->ID].Style->Width / 2);
1371 MinimapEvents[NumMinimapEvents].pos.y = UI.PlaneButtons[event_map_layer->Plane->ID].Y + (UI.PlaneButtons[event_map_layer->Plane->ID].Style->Height / 2);
1372 } else if (event_map_layer->World != nullptr && Map.GetCurrentWorld() != event_map_layer->World && UI.WorldButtons[event_map_layer->World->ID].X != -1) {
1373 MinimapEvents[NumMinimapEvents].pos.x = UI.WorldButtons[event_map_layer->World->ID].X + (UI.WorldButtons[event_map_layer->World->ID].Style->Width / 2);
1374 MinimapEvents[NumMinimapEvents].pos.y = UI.WorldButtons[event_map_layer->World->ID].Y + (UI.WorldButtons[event_map_layer->World->ID].Style->Height / 2);
1375 } else if (Map.GetCurrentSurfaceLayer() != event_map_layer->SurfaceLayer && UI.SurfaceLayerButtons[event_map_layer->SurfaceLayer].X != -1) {
1376 MinimapEvents[NumMinimapEvents].pos.x = UI.SurfaceLayerButtons[event_map_layer->SurfaceLayer].X + (UI.SurfaceLayerButtons[event_map_layer->SurfaceLayer].Style->Width / 2);
1377 MinimapEvents[NumMinimapEvents].pos.y = UI.SurfaceLayerButtons[event_map_layer->SurfaceLayer].Y + (UI.SurfaceLayerButtons[event_map_layer->SurfaceLayer].Style->Height / 2);
1378 } else {
1379 return;
1380 }
1381 MinimapEvents[NumMinimapEvents].Size = (W < H) ? W / 3 : H / 3;
1382 MinimapEvents[NumMinimapEvents].Color = color;
1383 ++NumMinimapEvents;
1384 }
1385 }
1386
Contains(const PixelPos & screenPos) const1387 bool CMinimap::Contains(const PixelPos &screenPos) const
1388 {
1389 return this->X <= screenPos.x && screenPos.x < this->X + this->W
1390 && this->Y <= screenPos.y && screenPos.y < this->Y + this->H;
1391 }
1392
1393 //@}
1394