1 // tool "framework"
2 #include "maplib.h"
3
4 #include "mapload.h"
5 #include "pngsave.h"
6
7 #include "vector.h"
8
9 struct PreviewColors
10 {
11 Vector3i cliffLow;
12 Vector3i cliffHigh;
13 Vector3i water;
14 Vector3i roadLow;
15 Vector3i roadHigh;
16 Vector3i groundLow;
17 Vector3i groundHigh;
18 };
19
20 // C1 - Arizona type
21 static const PreviewColors pArizonaColors = {
22 Vector3i (0x68, 0x3C, 0x24),
23 Vector3i (0xE8, 0x84, 0x5C),
24 Vector3i (0x3F, 0x68, 0x9A),
25 Vector3i (0x24, 0x1F, 0x16),
26 Vector3i (0xB2, 0x9A, 0x66),
27 Vector3i (0x24, 0x1F, 0x16),
28 Vector3i (0xCC, 0xB2, 0x80)};
29
30 // C2 - Urban type
31 static const PreviewColors pUrbanColors = {
32 Vector3i (0x3C, 0x3C, 0x3C),
33 Vector3i (0x84, 0x84, 0x84),
34 Vector3i (0x3F, 0x68, 0x9A),
35 Vector3i (0x00, 0x00, 0x00),
36 Vector3i (0x24, 0x1F, 0x16),
37 Vector3i (0x1F, 0x1F, 0x1F),
38 Vector3i (0xB2, 0xB2, 0xB2)};
39
40 // C3 - Rockies type
41 static const PreviewColors pRockiesColors = {
42 Vector3i (0x3C, 0x3C, 0x3C),
43 Vector3i (0xFF, 0xFF, 0xFF),
44 Vector3i (0x3F, 0x68, 0x9A),
45 Vector3i (0x24, 0x1F, 0x16),
46 Vector3i (0x3D, 0x21, 0x0A),
47 Vector3i (0x00, 0x1C, 0x0E),
48 Vector3i (0xFF, 0xFF, 0xFF)};
49
50 Vector3i clanColours[]=
51 { // see frontend2.png for team color order.
52 // [r,g,b]
53 Vector3i (0,255,0), // green Player 0
54 Vector3i (255,210,40), // orange Player 1
55 Vector3i (255,255,255), // grey Player 2
56 Vector3i (0,0,0), // black Player 3
57 Vector3i (255,0,0), // red Player 4
58 Vector3i (20,20,255), // blue Player 5
59 Vector3i (255,0,255), // pink Player 6 (called purple in palette.txt)
60 Vector3i (0,255,255), // cyan Player 7
61 Vector3i (255,255,0), // yellow Player 8
62 Vector3i (192,0,255), // pink Player 9
63 Vector3i (200,255,255), // white Player A (Should be brighter than grey, but grey is already maximum.)
64 Vector3i (128,128,255), // bright blue Player B
65 Vector3i (128,255,128), // neon green Player C
66 Vector3i (128,0,0), // infrared Player D
67 Vector3i (64,0,128), // ultraviolet Player E
68 Vector3i (128,128,0) // brown Player F
69 };
70
paintStructureData(uint8_t * pixels,GAMEMAP * map)71 static void paintStructureData(uint8_t *pixels, GAMEMAP *map)
72 {
73 const int height = (int) map->height;
74 uint32_t x, y;
75 Vector3i color;
76
77 for (int i = 0; i < map->numStructures; i++)
78 {
79 LND_OBJECT *psObj = &map->mLndObjects[IMD_STRUCTURE][i];
80
81 if (strcmp(psObj->name, "A0PowMod1") == 0 ||
82 strcmp(psObj->name, "A0FacMod1") == 0 ||
83 strcmp(psObj->name, "A0ResearchModule1") == 0)
84 {
85 continue; // ignore modules.
86 }
87
88 color = clanColours[psObj->player];
89 if (strcmp(psObj->name, "A0CommandCentre") == 0)
90 {
91 color = Vector3i(0xFF,0,0xFF); // base/palette.txt - WZCOL_MAP_PREVIEW_HQ
92 }
93
94 x = map_coord(psObj->x);
95 y = height - 1 - map_coord(psObj->y); // Origin at the top
96
97 uint8_t * const p = &pixels[(y * map->width + x) * 3];
98 p[0] = color.x;
99 p[1] = color.y;
100 p[2] = color.z;
101 }
102 }
103
main(int argc,char ** argv)104 int main(int argc, char **argv)
105 {
106 char *filename, *p_filename;
107 char *base, tmpFile[PATH_MAX];
108 GAMEMAP *map;
109 MAPTILE *psTile;
110
111 if (argc != 2)
112 {
113 printf("Usage: %s <map>\n", argv[0]);
114 return -1;
115 }
116
117 physfs_init(argv[0]);
118 filename = physfs_addmappath(argv[1]);
119
120 p_filename = strrchr(filename, '/');
121 if (p_filename)
122 {
123 p_filename++;
124 base = strdup(p_filename);
125 }
126 else
127 {
128 base = strdup(filename);
129 }
130
131 map = mapLoad(filename);
132 free(filename);
133
134 if (!map)
135 {
136 return EXIT_FAILURE;
137 }
138
139 const PreviewColors* tileColors = NULL;
140 switch (map->tileset)
141 {
142 case TILESET_ARIZONA:
143 tileColors = &pArizonaColors;
144 break;
145 case TILESET_URBAN:
146 tileColors = &pUrbanColors;
147 break;
148 case TILESET_ROCKIES:
149 tileColors = &pRockiesColors;
150 break;
151 default:
152 fprintf(stderr, "Unknown tileset: %d\n", (int)map->tileset);
153 mapFree(map);
154 physfs_shutdown();
155 return EXIT_FAILURE;
156 }
157
158 const int mapWidth = (int) map->width;
159 const int mapHeight = (int) map->height;
160 int col;
161
162 // RGB888 pixels
163 uint8_t *pixels = (uint8_t*) malloc(sizeof(uint8_t) * mapWidth * mapHeight * 3);
164
165 for (int y = 0; y < mapHeight; y++)
166 {
167 for (int x = 0; x < mapWidth; x++)
168 {
169 // We're placing the origin at the top for aesthetic reasons
170 psTile = mapTile(map, x, mapHeight-1-y);
171 col = psTile->height / 2; // 2 = ELEVATION_SCALE
172 uint8_t * const p = &pixels[(y * map->width + x) * 3];
173 switch(terrainType(psTile))
174 {
175 case TER_CLIFFFACE:
176 p[0] = tileColors->cliffLow.x + (tileColors->cliffHigh.x - tileColors->cliffLow.x) * col / 256;
177 p[1] = tileColors->cliffLow.y + (tileColors->cliffHigh.y - tileColors->cliffLow.y) * col / 256;
178 p[2] = tileColors->cliffLow.z + (tileColors->cliffHigh.z - tileColors->cliffLow.z) * col / 256;
179 break;
180 case TER_WATER:
181 p[0] = tileColors->water.x;
182 p[1] = tileColors->water.y;
183 p[2] = tileColors->water.z;
184 break;
185 case TER_ROAD:
186 p[0] = tileColors->roadLow.x + (tileColors->roadHigh.x - tileColors->roadLow.x) * col / 256;
187 p[1] = tileColors->roadLow.y + (tileColors->roadHigh.y - tileColors->roadLow.y) * col / 256;
188 p[2] = tileColors->roadLow.z + (tileColors->roadHigh.z - tileColors->roadLow.z) * col / 256;
189 break;
190 default:
191 p[0] = tileColors->groundLow.x + (tileColors->groundHigh.x - tileColors->groundLow.x) * col / 256;
192 p[1] = tileColors->groundLow.y + (tileColors->groundHigh.y - tileColors->groundLow.y) * col / 256;
193 p[2] = tileColors->groundLow.z + (tileColors->groundHigh.z - tileColors->groundLow.z) * col / 256;
194 break;
195 }
196 }
197 }
198
199 paintStructureData(pixels, map);
200
201 strcpy(tmpFile, base);
202 strcat(tmpFile, ".png");
203
204 savePng(tmpFile, pixels, mapWidth, mapHeight);
205
206 free(pixels);
207
208 mapFree(map);
209
210 physfs_shutdown();
211
212 return 0;
213 }
214