diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp
--- a/src/smallmap_gui.cpp
+++ b/src/smallmap_gui.cpp
@@ -32,13 +32,6 @@
#include "table/strings.h"
#include "table/sprites.h"
-struct smallmap_d {
- int32 scroll_x;
- int32 scroll_y;
- int32 subscroll;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(smallmap_d));
-
static const Widget _smallmap_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_RIGHT, 13, 11, 337, 0, 13, STR_00B0_MAP, STR_018C_WINDOW_TITLE_DRAG_THIS},
@@ -561,539 +554,536 @@ enum SmallMapWindowWidgets {
SM_WIDGET_RESIZEBOX,
};
-enum SmallMapType {
- SMT_CONTOUR,
- SMT_VEHICLES,
- SMT_INDUSTRY,
- SMT_OWNER = 5,
-};
-
-/**
- * Draws the small map.
- *
- * Basically, the small map is draw column of pixels by column of pixels. The pixels
- * are drawn directly into the screen buffer. The final map is drawn in multiple passes.
- * The passes are:
- *
- The colors of tiles in the different modes.
- * - Town names (optional)
- *
- * @param dpi pointer to pixel to write onto
- * @param w pointer to Window struct
- * @param type type of map requested (vegetation, owners, routes, etc)
- * @param show_towns true if the town names should be displayed, false if not.
- */
-static void DrawSmallMap(DrawPixelInfo *dpi, Window *w, int type, bool show_towns)
+class SmallMapWindow : public Window
{
- Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
- DrawPixelInfo *old_dpi;
- int dx,dy, x, y, x2, y2;
- void *ptr;
- int tile_x;
- int tile_y;
- ViewPort *vp;
+ enum SmallMapType {
+ SMT_CONTOUR,
+ SMT_VEHICLES,
+ SMT_INDUSTRY,
+ SMT_OWNER = 5,
+ };
+
+ enum {
+ BASE_NB_PER_COLUMN = 6,
+ };
+
+ int32 scroll_x;
+ int32 scroll_y;
+ int32 subscroll;
- old_dpi = _cur_dpi;
- _cur_dpi = dpi;
-
- /* clear it */
- GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 0);
+public:
+ /**
+ * Draws the small map.
+ *
+ * Basically, the small map is draw column of pixels by column of pixels. The pixels
+ * are drawn directly into the screen buffer. The final map is drawn in multiple passes.
+ * The passes are:
+ * - The colors of tiles in the different modes.
+ * - Town names (optional)
+ *
+ * @param dpi pointer to pixel to write onto
+ * @param w pointer to Window struct
+ * @param type type of map requested (vegetation, owners, routes, etc)
+ * @param show_towns true if the town names should be displayed, false if not.
+ */
+ void DrawSmallMap(DrawPixelInfo *dpi, int type, bool show_towns)
+ {
+ Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
+ DrawPixelInfo *old_dpi;
+ int dx,dy, x, y, x2, y2;
+ void *ptr;
+ int tile_x;
+ int tile_y;
+ ViewPort *vp;
- /* setup owner table */
- if (type == SMT_OWNER) {
- const Player *p;
+ old_dpi = _cur_dpi;
+ _cur_dpi = dpi;
+
+ /* clear it */
+ GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 0);
+
+ /* setup owner table */
+ if (type == SMT_OWNER) {
+ const Player *p;
+
+ /* fill with some special colors */
+ _owner_colors[OWNER_TOWN] = MKCOLOR(0xB4B4B4B4);
+ _owner_colors[OWNER_NONE] = MKCOLOR(0x54545454);
+ _owner_colors[OWNER_WATER] = MKCOLOR(0xCACACACA);
+ _owner_colors[OWNER_END] = MKCOLOR(0x20202020); /* industry */
- /* fill with some special colors */
- _owner_colors[OWNER_TOWN] = MKCOLOR(0xB4B4B4B4);
- _owner_colors[OWNER_NONE] = MKCOLOR(0x54545454);
- _owner_colors[OWNER_WATER] = MKCOLOR(0xCACACACA);
- _owner_colors[OWNER_END] = MKCOLOR(0x20202020); /* industry */
+ /* now fill with the player colors */
+ FOR_ALL_PLAYERS(p) {
+ if (p->is_active) {
+ _owner_colors[p->index] =
+ _colour_gradient[p->player_color][5] * 0x01010101;
+ }
+ }
+ }
+
+ tile_x = this->scroll_x / TILE_SIZE;
+ tile_y = this->scroll_y / TILE_SIZE;
- /* now fill with the player colors */
- FOR_ALL_PLAYERS(p) {
- if (p->is_active) {
- _owner_colors[p->index] =
- _colour_gradient[p->player_color][5] * 0x01010101;
+ dx = dpi->left + this->subscroll;
+ tile_x -= dx / 4;
+ tile_y += dx / 4;
+ dx &= 3;
+
+ dy = dpi->top;
+ tile_x += dy / 2;
+ tile_y += dy / 2;
+
+ if (dy & 1) {
+ tile_x++;
+ dx += 2;
+ if (dx > 3) {
+ dx -= 4;
+ tile_x--;
+ tile_y++;
}
}
- }
+
+ ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
+ x = - dx - 4;
+ y = 0;
+
+ for (;;) {
+ uint32 mask = 0xFFFFFFFF;
+ int reps;
+ int t;
- tile_x = WP(w, smallmap_d).scroll_x / TILE_SIZE;
- tile_y = WP(w, smallmap_d).scroll_y / TILE_SIZE;
+ /* distance from left edge */
+ if (x < 0) {
+ if (x < -3) goto skip_column;
+ /* mask to use at the left edge */
+ mask = _smallmap_mask_left[x + 3];
+ }
+
+ /* distance from right edge */
+ t = dpi->width - x;
+ if (t < 4) {
+ if (t <= 0) break; /* exit loop */
+ /* mask to use at the right edge */
+ mask &= _smallmap_mask_right[t - 1];
+ }
- dx = dpi->left + WP(w, smallmap_d).subscroll;
- tile_x -= dx / 4;
- tile_y += dx / 4;
- dx &= 3;
+ /* number of lines */
+ reps = (dpi->height - y + 1) / 2;
+ if (reps > 0) {
+ DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, _smallmap_draw_procs[type]);
+ }
- dy = dpi->top;
- tile_x += dy / 2;
- tile_y += dy / 2;
+ skip_column:
+ if (y == 0) {
+ tile_y++;
+ y++;
+ ptr = blitter->MoveTo(ptr, 0, 1);
+ } else {
+ tile_x--;
+ y--;
+ ptr = blitter->MoveTo(ptr, 0, -1);
+ }
+ ptr = blitter->MoveTo(ptr, 2, 0);
+ x += 2;
+ }
+
+ /* draw vehicles? */
+ if (type == SMT_CONTOUR || type == SMT_VEHICLES) {
+ Vehicle *v;
+ bool skip;
+ byte color;
- if (dy & 1) {
- tile_x++;
- dx += 2;
- if (dx > 3) {
- dx -= 4;
- tile_x--;
- tile_y++;
- }
- }
+ FOR_ALL_VEHICLES(v) {
+ if (v->type != VEH_EFFECT &&
+ (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0) {
+ /* Remap into flat coordinates. */
+ Point pt = RemapCoords(
+ v->x_pos / TILE_SIZE - this->scroll_x / TILE_SIZE, // divide each one separately because (a-b)/c != a/c-b/c in integer world
+ v->y_pos / TILE_SIZE - this->scroll_y / TILE_SIZE, // dtto
+ 0);
+ x = pt.x;
+ y = pt.y;
+
+ /* Check if y is out of bounds? */
+ y -= dpi->top;
+ if (!IsInsideMM(y, 0, dpi->height)) continue;
+
+ /* Default is to draw both pixels. */
+ skip = false;
+
+ /* Offset X coordinate */
+ x -= this->subscroll + 3 + dpi->left;
+
+ if (x < 0) {
+ /* if x+1 is 0, that means we're on the very left edge,
+ * and should thus only draw a single pixel */
+ if (++x != 0) continue;
+ skip = true;
+ } else if (x >= dpi->width - 1) {
+ /* Check if we're at the very right edge, and if so draw only a single pixel */
+ if (x != dpi->width - 1) continue;
+ skip = true;
+ }
- ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
- x = - dx - 4;
- y = 0;
+ /* Calculate pointer to pixel and the color */
+ color = (type == SMT_VEHICLES) ? _vehicle_type_colors[v->type] : 0xF;
+
+ /* And draw either one or two pixels depending on clipping */
+ blitter->SetPixel(dpi->dst_ptr, x, y, color);
+ if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, color);
+ }
+ }
+ }
+
+ if (show_towns) {
+ const Town *t;
- for (;;) {
- uint32 mask = 0xFFFFFFFF;
- int reps;
- int t;
+ FOR_ALL_TOWNS(t) {
+ /* Remap the town coordinate */
+ Point pt = RemapCoords(
+ (int)(TileX(t->xy) * TILE_SIZE - this->scroll_x) / TILE_SIZE,
+ (int)(TileY(t->xy) * TILE_SIZE - this->scroll_y) / TILE_SIZE,
+ 0);
+ x = pt.x - this->subscroll + 3 - (t->sign.width_2 >> 1);
+ y = pt.y;
- /* distance from left edge */
- if (x < 0) {
- if (x < -3) goto skip_column;
- /* mask to use at the left edge */
- mask = _smallmap_mask_left[x + 3];
+ /* Check if the town sign is within bounds */
+ if (x + t->sign.width_2 > dpi->left &&
+ x < dpi->left + dpi->width &&
+ y + 6 > dpi->top &&
+ y < dpi->top + dpi->height) {
+ /* And draw it. */
+ SetDParam(0, t->index);
+ DrawString(x, y, STR_2056, TC_WHITE);
+ }
+ }
}
- /* distance from right edge */
- t = dpi->width - x;
- if (t < 4) {
- if (t <= 0) break; /* exit loop */
- /* mask to use at the right edge */
- mask &= _smallmap_mask_right[t - 1];
+ /* Draw map indicators */
+ {
+ Point pt;
+
+ /* Find main viewport. */
+ vp = FindWindowById(WC_MAIN_WINDOW,0)->viewport;
+
+ pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
+
+ x = vp->virtual_left - pt.x;
+ y = vp->virtual_top - pt.y;
+ x2 = (x + vp->virtual_width) / TILE_SIZE;
+ y2 = (y + vp->virtual_height) / TILE_SIZE;
+ x /= TILE_SIZE;
+ y /= TILE_SIZE;
+
+ x -= this->subscroll;
+ x2 -= this->subscroll;
+
+ DrawVertMapIndicator(x, y, x, y2);
+ DrawVertMapIndicator(x2, y, x2, y2);
+
+ DrawHorizMapIndicator(x, y, x2, y);
+ DrawHorizMapIndicator(x, y2, x2, y2);
+ }
+ _cur_dpi = old_dpi;
+ }
+
+ void SmallMapCenterOnCurrentPos()
+ {
+ int x, y;
+ ViewPort *vp;
+ vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
+
+ x = ((vp->virtual_width - (this->widget[SM_WIDGET_MAP].right - this->widget[SM_WIDGET_MAP].left) * TILE_SIZE) / 2 + vp->virtual_left) / 4;
+ y = ((vp->virtual_height - (this->widget[SM_WIDGET_MAP].bottom - this->widget[SM_WIDGET_MAP].top ) * TILE_SIZE) / 2 + vp->virtual_top ) / 2 - TILE_SIZE * 2;
+ this->scroll_x = (y - x) & ~0xF;
+ this->scroll_y = (x + y) & ~0xF;
+ this->SetDirty();
+ }
+
+ SmallMapWindow(const WindowDesc *desc, void *data, int window_number) : Window(desc, data, window_number)
+ {
+ /* Resize the window to fit industries list */
+ if (_industries_per_column > BASE_NB_PER_COLUMN) {
+ uint diff = ((_industries_per_column - BASE_NB_PER_COLUMN) * BASE_NB_PER_COLUMN) + 1;
+
+ this->height = this->height + diff;
+
+ Widget *wi = &this->widget[SM_WIDGET_LEGEND]; // label panel
+ wi->bottom = wi->bottom + diff;
+
+ wi = &this->widget[SM_WIDGET_BUTTONSPANEL]; // filler panel under smallmap buttons
+ wi->bottom = wi->bottom + diff - 1;
+
+ /* Change widget position
+ * - footer panel
+ * - enable all industry
+ * - disable all industry
+ * - resize window button
+ */
+ for (uint i = SM_WIDGET_BOTTOMPANEL; i <= SM_WIDGET_RESIZEBOX; i++) {
+ wi = &this->widget[i];
+ wi->top = wi->top + diff;
+ wi->bottom = wi->bottom + diff;
+ }
}
- /* number of lines */
- reps = (dpi->height - y + 1) / 2;
- if (reps > 0) {
- DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, _smallmap_draw_procs[type]);
- }
+ this->LowerWidget(_smallmap_type + SMT_OWNER);
+ this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, _smallmap_show_towns);
-skip_column:
- if (y == 0) {
- tile_y++;
- y++;
- ptr = blitter->MoveTo(ptr, 0, 1);
- } else {
- tile_x--;
- y--;
- ptr = blitter->MoveTo(ptr, 0, -1);
- }
- ptr = blitter->MoveTo(ptr, 2, 0);
- x += 2;
+ this->SmallMapCenterOnCurrentPos();
+ this->FindWindowPlacementAndResize(desc);
}
- /* draw vehicles? */
- if (type == SMT_CONTOUR || type == SMT_VEHICLES) {
- Vehicle *v;
- bool skip;
- byte color;
+ virtual void OnPaint()
+ {
+ const LegendAndColour *tbl;
+ int x, y, y_org;
+ uint diff;
+ DrawPixelInfo new_dpi;
+
+ /* Hide Enable all/Disable all buttons if is not industry type small map*/
+ this->SetWidgetHiddenState(SM_WIDGET_ENABLEINDUSTRIES, _smallmap_type != SMT_INDUSTRY);
+ this->SetWidgetHiddenState(SM_WIDGET_DISABLEINDUSTRIES, _smallmap_type != SMT_INDUSTRY);
- FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_EFFECT &&
- (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0) {
- /* Remap into flat coordinates. */
- Point pt = RemapCoords(
- v->x_pos / TILE_SIZE - WP(w, smallmap_d).scroll_x / TILE_SIZE, // divide each one separately because (a-b)/c != a/c-b/c in integer world
- v->y_pos / TILE_SIZE - WP(w, smallmap_d).scroll_y / TILE_SIZE, // dtto
- 0);
- x = pt.x;
- y = pt.y;
+ /* draw the window */
+ SetDParam(0, STR_00E5_CONTOURS + _smallmap_type);
+ DrawWindowWidgets(this);
+
+ tbl = _legend_table[_smallmap_type];
- /* Check if y is out of bounds? */
- y -= dpi->top;
- if (!IsInsideMM(y, 0, dpi->height)) continue;
+ /* difference in window size */
+ diff = (_industries_per_column > BASE_NB_PER_COLUMN) ? ((_industries_per_column - BASE_NB_PER_COLUMN) * BASE_NB_PER_COLUMN) + 1 : 0;
+
+ x = 4;
+ y_org = this->height - 44 - 11 - diff;
+ y = y_org;
- /* Default is to draw both pixels. */
- skip = false;
-
- /* Offset X coordinate */
- x -= WP(w, smallmap_d).subscroll + 3 + dpi->left;
+ for (;;) {
+ if (_smallmap_type == SMT_INDUSTRY) {
+ /* Industry name must be formated, since it's not in tiny font in the specs.
+ * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font.*/
+ SetDParam(0, tbl->legend);
+ assert(tbl->type < NUM_INDUSTRYTYPES);
+ SetDParam(1, _industry_counts[tbl->type]);
+ if (!tbl->show_on_map) {
+ /* Simply draw the string, not the black border of the legend color.
+ * This will enforce the idea of the disabled item */
+ DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_GREY);
+ } else {
+ DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_BLACK);
+ GfxFillRect(x, y + 1, x + 8, y + 5, 0); // outer border of the legend color
+ }
+ } else {
+ /* Anything that is not an industry is using normal process */
+ GfxFillRect(x, y + 1, x + 8, y + 5, 0);
+ DrawString(x + 11, y, tbl->legend, TC_FROMSTRING);
+ }
+ GfxFillRect(x + 1, y + 2, x + 7, y + 4, tbl->colour); // legend color
- if (x < 0) {
- /* if x+1 is 0, that means we're on the very left edge,
- * and should thus only draw a single pixel */
- if (++x != 0) continue;
- skip = true;
- } else if (x >= dpi->width - 1) {
- /* Check if we're at the very right edge, and if so draw only a single pixel */
- if (x != dpi->width - 1) continue;
- skip = true;
- }
+ tbl += 1;
+ y += 6;
- /* Calculate pointer to pixel and the color */
- color = (type == SMT_VEHICLES) ? _vehicle_type_colors[v->type] : 0xF;
-
- /* And draw either one or two pixels depending on clipping */
- blitter->SetPixel(dpi->dst_ptr, x, y, color);
- if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, color);
+ if (tbl->end) { // end of the list
+ break;
+ } else if (tbl->col_break) {
+ /* break asked, continue at top, 123 pixels (one "row") to the right */
+ x += 123;
+ y = y_org;
}
}
+
+ if (!FillDrawPixelInfo(&new_dpi, 3, 17, this->width - 28 + 22, this->height - 64 - 11 - diff)) return;
+
+ this->DrawSmallMap(&new_dpi, _smallmap_type, _smallmap_show_towns);
}
- if (show_towns) {
- const Town *t;
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case SM_WIDGET_MAP: { // Map window
+ /*
+ * XXX: scrolling with the left mouse button is done by subsequently
+ * clicking with the left mouse button; clicking once centers the
+ * large map at the selected point. So by unclicking the left mouse
+ * button here, it gets reclicked during the next inputloop, which
+ * would make it look like the mouse is being dragged, while it is
+ * actually being (virtually) clicked every inputloop.
+ */
+ _left_button_clicked = false;
+
+ Point pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
+ Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
+ w->viewport->dest_scrollpos_x = pt.x + ((_cursor.pos.x - this->left + 2) << 4) - (w->viewport->virtual_width >> 1);
+ w->viewport->dest_scrollpos_y = pt.y + ((_cursor.pos.y - this->top - 16) << 4) - (w->viewport->virtual_height >> 1);
+
+ this->SetDirty();
+ } break;
+
+ case SM_WIDGET_CONTOUR: // Show land contours
+ case SM_WIDGET_VEHICLES: // Show vehicles
+ case SM_WIDGET_INDUSTRIES: // Show industries
+ case SM_WIDGET_ROUTES: // Show transport routes
+ case SM_WIDGET_VEGETATION: // Show vegetation
+ case SM_WIDGET_OWNERS: // Show land owners
+ this->RaiseWidget(_smallmap_type + SM_WIDGET_CONTOUR);
+ _smallmap_type = widget - SM_WIDGET_CONTOUR;
+ this->LowerWidget(_smallmap_type + SM_WIDGET_CONTOUR);
+
+ this->SetDirty();
+ SndPlayFx(SND_15_BEEP);
+ break;
+
+ case SM_WIDGET_CENTERMAP: // Center the smallmap again
+ this->SmallMapCenterOnCurrentPos();
+
+ this->SetDirty();
+ SndPlayFx(SND_15_BEEP);
+ break;
+
+ case SM_WIDGET_TOGGLETOWNNAME: // Toggle town names
+ this->ToggleWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME);
+ _smallmap_show_towns = this->IsWidgetLowered(SM_WIDGET_TOGGLETOWNNAME);
+
+ this->SetDirty();
+ SndPlayFx(SND_15_BEEP);
+ break;
- FOR_ALL_TOWNS(t) {
- /* Remap the town coordinate */
- Point pt = RemapCoords(
- (int)(TileX(t->xy) * TILE_SIZE - WP(w, smallmap_d).scroll_x) / TILE_SIZE,
- (int)(TileY(t->xy) * TILE_SIZE - WP(w, smallmap_d).scroll_y) / TILE_SIZE,
- 0);
- x = pt.x - WP(w, smallmap_d).subscroll + 3 - (t->sign.width_2 >> 1);
- y = pt.y;
+ case SM_WIDGET_LEGEND: // Legend
+ /* if industry type small map*/
+ if (_smallmap_type == SMT_INDUSTRY) {
+ /* if click on industries label, find right industry type and enable/disable it */
+ Widget *wi = &this->widget[SM_WIDGET_LEGEND]; // label panel
+ uint column = (pt.x - 4) / 123;
+ uint line = (pt.y - wi->top - 2) / 6;
+ uint free = _smallmap_industry_count % 3;
+
+ if (column <= 3) {
+ /* check if click is on industry label*/
+ uint industry_pos = 0;
+ for (uint i = 0; i <= column; i++) {
+ uint diff = (free > 0) ? 1 : 0;
+ uint max_column_lines = _industries_per_column + diff;
+
+ if (i < column) industry_pos = industry_pos + _industries_per_column + diff;
- /* Check if the town sign is within bounds */
- if (x + t->sign.width_2 > dpi->left &&
- x < dpi->left + dpi->width &&
- y + 6 > dpi->top &&
- y < dpi->top + dpi->height) {
- /* And draw it. */
- SetDParam(0, t->index);
- DrawString(x, y, STR_2056, TC_WHITE);
- }
+ if (i == column && line <= max_column_lines - 1) {
+ industry_pos = industry_pos + line;
+ _legend_from_industries[industry_pos].show_on_map = !_legend_from_industries[industry_pos].show_on_map;
+ }
+ if( free > 0) free--;
+ }
+ }
+ /* Raise the two buttons "all", as we have done a specific choice */
+ this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
+ this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
+ this->SetDirty();
+ }
+ break;
+
+ case SM_WIDGET_ENABLEINDUSTRIES: // Enable all industries
+ for (int i = 0; i != _smallmap_industry_count; i++) {
+ _legend_from_industries[i].show_on_map = true;
+ }
+ /* toggle appeareance indicating the choice */
+ this->LowerWidget(SM_WIDGET_ENABLEINDUSTRIES);
+ this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
+ this->SetDirty();
+ break;
+
+ case SM_WIDGET_DISABLEINDUSTRIES: // disable all industries
+ for (int i = 0; i != _smallmap_industry_count; i++) {
+ _legend_from_industries[i].show_on_map = false;
+ }
+ /* toggle appeareance indicating the choice */
+ this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
+ this->LowerWidget(SM_WIDGET_DISABLEINDUSTRIES);
+ this->SetDirty();
+ break;
}
}
- /* Draw map indicators */
+ virtual void OnRightClick(Point pt, int widget)
{
- Point pt;
-
- /* Find main viewport. */
- vp = FindWindowById(WC_MAIN_WINDOW,0)->viewport;
-
- pt = RemapCoords(WP(w, smallmap_d).scroll_x, WP(w, smallmap_d).scroll_y, 0);
-
- x = vp->virtual_left - pt.x;
- y = vp->virtual_top - pt.y;
- x2 = (x + vp->virtual_width) / TILE_SIZE;
- y2 = (y + vp->virtual_height) / TILE_SIZE;
- x /= TILE_SIZE;
- y /= TILE_SIZE;
-
- x -= WP(w, smallmap_d).subscroll;
- x2 -= WP(w, smallmap_d).subscroll;
-
- DrawVertMapIndicator(x, y, x, y2);
- DrawVertMapIndicator(x2, y, x2, y2);
-
- DrawHorizMapIndicator(x, y, x2, y);
- DrawHorizMapIndicator(x, y2, x2, y2);
+ if (widget == SM_WIDGET_MAP) {
+ if (_scrolling_viewport) return;
+ _scrolling_viewport = true;
+ _cursor.delta.x = 0;
+ _cursor.delta.y = 0;
+ }
}
- _cur_dpi = old_dpi;
-}
-
-void SmallMapCenterOnCurrentPos(Window *w)
-{
- int x, y;
- ViewPort *vp;
- vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
- x = ((vp->virtual_width - (w->widget[SM_WIDGET_MAP].right - w->widget[SM_WIDGET_MAP].left) * TILE_SIZE) / 2 + vp->virtual_left) / 4;
- y = ((vp->virtual_height - (w->widget[SM_WIDGET_MAP].bottom - w->widget[SM_WIDGET_MAP].top ) * TILE_SIZE) / 2 + vp->virtual_top ) / 2 - TILE_SIZE * 2;
- WP(w, smallmap_d).scroll_x = (y - x) & ~0xF;
- WP(w, smallmap_d).scroll_y = (x + y) & ~0xF;
- w->SetDirty();
-}
-
-enum {
- BASE_NB_PER_COLUMN = 6,
-};
-
-static void SmallMapWindowProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- const LegendAndColour *tbl;
- int x, y, y_org;
- uint diff;
- DrawPixelInfo new_dpi;
-
- /* Hide Enable all/Disable all buttons if is not industry type small map*/
- w->SetWidgetHiddenState(SM_WIDGET_ENABLEINDUSTRIES, _smallmap_type != SMT_INDUSTRY);
- w->SetWidgetHiddenState(SM_WIDGET_DISABLEINDUSTRIES, _smallmap_type != SMT_INDUSTRY);
-
- /* draw the window */
- SetDParam(0, STR_00E5_CONTOURS + _smallmap_type);
- DrawWindowWidgets(w);
-
- tbl = _legend_table[_smallmap_type];
-
- /* difference in window size */
- diff = (_industries_per_column > BASE_NB_PER_COLUMN) ? ((_industries_per_column - BASE_NB_PER_COLUMN) * BASE_NB_PER_COLUMN) + 1 : 0;
-
- x = 4;
- y_org = w->height - 44 - 11 - diff;
- y = y_org;
+ virtual void OnTick()
+ {
+ /* update the window every now and then */
+ if ((++this->vscroll.pos & 0x1F) == 0) this->SetDirty();
+ }
- for (;;) {
+ virtual void OnScroll(Point delta)
+ {
+ _cursor.fix_at = true;
- if (_smallmap_type == SMT_INDUSTRY) {
- /* Industry name must be formated, since it's not in tiny font in the specs.
- * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font.*/
- SetDParam(0, tbl->legend);
- assert(tbl->type < NUM_INDUSTRYTYPES);
- SetDParam(1, _industry_counts[tbl->type]);
- if (!tbl->show_on_map) {
- /* Simply draw the string, not the black border of the legend color.
- * This will enforce the idea of the disabled item */
- DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_GREY);
- } else {
- DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_BLACK);
- GfxFillRect(x, y + 1, x + 8, y + 5, 0); // outer border of the legend color
- }
- } else {
- /* Anything that is not an industry is using normal process */
- GfxFillRect(x, y + 1, x + 8, y + 5, 0);
- DrawString(x + 11, y, tbl->legend, TC_FROMSTRING);
- }
- GfxFillRect(x + 1, y + 2, x + 7, y + 4, tbl->colour); // legend color
-
- tbl += 1;
- y += 6;
-
- if (tbl->end) { // end of the list
- break;
- } else if (tbl->col_break) {
- /* break asked, continue at top, 123 pixels (one "row") to the right */
- x += 123;
- y = y_org;
- }
- }
+ int x = this->scroll_x;
+ int y = this->scroll_y;
- if (!FillDrawPixelInfo(&new_dpi, 3, 17, w->width - 28 + 22, w->height - 64 - 11 - diff))
- return;
-
- DrawSmallMap(&new_dpi, w, _smallmap_type, _smallmap_show_towns);
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case SM_WIDGET_MAP: { // Map window
- Window *w2 = FindWindowById(WC_MAIN_WINDOW, 0);
- Point pt;
+ int sub = this->subscroll + delta.x;
- /*
- * XXX: scrolling with the left mouse button is done by subsequently
- * clicking with the left mouse button; clicking once centers the
- * large map at the selected point. So by unclicking the left mouse
- * button here, it gets reclicked during the next inputloop, which
- * would make it look like the mouse is being dragged, while it is
- * actually being (virtually) clicked every inputloop.
- */
- _left_button_clicked = false;
+ x -= (sub >> 2) << 4;
+ y += (sub >> 2) << 4;
+ sub &= 3;
- pt = RemapCoords(WP(w, smallmap_d).scroll_x, WP(w,smallmap_d).scroll_y, 0);
- w2->viewport->dest_scrollpos_x = pt.x + ((_cursor.pos.x - w->left + 2) << 4) - (w2->viewport->virtual_width >> 1);
- w2->viewport->dest_scrollpos_y = pt.y + ((_cursor.pos.y - w->top - 16) << 4) - (w2->viewport->virtual_height >> 1);
-
- w->SetDirty();
- } break;
-
- case SM_WIDGET_CONTOUR: // Show land contours
- case SM_WIDGET_VEHICLES: // Show vehicles
- case SM_WIDGET_INDUSTRIES: // Show industries
- case SM_WIDGET_ROUTES: // Show transport routes
- case SM_WIDGET_VEGETATION: // Show vegetation
- case SM_WIDGET_OWNERS: // Show land owners
- w->RaiseWidget(_smallmap_type + SM_WIDGET_CONTOUR);
- _smallmap_type = e->we.click.widget - SM_WIDGET_CONTOUR;
- w->LowerWidget(_smallmap_type + SM_WIDGET_CONTOUR);
+ x += (delta.y >> 1) << 4;
+ y += (delta.y >> 1) << 4;
- w->SetDirty();
- SndPlayFx(SND_15_BEEP);
- break;
-
- case SM_WIDGET_CENTERMAP: // Center the smallmap again
- SmallMapCenterOnCurrentPos(w);
-
- w->SetDirty();
- SndPlayFx(SND_15_BEEP);
- break;
-
- case SM_WIDGET_TOGGLETOWNNAME: // Toggle town names
- w->ToggleWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME);
- _smallmap_show_towns = w->IsWidgetLowered(SM_WIDGET_TOGGLETOWNNAME);
-
- w->SetDirty();
- SndPlayFx(SND_15_BEEP);
- break;
-
- case SM_WIDGET_LEGEND: // Legend
- /* if industry type small map*/
- if (_smallmap_type == SMT_INDUSTRY) {
- /* if click on industries label, find right industry type and enable/disable it */
- Widget *wi = &w->widget[SM_WIDGET_LEGEND]; // label panel
- uint column = (e->we.click.pt.x - 4) / 123;
- uint line = (e->we.click.pt.y - wi->top - 2) / 6;
- uint free = _smallmap_industry_count % 3;
-
- if (column <= 3) {
- /* check if click is on industry label*/
- uint industry_pos = 0;
- for (uint i = 0; i <= column; i++) {
- uint diff = (free > 0) ? 1 : 0;
- uint max_column_lines = _industries_per_column + diff;
-
- if (i < column) industry_pos = industry_pos + _industries_per_column + diff;
-
- if (i == column && line <= max_column_lines - 1) {
- industry_pos = industry_pos + line;
- _legend_from_industries[industry_pos].show_on_map = !_legend_from_industries[industry_pos].show_on_map;
- }
- if( free > 0) free--;
- }
- }
- /* Raise the two buttons "all", as we have done a specific choice */
- w->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
- w->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
- w->SetDirty();
- }
- break;
-
- case SM_WIDGET_ENABLEINDUSTRIES: // Enable all industries
- for (int i = 0; i != _smallmap_industry_count; i++) {
- _legend_from_industries[i].show_on_map = true;
- }
- /* toggle appeareance indicating the choice */
- w->LowerWidget(SM_WIDGET_ENABLEINDUSTRIES);
- w->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
- w->SetDirty();
- break;
-
- case SM_WIDGET_DISABLEINDUSTRIES: // disable all industries
- for (int i = 0; i != _smallmap_industry_count; i++) {
- _legend_from_industries[i].show_on_map = false;
- }
- /* toggle appeareance indicating the choice */
- w->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
- w->LowerWidget(SM_WIDGET_DISABLEINDUSTRIES);
- w->SetDirty();
- break;
- }
- break;
+ if (delta.y & 1) {
+ x += TILE_SIZE;
+ sub += 2;
+ if (sub > 3) {
+ sub -= 4;
+ x -= TILE_SIZE;
+ y += TILE_SIZE;
+ }
+ }
- case WE_RCLICK:
- if (e->we.click.widget == SM_WIDGET_MAP) {
- if (_scrolling_viewport) return;
- _scrolling_viewport = true;
- _cursor.delta.x = 0;
- _cursor.delta.y = 0;
- }
- break;
-
- case WE_TICK:
- /* update the window every now and then */
- if ((++w->vscroll.pos & 0x1F) == 0) w->SetDirty();
- break;
-
- case WE_SCROLL: {
- int x;
- int y;
- int sub;
- int hx;
- int hy;
- int hvx;
- int hvy;
-
- _cursor.fix_at = true;
-
- x = WP(w, smallmap_d).scroll_x;
- y = WP(w, smallmap_d).scroll_y;
-
- sub = WP(w, smallmap_d).subscroll + e->we.scroll.delta.x;
-
- x -= (sub >> 2) << 4;
- y += (sub >> 2) << 4;
- sub &= 3;
-
- x += (e->we.scroll.delta.y >> 1) << 4;
- y += (e->we.scroll.delta.y >> 1) << 4;
+ int hx = (this->widget[SM_WIDGET_MAP].right - this->widget[SM_WIDGET_MAP].left) / 2;
+ int hy = (this->widget[SM_WIDGET_MAP].bottom - this->widget[SM_WIDGET_MAP].top ) / 2;
+ int hvx = hx * -4 + hy * 8;
+ int hvy = hx * 4 + hy * 8;
+ if (x < -hvx) {
+ x = -hvx;
+ sub = 0;
+ }
+ if (x > (int)MapMaxX() * TILE_SIZE - hvx) {
+ x = MapMaxX() * TILE_SIZE - hvx;
+ sub = 0;
+ }
+ if (y < -hvy) {
+ y = -hvy;
+ sub = 0;
+ }
+ if (y > (int)MapMaxY() * TILE_SIZE - hvy) {
+ y = MapMaxY() * TILE_SIZE - hvy;
+ sub = 0;
+ }
- if (e->we.scroll.delta.y & 1) {
- x += TILE_SIZE;
- sub += 2;
- if (sub > 3) {
- sub -= 4;
- x -= TILE_SIZE;
- y += TILE_SIZE;
- }
- }
+ this->scroll_x = x;
+ this->scroll_y = y;
+ this->subscroll = sub;
- hx = (w->widget[SM_WIDGET_MAP].right - w->widget[SM_WIDGET_MAP].left) / 2;
- hy = (w->widget[SM_WIDGET_MAP].bottom - w->widget[SM_WIDGET_MAP].top ) / 2;
- hvx = hx * -4 + hy * 8;
- hvy = hx * 4 + hy * 8;
- if (x < -hvx) {
- x = -hvx;
- sub = 0;
- }
- if (x > (int)MapMaxX() * TILE_SIZE - hvx) {
- x = MapMaxX() * TILE_SIZE - hvx;
- sub = 0;
- }
- if (y < -hvy) {
- y = -hvy;
- sub = 0;
- }
- if (y > (int)MapMaxY() * TILE_SIZE - hvy) {
- y = MapMaxY() * TILE_SIZE - hvy;
- sub = 0;
- }
-
- WP(w, smallmap_d).scroll_x = x;
- WP(w, smallmap_d).scroll_y = y;
- WP(w, smallmap_d).subscroll = sub;
-
- w->SetDirty();
- } break;
+ this->SetDirty();
}
-}
+};
static const WindowDesc _smallmap_desc = {
WDP_AUTO, WDP_AUTO, 350, 214, 446, 314,
WC_SMALLMAP, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_smallmap_widgets,
- SmallMapWindowProc
+ NULL
};
void ShowSmallMap()
{
- Window *w;
-
- w = AllocateWindowDescFront(&_smallmap_desc, 0);
- if (w == NULL) return;
-
- /* Resize the window to fit industries list */
- if (_industries_per_column > BASE_NB_PER_COLUMN) {
- uint diff = ((_industries_per_column - BASE_NB_PER_COLUMN) * BASE_NB_PER_COLUMN) + 1;
-
- w->height = w->height + diff;
-
- Widget *wi = &w->widget[SM_WIDGET_LEGEND]; // label panel
- wi->bottom = wi->bottom + diff;
-
- wi = &w->widget[SM_WIDGET_BUTTONSPANEL]; // filler panel under smallmap buttons
- wi->bottom = wi->bottom + diff - 1;
-
- /* Change widget position
- * - footer panel
- * - enable all industry
- * - disable all industry
- * - resize window button
- */
- for (uint i = SM_WIDGET_BOTTOMPANEL; i <= SM_WIDGET_RESIZEBOX; i++) {
- wi = &w->widget[i];
- wi->top = wi->top + diff;
- wi->bottom = wi->bottom + diff;
- }
- }
-
- w->LowerWidget(_smallmap_type + SMT_OWNER);
- w->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, _smallmap_show_towns);
-
- SmallMapCenterOnCurrentPos(w);
+ AllocateWindowDescFront(&_smallmap_desc, 0);
}
/* Extra ViewPort Window Stuff */
@@ -1225,3 +1215,19 @@ void ShowExtraViewPortWindow(TileIndex t
w->viewport->dest_scrollpos_y = w->viewport->scrollpos_y;
}
}
+
+bool ScrollMainWindowTo(int x, int y, bool instant)
+{
+ bool res = ScrollWindowTo(x, y, FindWindowById(WC_MAIN_WINDOW, 0), instant);
+
+ /* If a user scrolls to a tile (via what way what so ever) and already is on
+ * that tile (e.g.: pressed twice), move the smallmap to that location,
+ * so you directly see where you are on the smallmap. */
+
+ if (res) return res;
+
+ SmallMapWindow *w = dynamic_cast(FindWindowById(WC_SMALLMAP, 0));
+ if (w != NULL) w->SmallMapCenterOnCurrentPos();
+
+ return res;
+}
diff --git a/src/viewport.cpp b/src/viewport.cpp
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -144,8 +144,6 @@ TileHighlightData _thd;
static TileInfo *_cur_ti;
bool _draw_bounding_boxes = false;
-extern void SmallMapCenterOnCurrentPos(Window *w);
-
static Point MapXYZToViewport(const ViewPort *vp, uint x, uint y, uint z)
{
Point p = RemapCoords(x, y, z);
@@ -2079,27 +2077,6 @@ bool ScrollWindowTo(int x , int y, Windo
return true;
}
-
-bool ScrollMainWindowTo(int x, int y, bool instant)
-{
- Window *w;
- bool res = ScrollWindowTo(x, y, FindWindowById(WC_MAIN_WINDOW, 0), instant);
-
- /* If a user scrolls to a tile (via what way what so ever) and already is on
- * that tile (e.g.: pressed twice), move the smallmap to that location,
- * so you directly see where you are on the smallmap. */
-
- if (res) return res;
-
- w = FindWindowById(WC_SMALLMAP, 0);
- if (w == NULL) return res;
-
- SmallMapCenterOnCurrentPos(w);
-
- return res;
-}
-
-
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
{
return ScrollMainWindowTo(TileX(tile) * TILE_SIZE + TILE_SIZE / 2, TileY(tile) * TILE_SIZE + TILE_SIZE / 2, instant);