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