29 #include "table/strings.h"
52 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
55 #define MC(col_break) {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, col_break}
58 #define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
61 #define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false}
64 #define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false}
70 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, true}
75 MK(
PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
99 MK(
PC_RED, STR_SMALLMAP_LEGENDA_TRAINS),
104 MS(
PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
111 MK(
PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
115 MK(
PC_ORANGE, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY),
117 MK(
PC_RED, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT),
133 MK(
PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
140 MO(0x00, STR_SMALLMAP_LEGENDA_NO_OWNER),
184 _legend_from_industries[j].
legend = indsp->
name;
186 _legend_from_industries[j].
type = ind;
188 _legend_from_industries[j].
col_break =
false;
189 _legend_from_industries[j].
end =
false;
197 _legend_from_industries[j].
end =
true;
209 memset(_legend_linkstats, 0,
sizeof(_legend_linkstats));
216 _legend_linkstats[i].
colour = cs->legend_colour;
225 _legend_linkstats[i].
legend = STR_EMPTY;
231 _legend_linkstats[i - 1].
legend = STR_LINKGRAPH_LEGEND_OVERLOADED;
233 _legend_linkstats[i].
end =
true;
246 #define MKCOLOUR(x) TO_LE32X(x)
248 #define MKCOLOUR_XXXX(x) (MKCOLOUR(0x01010101) * (uint)(x))
249 #define MKCOLOUR_X0X0(x) (MKCOLOUR(0x01000100) * (uint)(x))
250 #define MKCOLOUR_0X0X(x) (MKCOLOUR(0x00010001) * (uint)(x))
251 #define MKCOLOUR_0XX0(x) (MKCOLOUR(0x00010100) * (uint)(x))
252 #define MKCOLOUR_X00X(x) (MKCOLOUR(0x01000001) * (uint)(x))
254 #define MKCOLOUR_XYXY(x, y) (MKCOLOUR_X0X0(x) | MKCOLOUR_0X0X(y))
255 #define MKCOLOUR_XYYX(x, y) (MKCOLOUR_X00X(x) | MKCOLOUR_0XX0(y))
257 #define MKCOLOUR_0000 MKCOLOUR_XXXX(0x00)
258 #define MKCOLOUR_0FF0 MKCOLOUR_0XX0(0xFF)
259 #define MKCOLOUR_F00F MKCOLOUR_X00X(0xFF)
260 #define MKCOLOUR_FFFF MKCOLOUR_XXXX(0xFF)
285 if (_heightmap_schemes[0].height_colours == NULL)
return;
307 uint deltas[][2] = { { 24, 2 }, { 48, 4 }, { 72, 6 }, { 120, 10 }, { 180, 15 }, { 240, 20 }, {
MAX_TILE_HEIGHT + 1, 25 }};
312 uint delta = deltas[i][1];
315 int rows =
CeilDiv(total_entries, 2);
318 for (i = 0; i <
lengthof(_legend_land_contours) - 1 && j < total_entries; i++) {
319 if (_legend_land_contours[i].legend != STR_TINY_BLACK_HEIGHT)
continue;
321 _legend_land_contours[i].
col_break = j % rows == 0;
322 _legend_land_contours[i].
end =
false;
323 _legend_land_contours[i].
height = j * delta;
327 _legend_land_contours[i].
end =
true;
339 FOR_ALL_COMPANIES(c) {
343 _legend_land_owners[i].
col_break =
false;
344 _legend_land_owners[i].
end =
false;
350 _legend_land_owners[i].
end =
true;
361 static inline uint32 ApplyMask(uint32 colour,
const AndOr *mask)
363 return (colour & mask->mand) | mask->mor;
369 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
370 {MKCOLOUR_0XX0(
PC_GREY ), MKCOLOUR_F00F},
371 {MKCOLOUR_0XX0(
PC_BLACK ), MKCOLOUR_F00F},
373 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
375 {MKCOLOUR_XXXX(
PC_WATER ), MKCOLOUR_0000},
376 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
378 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
380 {MKCOLOUR_0XX0(
PC_GREY ), MKCOLOUR_F00F},
385 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
386 {MKCOLOUR_0XX0(
PC_BLACK ), MKCOLOUR_F00F},
387 {MKCOLOUR_0XX0(
PC_BLACK ), MKCOLOUR_F00F},
389 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
390 {MKCOLOUR_0XX0(
PC_BLACK ), MKCOLOUR_F00F},
391 {MKCOLOUR_XXXX(
PC_WATER ), MKCOLOUR_0000},
392 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
394 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
396 {MKCOLOUR_0XX0(
PC_BLACK ), MKCOLOUR_F00F},
438 return ApplyMask(cs->
default_colour, &_smallmap_vehicles_andor[t]);
466 case STATION_AIRPORT:
return MKCOLOUR_XXXX(
PC_RED);
467 case STATION_TRUCK:
return MKCOLOUR_XXXX(
PC_ORANGE);
468 case STATION_BUS:
return MKCOLOUR_XXXX(
PC_YELLOW);
470 default:
return MKCOLOUR_FFFF;
475 _smallmap_contours_andor[t].mand
484 return ApplyMask(cs->
default_colour, &_smallmap_contours_andor[t]);
499 static const uint32 _vegetation_clear_bits[] = {
533 return ApplyMask(MKCOLOUR_XXXX(
PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
575 inline Point SmallMapWindow::SmallmapRemapCoords(
int x,
int y)
const
594 if (this->
zoom == 1)
return SmallmapRemapCoords(x_offset, y_offset);
597 if (x_offset < 0) x_offset -= this->
zoom - 1;
598 if (y_offset < 0) y_offset -= this->
zoom - 1;
600 return SmallmapRemapCoords(x_offset / this->
zoom, y_offset / this->
zoom);
619 Point pt = {((py >> 1) - (px >> 2)) * this->
zoom, ((py >> 1) + (px >> 2)) * this->
zoom};
647 assert(x >= 0 && y >= 0);
675 static const int zoomlevels[] = {1, 2, 4, 6, 8};
676 static const int MIN_ZOOM_INDEX = 0;
677 static const int MAX_ZOOM_INDEX =
lengthof(zoomlevels) - 1;
679 int new_index, cur_index, sub;
684 new_index = MIN_ZOOM_INDEX;
690 for (cur_index = MIN_ZOOM_INDEX; cur_index <= MAX_ZOOM_INDEX; cur_index++) {
691 if (this->
zoom == zoomlevels[cur_index])
break;
693 assert(cur_index <= MAX_ZOOM_INDEX);
695 tile = this->
PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
696 new_index =
Clamp(cur_index + ((change ==
ZLC_ZOOM_IN) ? -1 : 1), MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
699 default: NOT_REACHED();
702 if (new_index != cur_index) {
703 this->
zoom = zoomlevels[new_index];
704 if (cur_index >= 0) {
707 this->scroll_y + (tile.y - new_tile.y) *
TILE_SIZE, sub);
708 }
else if (this->
map_type == SMT_LINKSTATS) {
745 if (this->
map_type == SMT_INDUSTRY) {
765 if (_tiletype_importance[ttype] > importance) {
766 importance = _tiletype_importance[ttype];
794 default: NOT_REACHED();
813 void *dst_ptr_abs_end = blitter->
MoveTo(_screen.dst_ptr, 0, _screen.height);
821 if (dst < _screen.dst_ptr)
continue;
822 if (dst >= dst_ptr_abs_end)
continue;
826 if (min_xy == 1 && (xc == 0 || yc == 0)) {
827 if (this->
zoom == 1)
continue;
836 uint8 *val8 = (uint8 *)&val;
837 int idx =
max(0, -start_pos);
838 for (
int pos =
max(0, start_pos); pos < end_pos; pos++) {
839 blitter->
SetPixel(dst, idx, 0, val8[idx]);
843 }
while (xc += this->
zoom, yc += this->
zoom, dst = blitter->
MoveTo(dst, pitch, 0), --reps != 0);
861 int y = pt.y - dpi->top;
865 int x = pt.x - this->
subscroll - 3 - dpi->left;
869 if (++x != 0)
continue;
871 }
else if (x >= dpi->width - 1) {
873 if (x != dpi->width - 1)
continue;
881 blitter->
SetPixel(dpi->dst_ptr, x, y, colour);
882 if (!skip) blitter->
SetPixel(dpi->dst_ptr, x + 1, y, colour);
901 x < dpi->
left + dpi->width &&
903 y < dpi->
top + dpi->height) {
922 Point upper_left = this->
RemapTile(upper_left_smallmap_coord.x / (
int)
TILE_SIZE, upper_left_smallmap_coord.y / (
int)TILE_SIZE);
925 Point lower_right = this->
RemapTile(lower_right_smallmap_coord.x / (
int)TILE_SIZE, lower_right_smallmap_coord.y / (
int)TILE_SIZE);
955 GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1,
PC_BLACK);
961 int tile_y = this->scroll_y / (
int)
TILE_SIZE + tile.y;
963 void *ptr = blitter->
MoveTo(dpi->dst_ptr, -dx - 4, 0);
970 if (x >= dpi->width)
break;
972 int end_pos =
min(dpi->width, x + 4);
973 int reps = (dpi->height - y + 1) / 2;
975 this->
DrawSmallMapColumn(ptr, tile_x, tile_y, dpi->pitch * 2, reps, x, end_pos, blitter);
980 tile_y += this->
zoom;
982 ptr = blitter->
MoveTo(ptr, 0, 1);
984 tile_x -= this->
zoom;
986 ptr = blitter->
MoveTo(ptr, 0, -1);
988 ptr = blitter->
MoveTo(ptr, 2, 0);
996 if (this->
map_type == SMT_LINKSTATS) this->overlay->
Draw(dpi);
1018 legend_tooltip = STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION;
1019 enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_INDUSTRIES;
1020 disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES;
1025 legend_tooltip = STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION;
1026 enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES;
1027 disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES;
1032 legend_tooltip = STR_SMALLMAP_TOOLTIP_CARGO_SELECTION;
1033 enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS;
1034 disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_CARGOS;
1039 legend_tooltip = STR_NULL;
1040 enable_all_tooltip = STR_NULL;
1041 disable_all_tooltip = STR_NULL;
1052 SmallMapWindow::SmallMapWindow(
WindowDesc *desc,
int window_number) :
Window(desc), refresh(FORCE_REFRESH_PERIOD)
1080 for (uint n = 0; n <
lengthof(_heightmap_schemes); n++) {
1085 for (
int z = 0; z < heights; z++) {
1086 size_t access_index = (_heightmap_schemes[n].
colour_count * z) / heights;
1111 for (uint i = 0; i <
lengthof(_legend_table); i++) {
1113 uint num_columns = 1;
1116 if (i == SMT_INDUSTRY) {
1119 str = STR_SMALLMAP_INDUSTRY;
1120 }
else if (i == SMT_LINKSTATS) {
1122 str = STR_SMALLMAP_LINKSTATS;
1123 }
else if (i == SMT_OWNER) {
1133 str = STR_SMALLMAP_COMPANY;
1138 if (tbl->col_break) {
1177 if (!
FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1))
return;
1200 string = STR_SMALLMAP_INDUSTRY;
1203 string = STR_SMALLMAP_LINKSTATS;
1206 string = STR_SMALLMAP_COMPANY;
1213 if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER || this->map_type == SMT_LINKSTATS) && i++ >= number_of_rows)) {
1221 uint8 legend_colour = tbl->colour;
1239 if (!tbl->show_on_map) {
1242 DrawString(x + text_left, x + text_right, y,
string, TC_GREY);
1244 DrawString(x + text_left, x + text_right, y,
string, TC_BLACK);
1254 DrawString(x + text_left, x + text_right, y, tbl->legend);
1257 GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, legend_colour);
1277 if (map_type == SMT_LINKSTATS) this->overlay->
RebuildCache();
1312 bool changes =
false;
1313 for (
int i = begin_legend_item; i != end_legend_item; i++) {
1314 bool new_state = (i == click_pos);
1315 if (legend[i].show_on_map != new_state) {
1322 for (
int i = begin_legend_item; i != end_legend_item; i++) {
1336 uint32 cargo_mask = 0;
1338 if (_legend_linkstats[i].show_on_map)
SetBit(cargo_mask, _legend_linkstats[i].type);
1354 if (line >= number_of_rows)
return -1;
1357 int x = pt.x - wi->
pos_x;
1361 return (column * number_of_rows) + line;
1370 new_highlight = _legend_from_industries[industry_pos].
type;
1445 if (click_pos < 0)
break;
1448 if (this->
map_type == SMT_INDUSTRY) {
1453 }
else if (this->
map_type == SMT_LINKSTATS) {
1458 }
else if (this->
map_type == SMT_OWNER) {
1484 for (;!tbl->
end && tbl->
legend != STR_LINKGRAPH_LEGEND_UNUSED; ++tbl) {
1510 if (!gui_scope)
return;
1523 _legend_from_industries[i].
show_on_map = _displayed_industries.test(_legend_from_industries[i].type);
1532 default: NOT_REACHED();
1549 int cursor_x = _cursor.
pos.x - this->
left - wid->
pos_x;
1550 int cursor_y = _cursor.
pos.y - this->
top - wid->
pos_y;
1552 Point pt = {cursor_x, cursor_y};
1561 if (--this->
refresh != 0)
return;
1563 if (this->
map_type == SMT_LINKSTATS) {
1649 int x = (st->
rect.right + st->
rect.left + 1) / 2;
1650 int y = (st->
rect.bottom + st->
rect.top + 1) / 2;
1716 uint bar_height =
max(bar->
smallest_y, this->smallmap_window->GetLegendHeight(this->smallmap_window->GetNumberColumnsLegend(given_width - bar->
smallest_x)));
1717 uint display_height = given_height - bar_height;
1725 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
1727 if (widget != NULL)
return widget;
1734 for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) child_wid->Draw(w);
1741 NWidget(
WWT_INSET, COLOUR_BROWN,
WID_SM_MAP),
SetMinimalSize(346, 140),
SetResize(1, 1),
SetPadding(2, 2, 2, 2),
EndContainer(),
1754 SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
SetFill(1, 1),
1760 SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP),
SetFill(1, 1),
1762 SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP),
SetFill(1, 1),
1764 SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP),
SetFill(1, 1),
1769 SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
SetFill(1, 1),
1771 SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF),
SetFill(1, 1),
1773 SetDataTip(SPR_IMG_CARGOFLOW, STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP),
SetFill(1, 1),
1775 SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON),
SetFill(1, 1),
1777 SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP),
SetFill(1, 1),
1779 SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP),
SetFill(1, 1),
1787 static NWidgetBase *SmallMapDisplay(
int *biggest_index)
1791 MakeNWidgets(_nested_smallmap_display,
lengthof(_nested_smallmap_display), biggest_index, map_display);
1792 MakeNWidgets(_nested_smallmap_bar,
lengthof(_nested_smallmap_bar), biggest_index, map_display);
1797 static const NWidgetPart _nested_smallmap_widgets[] = {
1827 _nested_smallmap_widgets,
lengthof(_nested_smallmap_widgets)
1835 AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
1854 if (res)
return res;