diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 63f3c92..2c628df 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -557,6 +557,9 @@ class SmallMapWindow : public Window SD_LEGEND_MIN_HEIGHT = SD_LEGEND_ROW_HEIGHT * LEGEND_MIN_ROWS, }; + typedef std::map VehiclePositionMap; + VehiclePositionMap vehicles_on_map; + static SmallMapType map_type; static bool show_towns; @@ -568,7 +571,7 @@ class SmallMapWindow : public Window /** * zoom level of the smallmap. - * May be something between ZOOM_LVL_NORMAL and ZOOM_LVL_MAX. + * May be something between ZOOM_LVL_MIN and ZOOM_LVL_MAX. */ ZoomLevel zoom; @@ -685,14 +688,23 @@ class SmallMapWindow : public Window void DrawVehicles(DrawPixelInfo *dpi) { if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) { + VehiclePositionMap new_vehicles; Vehicle *v; FOR_ALL_VEHICLES(v) { if (v->type != VEH_EFFECT && (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0) { - DrawVehicle(dpi, v); + DrawVehicle(dpi, v, new_vehicles); } } + + if (this->zoom < ZOOM_LVL_NORMAL) { + if(this->refresh != FORCE_REFRESH && new_vehicles.size() != this->vehicles_on_map.size()) { + /* redraw the whole map if the vehicles have changed. This prevents artifacts. */ + this->refresh = FORCE_REFRESH; + } + std::swap(new_vehicles, this->vehicles_on_map); + } } } @@ -701,9 +713,13 @@ class SmallMapWindow : public Window * @param dpi the part of the smallmap to be drawn into * @param v the vehicle to be drawn */ - void DrawVehicle(DrawPixelInfo *dpi, Vehicle *v) + void DrawVehicle(DrawPixelInfo *dpi, Vehicle *v, VehiclePositionMap &new_vehicles) { Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); + int scale = 1; + if (this->zoom < ZOOM_LVL_NORMAL) { + scale = 1 << (ZOOM_LVL_NORMAL - this->zoom); + } /* Remap into flat coordinates. */ Point pt = RemapTileCoords(v->tile); @@ -711,15 +727,39 @@ class SmallMapWindow : public Window int x = pt.x - dpi->left; int y = pt.y - dpi->top; - byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : 0xF; + /* Check if rhombus is inside bounds */ + if ((x + 2 * scale < 0) || //left + (y + 2 * scale < 0) || //top + (x - 2 * scale >= dpi->width) || //right + (y - 2 * scale >= dpi->height)) { //bottom + return; + } - /* Draw vehicle */ - if (IsInsideMM(y, 0, dpi->height)) { - if (IsInsideMM(x, 0, dpi->width)) { - blitter->SetPixel(dpi->dst_ptr, x, y, colour); + if (this->zoom < ZOOM_LVL_NORMAL) { + if (this->refresh != FORCE_REFRESH) { + VehiclePositionMap::iterator i = this->vehicles_on_map.find(v->index); + if (i == vehicles_on_map.end() || i->second != v->tile) { + /* redraw the whole map if the vehicles have changed. This prevents artifacts. */ + this->refresh = FORCE_REFRESH; + } } - if (IsInsideMM(x + 1, 0, dpi->width)) { - blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour); + new_vehicles[v->index] = v->tile; + } + + byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : 0xF; + + /* Draw rhombus */ + for (int dy = 0; dy < scale; dy++) { + for (int dx = 0; dx < scale; dx++) { + pt = RemapCoords(-dx, -dy, 0); + if (IsInsideMM(y + pt.y, 0, dpi->height)) { + if (IsInsideMM(x + pt.x, 0, dpi->width)) { + blitter->SetPixel(dpi->dst_ptr, x + pt.x, y + pt.y, colour); + } + if (IsInsideMM(x + pt.x + 1, 0, dpi->width)) { + blitter->SetPixel(dpi->dst_ptr, x + pt.x + 1, y + pt.y, colour); + } + } } } } @@ -747,6 +787,7 @@ class SmallMapWindow : public Window } } } + } public: @@ -821,10 +862,15 @@ public: tile_y--; } - /* Beginning at ZOOM_LVL_OUT_2X the background is off by 1 pixel + /* The map background is off by a little less than one tile in y direction compared to vehicles and signs. + * I have no idea why this is the case. + * on zoom levels >= ZOOM_LVL_NORMAL this isn't visible as only full tiles can be shown. However, beginning + * at ZOOM_LVL_OUT_2X it's again off by 1 pixel */ dy = 0; - if (this->zoom > ZOOM_LVL_NORMAL) { + if (this->zoom < ZOOM_LVL_NORMAL) { + dy = UnScaleByZoomLower(2, this->zoom) - 2; + } else if (this->zoom > ZOOM_LVL_NORMAL) { dy = 1; } @@ -993,7 +1039,6 @@ public: this->SmallMapCenterOnCurrentPos(); this->FindWindowPlacementAndResize(desc); - this->SetWidgetDisabledState(SM_WIDGET_ZOOM_IN, true); this->SetWidgetsHiddenState(this->map_type != SMT_INDUSTRY, SM_WIDGET_ENABLEINDUSTRIES, SM_WIDGET_DISABLEINDUSTRIES, WIDGET_LIST_END); } diff --git a/src/zoom_type.h b/src/zoom_type.h index 4225dd4..a234aa7 100644 --- a/src/zoom_type.h +++ b/src/zoom_type.h @@ -9,6 +9,9 @@ enum ZoomLevel { /* Our possible zoom-levels */ + ZOOM_LVL_IN_8X, + ZOOM_LVL_IN_4X, + ZOOM_LVL_IN_2X, ZOOM_LVL_NORMAL, ZOOM_LVL_OUT_2X, ZOOM_LVL_OUT_4X, @@ -28,7 +31,7 @@ enum ZoomLevel { ZOOM_LVL_DETAIL = ZOOM_LVL_OUT_2X, ///< All zoomlevels with higher resolution or equal to this, will result in details on the screen, like road-work, ... /* min/max for all zoom levels */ - ZOOM_LVL_MIN = ZOOM_LVL_NORMAL, + ZOOM_LVL_MIN = ZOOM_LVL_IN_8X, ZOOM_LVL_MAX = ZOOM_LVL_OUT_8X, ZOOM_LVL_COUNT = ZOOM_LVL_MAX + 1 - ZOOM_LVL_MIN,